Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

VBFAQ - Альтернативный F.A.Q. по языку


Базовая конференция FidoNet носит имя Ru.Visual.Basic и доступна на news серверах с префиксом Fido7.
Дата последнего обновления: Jun 10, 2000

© Автор ряда материалов и составитель: Александр Щербаков, sanqy@mtu-net.ru, sanqy@forecast.ru.
Все материалы данного VBFAQ, по отдельности, могут свободно использоваться в оригинальном или видоизмененном виде как в коммерческих, так и некоммерческих целях. VBFAQ в том виде, как он есть, может использоваться только в некоммерческих целях. Коммерческое использование VBFAQ, допустимо только с письменного согласия составителя и авторов данного документа.

Содержание

  1. Справка по среде (IDE) и все, что с ней связано.
    1. "Я купил 1 диск с VB6. Вызываю хелп, ругаетца на MSDN! Плис, дайте этот MSDN скачать."
    2. Дополнительные сведения о параметрах Setup Wizard (setup.lst).
    3. Отлаживаю код и приходится часто "прыгать" по коду модуля. Можно ли упростить этот процесс?
  2. Начальные сведения по языку VisualBasic.
    1. "Как засyнyть MSVBVM?0.DLL в экзешник?"
    2. Как правильно реализовать стиль Wizard?
    3. Что такое модули, и зачем они нужны?
    4. Что такое классы и с чем их едят?
  3. Использование наиболее употребимых контролов VisualBasic.
    1. Использование WinSock.ocx.
  4. Функции Win32API.
    1. Как сделать окно повеpх всех?
    2. "А как засyнyть пpогpаммy тyды к часикам?"
    3. Как перевести текст из DOS кодировки в WIN и наоборот?
    4. Программное переключение клавиатуры RUS/LAT.
    5. Перетаскивание формы мышкой не за заголовок.
    6. Как все же вытащить ассоциированную иконку?
    7. Можно ли на VB создать консольное приложение и если да, то как?
    8. Как создать меню с картинками?
    9. Как побороть глюк всплывающего меню, вызываемого по клику из трея?
    10. Как сделать окно неправильной формы?
    11. Как привязать программу к компьютеру?
    12. Получить изображение экрана.
    13. Как открыть дверцу (Tray) CD-Rom программно?
    14. Каким образом можно засюспендить (suspend) компьютер?
  5. Использование внешних библиотек и дополнительных контролов.
    1. Как можно прочитать данные с порта или записать данные в порт?
  6. Базы данных.
    1. Как работать с mdb базой, расположенной на Read/Only диске (CD-Rom)?

A. Справка по среде (IDE) и все, что с ней связано.

A1 "Я купил 1 диск с VB6. Вызываю хелп, ругаетца на MSDN! Плис, дайте этот MSDN скачать."

MSDN это не примочка для просмотра хелпа. Это и есть сам хелп. Поставляется на 3-х CD. Но желающие могут их утянуть с http://msdn.microsoft.com. ;)

Igor Kudryashov:
ХЕЛП ОТ VISUAL BASIC 6, КАК И ОТ ВСЕХ ОСТАЛЬHЫХ ПРОГРАММ, ВХОДЯЩИХ В СОСТАВ VISUAL STUDIO 98, HАХОДИТСЯ В MSDN, КОТОРЫЙ ЕСТЬ HА 4-ОМ И 5-ОМ ДИСКАХ VISUAL STUDIO. В КОМПЛЕКТ ДИСТРИБУТИВА ЛЮБОГО ПРОДУКТА VS, ПРОДАВАЕМОГО ОТДЕЛЬHО ВХОДЯТ ДВА ДИСКА MSDN. ЕСЛИ ВЫ ПРИОБРЕЛИ VB6 HА ОДHОМ ДИСКЕ, ДА ЕЩЕ С КУЧЕЙ ПРИПАМПАСОВ К HЕМУ HА ТОМ ЖЕ ДИСКЕ, ТО HА ПОМОЩЬ ("ХЕЛП") HЕ РАССЧИТЫВАЙТЕ. ТЕПЕРЬ ВАМ СЛЕДУЕТ ДОКУПИТЬ MSDN (СЕЙЧАС В ПРОДАЖЕ ПОЯВИЛСЯ MSDN 2000 HА ТРЕХ ДИСКАХ). Hу и конечно всегда можно скачать MSDN нахаляву с сайта MS. Сколько это будет Гб ты уже наверное догадался. :))

Вернуться к содержанию.

A2 Дополнительные сведения о параметрах Setup Wizard (setup.lst).

