Visual Basic, .NET, ASP, VBScript
 

   
 

Михаил Эскин немало сделал для развития русскоязычных VB сайтов. Многие знают его по статьям про ActiveX на VB сайтах, другие читают статьи Михаила уже на его собственном сайте. Михаил родился в Городском роддоме №1 города Астрахани, в “черную пятницу”, ну, так скажем, почти сорок лет назад. По-прежнему живет на Юге, правда теперь уже Германии, в прекрасном городе Мюнхене.

 
     
   
 

    Прежде чем начать работу с конкретным примером я бы хотел вначале несколько подробнее остановиться, что же такое dll в VB. DLL, созданный в VB, отличается от DLL, созданных на С++, как небо и земля. Чтобы воспользоваться библиотекой, написанной на С, необходимо задекларировать конкретную функцию в конкретной библиотеке, и можно пользоваться. Эти библиотеки представляют иногда такие возможности, которые отсутствуют в самом VB.

    Библиотеки, написанные на VB, несмотря на одинаковое расширение файлов, структурно принципиально отличаются. Это, так называемые, ActiveX DLL. И, исходя из их названия, работают, как и любое другое ActiveX-приложение. То есть данную библиотеку необходимо вначале зарегистрировать, чтобы VB ее увидел, а затем присоединить к программе. Исходя из того, что эти библиотеки являются внешними, мы получаем некоторые ограничения при объявлении типов данных. Например, мы не можем передать параметр с пользовательским типом данных или с типом как форма или контрол (что VВ интерпретирует как все тот же пользовательский тип). Возможно, это и послужило среди программистов причиной низкой популярности данного типа приложений, созданных на VB. Однако, как и любое другое приложение, оно имеет свои плюсы, например возможность создания объектно-ориентированного кода.

    Создавая свои программы, у каждого накопились какие-либо свои разработки, уловки, хорошо отлаженные коды. И чтобы их использовать вы начинаете хранить их в виде текстовых файлов, баз данных или ссылок на Интернет. Я предлагаю использовать для этого свою библиотеку, подключаемую к любому своему приложению с уже известными вам функциями.

    Шаг 1. Создадим новый проект ActiveX DLL. Назовем его MyLibrary. Класс, который создается с данным проектом по умолчанию, сделаем главным, назовем MyLib, и пока закроем. К нему мы вернемся чуть позже.

    Шаг 2. Добавим в проект через меню Project/Add Class Module. Изменим его название на FrmFunct. Сюда мы будем добавлять коды функций, связанных с работой форм. Для примера возьмем возможность показа формы поверх всех и снятия этой возможности. Для этого в разделе деклараций объявим API-функцию:

Private Declare Function SetWindowPos Lib "user32" _
    (ByVal hwnd As Long, _
    ByVal hWndInsertAfter As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal cx As Long, _
    ByVal cy As Long, _
    ByVal wFlags As Long) As Long 

А теперь напишем 2 процедуры, которые и выполняют данные функции.

Public Sub MakeNormal(Handle As Long)
    SetWindowPos Handle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub

Public Sub MakeTopMost(Handle As Long)
    SetWindowPos Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub

    Шаг 3. Добавим еще один класс. Он будет отвечать у нас за работу с ini-файлами. Соответственно дадим ему имя IniFunct. Объявим 2 API функции, отвечающие за работу с ini-файлами

Private Declare Function WritePrivateProfileString Lib "kernel32" _
    Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As Any, _
    ByVal lpString As Any, _
    ByVal lpFileName As String) As Long

Private Declare Function GetPrivateProfileString Lib "kernel32" _
    Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As Any, _
    ByVal lpDefault As String, _
    ByVal lpReturnedString As String, _
    ByVal nSize As Long, _
    ByVal lpFileName As String) As Long

и напишем также 2 процедуры.

'Читаем данные из ini
Public Function ReadINIKey(Section As String, KeyName As String, FileName As String) As String
    Dim RetVal As String

    RetVal = String(255, Chr(0))
    ReadINIKey = Left(RetVal, GetPrivateProfileString(Section, KeyName, "", RetVal, Len(RetVal), FileName))
End Function

'Записываем данные в ini
Public Function WriteInIKey(Section As String, KeyName As String, KeyValue As String, FileName As String)
    WritePrivateProfileString Section, KeyName, KeyValue, FileName
End Function

NB! Функции, написанные в обоих классах, объявлены как Public для того, чтобы иметь к ним доступ из вне.

    Шаг 4. Вернемся в класс MyLib. Теперь настало самое время привязать другие классы к нему. Для этого в разделе деклараций объявим 2 переменные (по одной для каждого класса) с типом этого класса.

Private m_FormFunction As FrmFunct
Private m_IniFunction As IniFunct

    В процедуре инициализации класса запустим эти переменные, а в процедуре завершения работы класса – не забудем от них почистить память.

Private Sub Class_Initialize()
    Set m_FormFunction = New FrmFunct
    Set m_IniFunction = New IniFunct
End Sub

Private Sub Class_Terminate()
    Set m_FormFunction = Nothing
    Set m_IniFunction = Nothing
End Sub

Теперь объявим 2 свойства Property Get, соответствующих каждому классу.

Public Property Get FormFunction() As FrmFunct
    Set FormFunction = m_FormFunction
End Property