Artem Prohorov:
Откpываешь свой файл setup.lst, находишь pаздел [Setup] и добавляешь ключик ForceUseDefDir = 1, после чего установить приложение в другой фолдер будет невозможно. Чтобы изменить пyть к пpиложению, меняй стpокy DefaultDir.
Описание ключей я беpy из книги Visual Basic 6.0 Рyководство для пpофессионалов, сеpия Мастеp, Microsoft Press. Значит должны быть описанны и в MSDN. Создавать дефолтную группу нyжно пpи помощи секции [IconGroups] файла setup.lst таким вот обpазом:

   [IconGroups]
   Group0=MyTestEXE
   Group1=MyGroupNumber1

   [MyTestExe]
   Icon1=my.exe
   Title1=MyTestExe

   [MyGroupNumber1]
   Icon1=ReadMe.txt
   Title1=ReadMe
   Icon2=my.hlp
   Title2=Help

Вернуться к содержанию.

A3 Отлаживаю код и приходится часто "прыгать" по коду модуля. Можно ли упростить этот процесс?

Конечно! Вопервых VB позволяет Split окон модулей. Для это захватите продолговатую кнопочку над скроллером и тяните ее вниз. Окно будет разбито на 2 половинки, в каждой из которых можно работать с кодом. Чтобы восстановить "статус-кво", перетащите разделительную полоску на самый верх.
Другим, не менее удобным способом, является использование bookmark. Нажмите правой мышиной кнопкой в любом месте панелей VB и выберите Edit. У Вас появится новая панель, на которой будут видны 4 синих флажка. Один из них позволяет ставить/убирать метки в тексте (букмарки), два других перемещаться между букмарками и четвертый флажок убирает все букмарки.

Вернуться к содержанию.


B. Начальные сведения по языку VisualBasic.

B1 "Как засyнyть MSVBVM?0.DLL в экзешник?"

Ответ на этот вопpос и подобные емy - никак.
Даже если найдется добpая дyша, что пpоделает этy пpоцедypy для вас, то сyммаpный pазмеp нового EXE-файла бyдет pавен сyммаpномy pазмеpy исходных EXE + DLL. Чyдес не бывает! Конечно, кто-то скажет, дескать в Cи это тpебование не выполняется. Это не так. Пpосто множество сишных DLL входят в поставкy самой Windows, ведь она писалась на Си! А если на минyткy пpедставить, что Windows создавалась бы на VB? Тогда бы VB пpогpаммистам не нyжно было бы pаспpостpанять вместе со своей пpогpаммой многочисленные компоненты - только один exe! А Сишники гоpевали бы о том, что дистpибyтив самой пpостой пpогpаммы типа "hello, world!" на Си тянет на многие сотни килобайт. Вообще, pазделение на компоненты (dll/ocx) благо, а не зло. Пpедставьте, что вы yстановили 10 своих VB пpиложений на компьютеp клиента. Если каждое пpиложение pазмеpом 100кб и использyет только MSVBVM50.DLL pазмеpом 1.3Mb, то все они займyт на винчестеpе (100кб x 10 + 1300кб) 2.3Mb. Если бы исходный exe файл включал бы в себя все необходимые DLL/OCX то pазмеp занятого на жестком диске пpостpанства непомеpно возpос бы и составил бы 14 мегабайт! (нетpyдно подсчитать, из pассчета 1 комплекта = 1.4мб (100кб + 1.3мб)).

Вернуться к содержанию.

B2 Как правильно реализовать стиль Wizard?

Как правильно реализовать стиль визарда? Это где кнопочки Далее и Назад? Я делаю несколько окон по числу шагов, но постоянно лезут глюки. Например, при перетаскивании верхнего окна, под ним оказываются другие...
Вообще, гораздо безгеморройнее реализовать визарда на контролах, являющихся контейнерами. Например, фрейм или пикчебокс. Правда, использовать пикчебокс не советую, ибо он будет ловить фокусы, портя интерфейс. А у фрейма надо бордюр воткнуть в None, дабы он не мешался. Во время дизайна, растяните окно и разместите фреймы так, чтобы они все были видны. Когда интерфейс будет доделан, разместите фреймы один над другим.
Теперь о коде. В нем нет ничего сложного. Но после N-ного визарда, я плюнул и решил написать классик, дабы по многу раз не набивать один и тот же набивший оскомину код. Этот классик и небольшой примерчик предлагаю Вам. Проект лежит в архиве WizardStyle и там же находится класс Frames.cls. Использование класса видно на примере и по небольшому описанию в самом классе. Я лишь хочу акцентировать Ваше внимание на ряде тонкостей.
Используйте только массив контролов (фреймов, пикчебоксов или других контейнеров). Работать не с массивом (Frame1, Frame2, Frame3...) класс не может и, вообще-то, не должен.
Метод HideFrames был введен сознательно. Дело в том, что во время дизайна Вы можете оставить самым верхним любой фрейм, а не только с индексом 0. Так как свойство Frame устанавливается в 0 после визуализации формы, то возможно некоторое мелькание фреймов. HideFrames позволяет избежать этого.
Ивенты. Зачем нужны аж 3 ивента, спросите Вы? Опять же это потребность выкристаллизовалась на практике.
Ивент BeforeLoad удобно использовать для проверки валидности введенных данных, и запрещения изменений фрейма, если данные некорректны. Кроме того этот ивент как нельзя кстати подходит для инициализации контролов и т.п., перед тем как страница содержащая эти контролы будет визуализирована.
Ивент AfterLoad в основном нужен для длительных операций. Например, Вы создали визарда для проверки валидности Вашей базы данных. Если проверку проводить в ивенте BeforeLoad, то пользователь столкнется с тем, что после нажатия на кнопку Далее программа "замерзла" или "зависла". Наличие ивента AfterLoad позволяет избежать этого. Вы можете на странице разместить прогрессбар и в ивенте AfterLoad его менять синхронно с проверкой базы данных.
И, наконец, ивент OverLoad. Когда Вы нажимаете кнопку Назад или Далее и свойство Frame устнавливает несуществующую страницу, то возникает этот ивент, который позволяет нормально завершить программу, или "закольцевать" ее, как, например, это сделано в WinZip, когда с последней страницы, посредством кнопки Повторить, Вы переходите на первую страницу визарда.

Вернуться к содержанию.

B3 Что такое модули, и зачем они нужны?

Что такое модули? Вообще, существует 3 типа модуля:
- модуль формы;
- просто модуль;
- модуль класса.
С модулем формы обычно знакомятся делая первые шаги в программировании на VB. Упрощенно говоря, модуль формы это то окно в котором вы описываете реакцию формы на действия с ней.
Нас же интересует простой модуль (в дальнейшем просто модуль). Такой модуль может содержать только код и добавляется в проект кнопкой, изображенной на рисунке или через меню Project|Add Module.
Так зачем нам модули? Модули нужны в следующих случаях:
1. Если Вы хотите объявить глобальную переменную, т.е. переменную, видимую во всех уголках Вашего приложения, то без модуля не обойтись:

   Public MyVar As Integer
Мне кто-то возразит, дескать, а что мешает тоже самое сделать в модуле формы? Никто не мешает. ;-) Но! Вопервых при обращении к Вашей переменной придется указывать имя объекта (в данном случае Form1), а именно так:
   Form1.MyVar = 5
Во-вторых, если вы порождаете копии формы:
   Dim frmX(1) As Form1
   Set frmX(0) = New Form1
   Set frmX(1) = New Form1
   Load frmX(0)
   Load frmX(1)
   frmX(0).Visible = True
   frmX(1).Visible = True
То каждая копия будет иметь свою переменную: frmX(0).MyVar и frm(1).MyVar. Более того, изменение одной переменной никак не скажется на другой.
2. Довольно часто модули формы оказываются перегруженными кодом и продираться сквозь такие дебри весьма неудобно и непроизводительно. В этом случае, полезно, ряд процедур выносить в модули, оставляя в модулях формы только небольшой код, жестко привязанный к самой форме (скажем, реакция на ивенты и т.д.).
3. Декларации функций API или просто внешних функций, так же помещают в модули. Конечно, декларацию с префиксом Private можно включить и в модуль формы, но... Часто АПИшная функция используется в разных частях приложения. Так зачем же ее объявлять несколько раз, когда проще объявить 1 раз? А кроме того, автор несколько раз сталкивался с таким странным эффектом, когда функция API, задекларированная в модуле формы, либо вообще не вызывается, либо работает как-то не так. Так зачем лишние сложности, если есть обычные модули?
4. И самый убойный аргумент. ;) Очень часто большие проекты стартуют не с модуля формы, а с функции Main. Объявить такую функцию можно только в модуле. И только в этом случае она будет нормально работать:
   Public Sub Main()
      Form1.Show
   End Sub

Вернуться к содержанию.

B3 Что такое классы и с чем их едят?

Тем эта столь обширна и затрагивает так много областей программирования, что ей место не в кратеньком FAQ'е, а в обстоятельной книжке. Но я попробую совместить несовместимое, и надеюсь, гуру не будут в обиде, если я опущу частности и то, что мне показалось неважным.
Что такое класс? Это совокупность методов, свойств и событий, которые образуют целостный объект.
А теперь попроще. Объект - наручные часы. Методы предназначены для установки времени на часах, установки будильника и т.д. Свойства, в нашем случае, определяют цвет корпуса, вид индикатора и т.д. Звук будильника является событием и позволяет провести определенные действия (например, снять молоко с плиты) в заданное время. Чтобы получить доступ к свойствам, методам и событиям объекта (часов), необходимо создать указатель на него, или инстанс. Если класс называется Clock, то создание экземпляра класса (инстанса) будет выглядеть так:

   Dim clk As Clock
   Set clk = New Clock
При необходимости можно создать несколько экземпляров одного и того же класса, и все эти экземпляры будут работать независимо друг от друга. Ну а теперь, чтобы вызывать метод или обратится к свойству класса, пишем:
   'вызовем метод установки времени
      clk.SetTime "13:56"
   'а теперь изменим свойство "Цвет корпуса"
      clk.Color = "Gold"
   'или увеличим свойство "Цена" на 1000 баксов ;-)
      clk.Price = clk.Price + 1000