Public Property Get IniFunction() As IniFunct
    Set IniFunction = m_IniFunction
End Property

Вот, собственно говоря, и все.

    Шаг 5. Теперь наступает один из самых неприятных моментов – это тестирование DLL. Их можно тестировать только в другом проекте. Поэтому запустите на выполнение наш проект, и откройте еще один экземпляр VB. Создайте проект Standard EXE. Зайдите в меню Project/References. В диалоговом окне найдите название нашей библиотеки. Открыжте ее и нажмите кнопку ОК. Мы подсоединили нашу библиотеку к тестировочному проекту.

NB! Если вы в свойствах проекта не заполняли поле Description, то в качестве названия будет по умолчанию стоять имя ехе-файла. В противном случае будет выводиться надпись из поля Description.

    Шаг 6. Давайте на примере одной функции покажем, как работает наша библиотека. В разделе деклараций объявим переменную с типом нашего основного класса (то есть MyLib). В Form_Load озвучим эту переменную, а в Form_Unload не забудем освободить от нее память.

Private Sub Form_Load()
    Set ML = New MyLib
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Set ML = Nothing
End Sub

    На форме разместим 2 кнопки, каждой из которых назначим функцию этого класса, отвечающего за расположение поверх вcех форм и нормального расположения.

Private Sub Command1_Click()
    ML.FormFunction.MakeTopMost Me.hWnd
End Sub

Private Sub Command2_Click()
    ML.FormFunction.MakeNormal Me.hWnd
End Sub

Запустим проект на тестирование. Вы можете добавлять другие функции в эти классы или создать новые, определив ту структуру хранения информации, какую вы хотите.

NB! При компиляции библиотеки происходит автоматическая регистрация ее на Вашем компьютере. Если же вы переносите ее на другой компьютер, необходимо позаботиться о ее регистрации там (выполняется с помощью все того же файла, что и для регистрации ОСХ – т.е. regsvr32.exe, или можно воспользоваться моей утилитой Reg).

Лирическое отступление. Чуть-чуть об апгрейдах. Вполне вероятно, что вы найдете что-либо новое, которое перечеркнет ваши предыдущие функции. Мой совет – не удаляйте их. Иначе произведя апгрейд, вы можете столкнуться с тем, что в какие-то ваши программы не будут работать, т.к. они опирались на удаленные функции. Скройте их. Они вам не будут мозолить глаза при работе в программе, и вместе с тем они будут продолжать работать. Для того чтобы скрыть функцию выберите меню Tools/Procedure Attributes. Выберите необходимую (-ые) функцию, нажмите кнопку Advanced>> и в поле Hide this member поставьте галочку. Нажмите ОК.

Полный листинг программы

Класс MyLib

Option Explicit

Private m_FormFunction As FrmFunct
Private m_IniFunction As IniFunct

Public Property Get FormFunction() As FrmFunct
    Set FormFunction = m_FormFunction
End Property

Public Property Get IniFunction() As IniFunct
    Set IniFunction = m_IniFunction
End Property

Private Sub Class_Initialize()
    Set m_FormFunction = New FrmFunct
    Set m_IniFunction = New IniFunct
End Sub

Private Sub Class_Terminate()
    Set m_FormFunction = Nothing
    Set m_IniFunction = Nothing
End Sub

Класс FrmFunct

Option Explicit

Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_SHOWWINDOW = &H40
Private Const TOPMOST_FLAGS = SWP_NOMOVE Or SWP_NOSIZE

Private Declare Function SetWindowPos Lib "user32" _
    (ByVal hwnd As Long, _
    ByVal hWndInsertAfter As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal cx As Long, _
    ByVal cy As Long, _
    ByVal wFlags As Long) As Long

Public Sub MakeNormal(Handle As Long)
    SetWindowPos Handle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub

Public Sub MakeTopMost(Handle As Long)
    SetWindowPos Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub

Класс IniFunct

Option Explicit

Private Declare Function WritePrivateProfileString Lib "kernel32" _
    Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As Any, _
    ByVal lpString As Any, _
    ByVal lpFileName As String) As Long

Private Declare Function GetPrivateProfileString Lib "kernel32" _
    Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As Any, _
    ByVal lpDefault As String, _
    ByVal lpReturnedString As String, _
    ByVal nSize As Long, _
    ByVal lpFileName As String) As Long

'Читаем данные из ini
Public Function ReadINIKey(Section As String, KeyName As String, FileName As String) As String
    Dim RetVal As String

    RetVal = String(255, Chr(0))
    ReadINIKey = Left(RetVal, GetPrivateProfileString(Section, KeyName, "", RetVal, Len(RetVal), FileName))
End Function

'Записываем данные в ini
Public Function WriteInIKey(Section As String, KeyName As String, KeyValue As String, FileName As String)
    WritePrivateProfileString Section, KeyName, KeyValue, FileName
End Function

Тестировочный проект. Форма.

Option Explicit

Private ML As MyLib

Private Sub Command1_Click()
    ML.FormFunction.MakeTopMost Me.hWnd
End Sub

Private Sub Command2_Click()
    ML.FormFunction.MakeNormal Me.hWnd
End Sub

Private Sub Form_Load()
    Set ML = New MyLib
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Set ML = Nothing
End Sub

 
     

   
   
     
  VBNet рекомендует