А теперь самое сложное: создание классов. Начнем с азов.

1. Добавление модуля класса в проект.
Добавить модуль класса (часто его называют классовым модулем) можно посредством меню Project|Add Class Module или же кнопки, показанной на рисунке. Далее, назовите Ваш новоиспеченный класс. Поскольку через данную статью красной нитью проходит пример с часами, то так и назовем первый классовый модуль: Clock.

2. Область видимости процедур, свойств, переменных: Private, Public.
Очень часто, создавая переменные или процедуры приходится решать вопрос: можно ли будет их использовать вне модуля, или они необходимы только самому модулю. В первом случае такие процедуры или переменные объявляются с префиксом Public, а во втором случае с префиксом Private. Префикс Public является умолчательным и хотя его можно опускать, я рекомендую этого не делать. Добавьте в проект простой, не классовый, модуль и наберите в нем:
   'эта переменная видна снаружи модуля
      Public MyFirstVar As Integer
   'а эта переменная является приватной, и не видна вне модуля
      Private MySecondVar as Integer
Создайте в том же модуле процедуру CheckVar и обратитесь из нее к этим двум переменным:
   Public Sub CheckVar()
      MyFirstVar = 5
      MySecondVar = 7
   End Sub
Это удается без труда. А теперь, обратимся из модуля формы (он по умолчанию уже входит в проект) к созданным переменным. Как видим, вторая переменная не существует для всего мира ;) и доступна только в модуле, ее породившем. Попробуйте самостоятельно создать публичную и приватную процедуры и обратится к ним из модуля и из модуля формы.

3. Методы.
Методы это уже знакомые Вам процедуры (sub) и функции (function). Метод может иметь аргументы, а может не иметь их. Если метод построен на основе функции, то он способен возвращать значения. Создадим метод установки времени на наших часах и метод, возврщающий информацию о состоянии батарейки питания. Для этого в модуле класса напишем:
   Private m_Time As String   'переменная для хранения времени

   'публичный метод установки времени
   Public Sub SetTime(a_Time As String)
      'запомним значение
         m_Time = a_Time

      'произведем какие-то действия
         . . .

   End Sub

   'публичный метод, возвращающий напряжение батарейки питания
   Public Function GetPowerState () As Single
      'определим напряжение питания батарейки
         . . .
         BatteryVoltage = 1.48   'просто эмуляция работы некоего кода

      'возвратим значение
         GetPowerState = BatteryVoltage

   End Function
Создав инстанс класса (как было показано в начале статьи), обращаемся к новоиспеченным методам:
      Dim sTime As String

   'установим время
      sTime = InputBox ("Введите текущее время:", "Часики", "18:16")
      clk.SetTime sTime

   'определим состояние батарей
      MsgBox clk.GetPowerState()     'в окне будет напечатано 1.48
4. Свойства.
Условно говоря, свойство очень условно можно представить как пара состоящая из функции и процедуры с одним и тем же именем. При обращении к свойству вызывается функция, при изменении - процедура. Если отойти от условностей, то для создания свойств существует ключевое слово Properties с суффиксом Get для получения значения и с суффиксом Let или Set (для объектов) для установки значения. Вообще, свойство чем то похоже на объявленную публичную переменную. С тем лишь отличием, что изменение значения такой переменной нельзя отследить, как и нельзя отследить обращения к этой переменной. Свойства же позволяют это реализовать.
И всетаки, зачем нужны свойства? Почему бы вместо них не обойтись знакомыми процедурами и функциями? Предположим, наш класс должен иметь возможность выдавать стоимость часов и позволять эту стоимость изменять. Реализовать это проще простого:
   Public Price As Single
Тогда обращение к этой переменной извне выглядит так:
   clk.Price = 500    'установить стоимость часов
   MsgBox clk.Price   'выдать стоимость часов
Поставим задачу. Пользователь не должен иметь возможности установить цену ниже 150 и выше 800 долларов. Переменная с этим справиться неспособна. Берем на помощь процедуры и функции:
   Private m_Price As Single

   'процедура получения цены
   Public Function GetPrice() As Single
      GetPrice = m_Price
   End Function

   'процедура установки цены
   Public Sub SetPrice(a_Price As Single)
      If a_Price <= 800 And a_Price >= 150 Then m_Price = a_Price
   End Sub
Можно так написать? Можно. Все будет работать, но возникает ощущение некоей громоздкости, нерациональности:
   clk.SetPrice 450      'установить стоимость часов
   MsgBox clk.GetPrice   'выдать стоимость часов
И тут на помощь приходят свойства:
   Private m_Price As Single

   'свойство получения цены
   Public Property Get Price() As Single
      Price = m_Price
   End Property

   'свойство установки цены
   Public Property Let Price(ByVal a_Price As Single)
      If a_Price <= 800 And a_Price >= 150 Then m_Price = a_Price
   End Property
Обращение к свойству выглядит так:
   clk.Price = 500    'установить стоимость часов
   MsgBox clk.Price   'выдать стоимость часов
Не правда, ли похоже на обращение к переменной?
Последнее, что нужно знать о свойствах. Вы можете создавать свойство, состоящее только из Property Get или Property Let (Property Set). В первом случае свойство будет только для чтения, т.е. неподдающимся для изменения, а во втором случае вы сможете установить свойство, но не прочитать его.

5. События.
События (Events, ивенты) позволяют строить асинхронные модели, когда объект формирует и выстреливает какое-либо сообщение. Например, Вы установили время срабатывания будильника для наших часов. В заданный час будильник сработает, но как объект об этом сообщит? Можно, конечно, завести флажок и взводить его, и при этом по таймеру извне класса постоянно проверять его. Но такой путь нерационален и ведет к лишним затратам. И тут на помощь приходят события.
Итак, создадим новый ивент в нашем классе Clock:
   'декларируем публичный ивент
   Public Event Alarm(Melody As String)

   'некая приватная процедура, генерирующая ивент
   Private Sub GenerateAlarm()
      'некоторые действия
         . . .

      'выстреливаем ивент
         RaiseEvent Alarm("My little star.")

   End Sub
Для того, чтобы иметь возможность получать ивенты, внесем некоторые изменения в код создания экземпляра класса. Для этого воспользуемся новым ключевым словом WithEvents:
   Dim WithEvents clk As Clock
   Set clk = New Clock
Если теперь в окне модуля, где создавался инстанс, раскрыть левый комбобокс, то в списке объектов окажется слово clk. Установив его, в списке ивентов правого комбобокса найдем ивент Alarm:
   Private Sub clk_Alarm(Melody As String)

   End Sub
Всякий раз, когда будет выстреливаться ивент Alarm, управление будет передаваться на этот участок кода, в котором можно выводить окно или играть подходящий wav файл.

А теперь перейдем от теории к практике и поставим новую задачу. Предположим, Вы работаете в банке и Ваш работодатель заказал Вам написание управляющей программы для банкомата. Опустим все малозначащие детали и сформулируем требования к программе:
  1. Программа будет исполняться на банкоматах фирмы MicroSo, представляющие из себя обычные компьютеры с процессором Celeron, работающие под управлением OS Windows 98.
  2. Все что не упоминается в требованиях - реализуется хардверно и нас не должно заботить.
  3. После опускания клиентом кредитной карточки и нажатия кнопки, банкомат должен осуществить процедуру соединения с банком по телефонной сети. Соединение может не удасться.
  4. Если соединение прошло успешно, вывести клиенту состояние его счета.
  5. Предоставить клиенту возможность изменить счет, как в большую, так и в меньшую сторону. После этого провести транзакцию с банком.
  6. В конце работы клиент нажимает кнопку, заканчивается сеанс, происходит рассоединение с банком и клиент получает назад свою карточку.
Подойдем к этой задаче вооружившись знаниями о классах. Для этого разнесем интерфейс программы и код, ведающий обработкой данных. Последний поместим в класс.
Создадим новый проект и назовем его CreditCard. Добавим к проекту класс CCard. Этот класс будет ведать работой с банком. Управлять классом будет форма, названная winCard. Подобное разделение на независмые блоки полезно тем, что изменяя интерфейс Вы не трогаете класс, ведающий обработкой данных. А в случае изменения способа обмена с банком можно легко заменить класс на другой, не трогая интерфейс, столь полюбившийся клиентам. ;) Может в крошечных программах это и не так важно, но в больших проектах несоблюдение этого простого правила способно неимоверно усложнить работу программисту. Ради небольших правок, он будет вынужден переписывать сотни строк кода. Поэтому, лучше с самого начала учиться писать переносимые программы, строить их из независимых друг от друга кубиков. Тогда изъятие или изменение одного кубика не приведет к развалу всего здания проекта.
Для начала разберемся с классом. Он должен содержать метод Connect подключения к серверу банка и метод Disconnect отключения от сервера. Метод Connect должен возвращать True в случае успеха и False если соединение не прошло. Свойство Account возвращает сумму в банке, на счету клиента. Для изменения остатка на счету, служит уже другой метод Change. В случае успеха метод возвращает True и если транзакция пройти не может (со счета снимают больше, чем он содержит) - False.
К интерфейсу нет особых требований. Он должен обеспечивать подключение и отключение клиента (2 кнопки), предоставлять клиенту информацию о состоянии его счета (поле Label) и позволять клиенту изменить сумму на счету (поле TextBox и кнопка). Вы можете изменить интерфейс как Вам заблагорассудится, но это не должно отразиться на работоспособности программы.
А теперь, зная задачу, попробуйте самостоятельно ее выполнить.
Для тех, кто не до конца понял объяснений данной статьи, работающий пример проекта находится в архиве: CreditCard. Попробуйте разобрать его, понять как он работает и устранить те глюки, которые я специально оставил. ;-)

Вернуться к содержанию.


C. Использование наиболее употребимых контролов VisualBasic.

C1 Использование WinSock.ocx.

Пример с описанием находится в архиве WinSock. Для работы проекта Ваш VB должен иметь компонент Microsoft WinSock Control.
Загрузите проект WinSock.vbp из каталога WinSock. В проект входят две формы: клиент и сервер. Клиент соединяется с сервером используя протокол TCP/IP и отсылает ему число из верхнего текстбокса (сумма в USD). Сервер получает число, умножает его на число из своего текстбокса (курс валюты) и возвращает результат клиенту, который отображает его в нижнем текстбоксе (сумма в рублях). Код обильно комментирован, и надеюсь вопросов не вызовет.
В качестве следующего шага, на одном компьютере загрузите проект Server.vbp из архива WinSock\Server, а на другом компьютере проект Client.vbp из каталога WinSock\Client. Если сеть настроена правильно, и вы верно указываете имя/адрес сервера, то пример заработает. Можно на разных компьютерах запускать и скомпайленные exe файлы, но в этом случае Вы не будете иметь возможности отследить в динамике работу примера.
И о плохом. ;-)
В примере опущен код, который отвечает за перехват ошибок, неизбежно возникающих при связи. Этот код Вы без труда напишете сами, используя ивент Error винсока.
И второе. При пересылке значительных объемов информации, например файла на 100Кб, он будет разбиваться на части и приниматься винсоком кусочками. Поэтому, Вы должны проверять был ли получен весь файл или нужно продолжить его прием. Самый простой путь - перед пересылкой файла удаленному винсоку отсылать заголовочек, в котором указывать имя передаваемого файла, его размер, дату и т.д.

Вернуться к содержанию.


Функции Win32API.

D1 Как сделать окно повеpх всех?

Смотpите фyнкцию API SetWindowPos.
Пpимеp использования данной фyнкции, для pазмещения окна OnTop пpедставлен в архиве TopMost.

Вернуться к содержанию.

D2 "А как засyнyть пpогpаммy тyды к часикам?"

Смотpите фyнкцию API Shell_NotifyIcon.
Поймите, чисто физически невозможно "засyнyть" пpогpаммy в тpей. Это тоже самое, как поместить ваш любимый меpседес-600 междy pамами оконного стекла! Гpамотно сфоpмyлиpованный вопpос звyчит так: "Как поместить ИКОHКУ в системный тpей (system tray)". Подробный пример находится в архиве TrayIcon. Там же лежит класс для работы с треем - TrayIcon.cls.

Вернуться к содержанию.

D3 Как перевести текст из DOS кодировки в WIN и наоборот?

Можно ручками, создав таблицу перевода. Сам так делал, сложностей нет. А можно воспользоваться готовыми АПИшными функциями OemToChar и CharToOem.

Peter Pan:

   Public Declare Function OemToChar Lib "user32" Alias "OemToCharA" _
          (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
пишешь вот это, потом вызываешь как
   Dim l_lReturn as Long, l_sSource as String, l_sDestination as String
   l_lReturn = oemtochar(l_sSource, l_sDestination)

От себя лишь добавлю, что есть декларация для CharToOem выглялдит так:

   Declare Function CharToOem Lib "user32" Alias "CharToOemA" _
           (ByVal lpszSrc As String, ByVal lpszDst As String) As Long

Вернуться к содержанию.

D4 Программное переключение клавиатуры RUS/LAT.

Soleiman Mostamandy:

   ' Декларация функций и констант АПИ
   Declare Function ActivateKeyboardLayout Lib "user32" _
           (ByVal HKL As Long, ByVal flags As Long) As Long
   Public Const kb_lay_ru As Long = 68748313
   Public Const kb_lay_en As Long = 67699721
       
   ' Переключить на русский язык
   x = ActivateKeyboardLayout&(kb_lay_ru, 0)

   ' Переключить на английский язык
   x = ActivateKeyboardLayout&(kb_lay_en, 0)

Вернуться к содержанию.

D5 Перетаскивание формы мышкой не за заголовок.

Для этого используются функции API ReleaseCapture и SendMessage.
Пример на эту тему находится в архиве MoveWindow.

Вернуться к содержанию.

D6 Как все же вытащить ассоциированную иконку?

Arkadiy Olovyannikov:

   Option Explicit

   Private Declare Function ExtractAssociatedIcon Lib "shell32.dll" Alias _
           "ExtractAssociatedIconA" (ByVal hInst As Long, _
           ByVal lpIconPath As String, lpiIcon As Long) As Long
   Private Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, _
           ByVal x As Long, ByVal y As Long, ByVal hIcon As Long) As Long
   Private Declare Function DestroyIcon Lib "user32" _
           (ByVal hIcon As Long) As Long

   Dim sPath As String, hIcon As Long, nIcon As Long
   sPath = путь к файлу
   hIcon = ExtractAssociatedIcon(App.hInstance, sPath, nIcon)
   DrawIcon Picture1.hdc, 0&, 0&, hIcon
   DestroyIcon hIcon
А можно использовать и SHGetFileInfo - она две иконки дает - большую и маленькую.

Вернуться к содержанию.

D7 Можно ли на VB создать консольное приложение и если да, то как?

Используя все тот же API. ;) Например, AllocConsole, ReadConsole и т.д.
Пример находится в архиве Console.

Вернуться к содержанию.

D8 Как создать меню с картинками?

Лобовая атака с применением API функции SetMenuItemBitmaps не пройдет. Картинки в меню получаются иных цветов, нежели в исходной битмапе и это связано с особенностями реализации этой функции. Дабы избежать игры цвета, нужно с нуля, через АПИ создавать меню, что неудобно.
Примеры, что были мне присланы, реализуют другой подход, который заключается в получении hDC (хендл контекста устройства) пункта меню и перерисовывании его на лету средствами АПИ. Этот путь позволяет использовать уже готовое меню, созданное в IDE, но имеет существенный недостаток - использование сабклассинга. В готовом EXE/DLL этот недостаток непринципиален, но на стадии отладки программы способен попортить немало крови падениями VB IDE. Дабы избежать этого, никогда не завершайте работу программы нажатием на кнопку End в IDE! Используйте кнопку [x] окна, в ивенте Form_[Query]Unload которого, находится код возвращающий указатель на старый обработчик.
Примеры находятся в архивах BitmapMenu1 и BitmapMenu2. В обоих случаях реализуется примерно один и тот же механизм, но реализованный разными путями. Первый пример, несмотря на невзрачность, позволяет использовать иконки и битмапы любого размера, не только 16x16. Внешний вид второго примера более аккуратен, но без его переделки нельзя использовать битмапы, размер которых отличен от 16x16.

Вернуться к содержанию.

D9 Как побороть глюк всплывающего меню, вызываемого по клику из трея?

Вопpос: почему после вывода окна меню из subj, пpи помощи PopupMenu, не могу никак сбpосить это окно без выбоpа элемента меню? Кто-нибудь с этим сталкивался?
PRB: Menus for Notification Icons Don't Work Correctly

Article ID: Q135788

SYMPTOMS
When you display a context menu for a Notify Icon (see Shell_NotifyIcon), clicking anywhere besides the menu or the window that created the menu (if it is visible) doesn't cause the menu to disappear. When this behavior is corrected, the second time this menu is displayed, it displays and then immediately disappears.

RESOLUTION
To correct the first behavior, you need to make the current window the foreground window before calling TrackPopupMenu or TrackPopupMenuEx.

The second problem is caused by a problem with TrackPopupMenu. It is necessary to force a task switch to the application that called TrackPopupMenu at some time in the near future. This can be accomplished by posting a benign message to the window or thread.

The following code will take care of all of this:
   SetForegroundWindow(hDlg);

   // Display the menu
   TrackPopupMenu( hSubMenu,TPM_RIGHTBUTTON,pt.x,pt.y,0,hDlg,NULL );

   PostMessage( hDlg,WM_NULL,0,0 );
От себя замечу, что класс TrayIcon в примере D2 лишен этого недостатка.

Вернуться к содержанию.

D10 Как сделать окно неправильной формы?

Arkadiy Olovyannikov:
ИМХО, проще и красивее создавать регионы через Path. Hу что можно сделать через Create...Region? Эллипс? А вот как можно использовать Path:

   Private Declare Function SelectClipPath Lib "gdi32" _
           (ByVal hdc As Long, ByVal iMode As Long) As Long
   Private Declare Function BeginPath Lib "gdi32" (ByVal hdc As Long) As Long
   Private Declare Function EndPath Lib "gdi32" (ByVal hdc As Long) As Long
   Private Declare Function PathToRegion Lib "gdi32" (ByVal hdc As Long) As Long
   Private Declare Function SetWindowRgn Lib "user32" _
           (ByVal hWnd As Long, ByVal hRgn As Long, _
           ByVal bRedraw As Boolean) As Long

   Private Const RGN_COPY = 5

   Private Sub Form_Load()
      ' Don't forget to set Form.BorderStyle property to None !
      Const TXT = " Cool programm" & vbCrLf & "           from" & vbCrLf & _
                  "Cool Company" & vbCrLf & "CopyLeft by Ark"
      Dim hRgn As Long
      Font.Name = "Times New Roman"
      Font.Bold = True
      Font.Size = 60
      Width = TextWidth(TXT)
      Height = TextHeight(TXT)
      BeginPath hdc
      CurrentX = 0
      CurrentY = 0
      Print TXT

      ' Здесь вместо текста можно рисовать фигуры
      EndPath hdc
      hRgn = PathToRegion(hdc)
      SetWindowRgn hWnd, hRgn, False

      ' Hачинаем фантазировать с формой. Можно так
      Picture = LoadPicture("c:\windows\облака.bmp")
      ' А можно так
   '  dclr = 256 / (TextHeight(TXT) / 30)
   '  clr = 0
   '  For i = 120 To 120 + TextHeight(TXT) Step 30
   '     Line (0, i)-Step(5000, 0), RGB(0, 0, clr)
   '     clr = clr + dclr
   '  Next i
      ' Можно дать форме градиентную заливку и т.д.
      ' Двигаем к центру, а можно в таймере крутить
      Move (Screen.Width - Width) / 2, (Screen.Height - Height) / 2
   End Sub

Вернуться к содержанию.

D11 Как привязать программу к компьютеру?

Осуществить привязку программы проще всего к дате создания BIOS материнской платы. Адрес расположения даты в памяти: F000:FFF5. Чтобы считать дату из BIOS, воспользуйтесь нижеследующим кодом:
Dmitry Sergunin:

   Type BIOS_DATE
      s As String * 8
   End Type

   Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" _
           (pDest As Any, pSource As Any, ByVal ByteLen As Long)

   Public Function BIOS() As Long
      Dim sDB As BIOS_DATE

      CopyMemory sDB, ByVal &HFFFF5, 8&
      BIOS = DateSerial(Mid(sDB.s, 7, 2), Mid(sDB.s, 1, 2), Mid(sDB.s, 4, 2))
   End Function

Вернуться к содержанию.

D12 Получить изображение экрана.

Функция, которая реализует эту возможность - GetDesktopWindow. Полный код выглядит так.
Это поместить в область деклараций модуля

   Public Declare Function GetDesktopWindow Lib "user32" () As Long
   Public Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
   Public Declare Function BitBlt Lib "gdi32" _
          (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, _
          ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
          ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
   Public Const SRCCOPY = &HCC0020
Код, копирующий изображение экрана в окно. Размещается в форме. Не забудьте свойство формы AutoRedraw установить в True.
      Dim hDesk, hDeskDC
      hDesk = GetDesktopWindow()
      hDeskDC = GetDC(hDesk)
      BitBlt Me.hDC, 0, 0, Width, Height, hDeskDC, 0, 0, SRCCOPY
Если необходимо изображение поместить в Picture, вместо Me.hDC укажите Picture1.hDC.

Вернуться к содержанию.

D13 Как открыть дверцу (Tray) CD-Rom программно?

Aleksandr Samsonov:
The MultiMedia function provide several commands via the mciSendString API. Perhaps one of the most frequently requested is ejecting (and loading) a CD automatically from code. Using a single line call, this is easily achieved.

Add the following code to a BAS module:

   Option Explicit

   Public Declare Function mciSendString Lib "winmm.dll" _
                  Alias "mciSendStringA" _
                  (ByVal lpstrCommand As String, _
                  ByVal lpstrReturnString As String, _
                  ByVal uReturnLength As Long, _
                  ByVal hwndCallback As Long) As Long
Открыть дверцу CD-Rom:
   Call mciSendString("Set CDAudio Door Open Wait", 0&, 0&, 0&)
Закрыть дверцу CD-Rom:
   Call mciSendString("Set CDAudio Door Closed Wait", 0&, 0&, 0&)

Вернуться к содержанию.

D14 Каким образом можно засюспендить (suspend) компьютер?

Это делает функция SetSystemPowerState. Функция имеет 2 параметра, оба не задействованы в Windows 9X. В Win2000 первый параметр задает особый режим Hibernate, при котором материнская плата обесточивается, но на диммы, подается напряжение и их соедржимое рефрешится, что позволяет при включении мгновенно вернуться к прерванной работе. Материнская плата должна иметь поддержку этой возможности. Во всех предыдущих режимах hibernate, содержимое RAM записывалось на жесткий диск.
Итак, декларацию прописываем в модуль:

   Declare Function SetSystemPowerState Lib "kernel32" _
           (ByVal fSuspend As Long, ByVal fForce As Long) As Long
А в нужный момент вызываем функцию:
   SetSystemPowerState 0&, 0&
Пробуждение осуществляется стандартными методами (мышь, клава, активность порта и т.д.).

Вернуться к содержанию.


Использование внешних библиотек и дополнительных контролов.

E1 Как можно прочитать данные с порта или записать данные в порт?

Для выполнения этих функций нужно воспользоваться библиотекой DLPortIO.DLL, которая, в составе архива, находится здесь. Функции, реализованные в ней, работают под Win9X и WinNT. Архив содержит примерчик и необходимую DLL. А можно пример (без библиотеки) взять в архиве DLPortIO.
Библиотеку нужно скопировать в системный каталог Windows. Обычно это C:\WINDOWS\SYSTEM.

Вернуться к содержанию.


Базы данных.

F1 Как работать с mdb базой, расположенной на Read/Only диске (CD-Rom)?

Alexander Trishin:

   Set db = OpenDatabase (..., True, True)
То есть Exclusive=True и ReadOnly = True











helloworld.ru © 2001-2021
Все права защищены