Советы тем, кто программирует на VB & VBA
Совет 217. Использование функции Split для вычисления количества подстрок
Как мы уже писали в Совете 198 (КомпьютерПресс № 6’99, компакт-диск), в состав VB6 вошла новая функция, предназначенная для проведения синтаксического разбора строковых переменных. Для этого вы просто указываете конкретный разделитель внутри строки, а VB создает одномерный массив, состоящий из подстрок.
Однако функция Split обладает еще одной возможностью — вы можете использовать ее для быстрого подсчета количества подстрок внутри длинной строки. Предположим, что вы хотите определить, сколько раз слово «лес» встречается в строковой переменной «Мы пошли в лес собирать лесные ягоды». Для этого сначала проведите синтаксический разбор данной строки, а затем с помощью функции UBound подсчитайте количество элементов в полученном массиве, как это видно из следующего примера:
strTungTied = “Мы пошли в лес собирать лесные ягоды” aryWood = Split(strTungTied, “лес”) MsgBox “Слово ‘Лес’ встречается в “ & vbCrLf & _ strTungTied & “‘“ & vbCrLf & _ UBound(aryWood) & “ раз(а).”
Теперь запустите этот код на выполнение, и VB сообщит вам, что слово «лес» встречается в заданной нами фразе два раза.
Совет 218. Будьте осторожны при использовании методов Delete объекта FileSystemObject в VB
Как вы уже, вероятно, знаете, объектная библиотека Microsoft Scripting Runtime Library упрощает управление файлами и папками. Так, методы DeleteFolder и DeleteFile позволяют удалять любые ненужные элементы. Однако при их использовании необходимо быть особенно внимательными: в случае нахождения ошибки они прекращают свое выполнение и не совершают отказа от изменений, сделанных к этому моменту времени. Например, если метод DeleteFolder удаляет две папки из десяти, а затем возникает какая-либо ошибка, то VB прерывает выполнение и удаленными оказываются только первых два элемента. Здесь следует также помнить о том, что некоторые другие методы объекта FileSystemObject работают аналогичным образом.
Совет 219 (продолжение Совета 218). Заменяйте длинные строки, содержащие путь, на объектные переменные
Большинство методов, управляющих дисководами, папками или файлами в объектной библиотеке Microsoft Scripting Runtime Library, требует задания аргумента filespec — полного пути, представленного в виде строковой переменной. Однако поскольку свойство Path используется по умолчанию для этих трех типов элементов, вы можете применять объектные переменные вместо строк, содержащих пути. Например, чтобы скопировать одну папку в другую с помощью объектных переменных, напишите следующее:
fldr1.Copy fldr2, Falseили
MyFSO.CopyFile file1, file2, False
Совет 220. Для ограничения размеров VB-формы пользуйтесь элементом управления ActiveX
При создании VB-формы часто бывает необходимо запретить пользователю увеличивать ее за пределы каких-либо установленных размеров. Для этого можно использовать событие Resize-формы и проверить, не превышают ли ее текущие размеры заданное значение (в твипах). Если это так, то VB уменьшает форму и устанавливает ее размеры в соответствии с максимальным значением, например, так:
Private Sub Form_Resize() If Me.Width > 2800 Then Me.Width = 2800 End Sub
Однако такой способ все же дает возможность изменить размеры формы за пределы установленных значений — он просто возвращает форму обратно в ее границы, когда вы отпускаете клавишу мыши. Кроме того, если щелкнуть кнопку «развернуть», то форма раскроется, займет все пространство экрана, а потом появится сообщение об ошибке — нельзя изменять размеры формы в режиме «развернуть». Конечно же, VB предлагает несколько путей решения данной проблемы программным образом, но они не всегда достаточно корректны. Так, форма может возникать в различных частях экрана по мере выполнения кода, который изменяет ее размеры. В Руководствах по графическому интерфейсу говорится, что пользователь всегда прав, поэтому лучше сделать так, чтобы он не мог никаким образом перейти за указанные границы формы.
Для этой цели существует бесплатный элемент управления ActiveX, называемый ARFormExtender. Поместите этот невидимый компонент на форму и установите его свойства MaxHeight, MinHeight, MaxWidth, MinWidth — и это все! Теперь, запустив программу на выполнение, вы не сможете даже перетащить границы формы за пределы заданных значений. Форма останется неизменной, если вы также щелкнете кнопку «развернуть».
Кроме того, ARFormExtender обрабатывает свойство ResizeContents. Если установить последнее как True, элемент управления ARFormExtender будет изменять размеры и взаимное расположение всех компонентов, расположенных на форме, в соответствии с изменением размеров самой формы. Кроме того, любое изменение размеров формы запускает собственное событие Resize элемента управления ARFormExtender, которое передает параметры WidthChange и HeightChange. Эти две величины отражают вертикальное и горизонтальное изменения (в твипах), произошедшие со времени последнего запуска события Resize.
Загрузить элемент управления ARFormExtender или получить более подробную информацию о его возможностях можно по адресу: http://www.sevillaonline.com/ActiveX/.
Совет 221. Как показать стандартное диалоговое окно Properties для файла
Если вы хотите создать стандартное Windows-приложение, желательно, чтобы оно имело диалоговое окно Properties, которое обычно вызывается командой File|Properties. Для этого можно воспользоваться API-функцией ShellExecuteEx:
Option Explicit Private Type SHELLEXECUTEINFO cbSize As Long fMask As Long hWnd As Long lpVerb As String lpFile As String lpParameters As String lpDirectory As String nShow As Long hInstApp As Long lpIDList As Long lpClass As String hkeyClass As String dwHotKey As Long hIcon As Long hprocess As Long End Type Private Declare Function ShellExecuteEx Lib _ “shell32” (lpSEI As SHELLEXECUTEINFO) As Long Private Const SEE_MASK_INVOKEIDLIST = &HC Private Sub Form_Click() Call ShowFileProperties(“c:\windows\system\msvbvm50.dll”) End Sub Private Sub ShowFileProperties(ByVal aFile As String) Dim sei As SHELLEXECUTEINFO sei.hWnd = Me.hWnd sei.lpVerb = “properties” sei.lpFile = aFile sei.fMask = SEE_MASK_INVOKEIDLIST sei.cbSize = Len(sei) ShellExecuteEx sei End Sub
Совет 222. Настройка цветов и шрифтов в строке состояния приложения
Для настройки шрифтов и цветов в создаваемой вами строке состояния можно воспользоваться элементом управления PictureBox и API-функцией SendMessage. Каждая строка состояния может отображать объект Picture, поэтому сначала вы устанавливаете необходимые элементы Background, Foreground и Font для невидимого компонента PictureBox, а затем присваиваете изображение PictureBox объекту Picture в строке состояния. Объект Panel работает со свойством Width вместо свойства Height (Высота), в то время как функция SendMessage может получать значение этой высоты.
Поместите элемент управления PictureBox на форму и установите его свойства следующим образом:
Свойство Значение Name picStatus AutoRedraw True Visible False
Перед вызовом подпрограммы PanelText измените объект Font строки состояния в соответствии с параметрами объекта Panel:
Option Explicit Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Declare Function SendMessage Lib _ “user32” Alias “SendMessageA” (ByVal hWnd _ As Long, ByVal wMsg As Long, ByVal wParam _ As Long, lParam As Any) As Long Private Const WM_USER = &H400 Private Const SB_GETRECT = (WM_USER + 10) Private Sub PanelText(sb As StatusBar, Index As _ Long, aText As String, bkColor As Long, fgColor As Long) Dim R As RECT SendMessage sb.hWnd, SB_GETRECT, Index — 1, R With picStatus Set .Font = sb.Font .Move 0, 0, (R.Right — R.Left + 1) * _ Screen.TwipsPerPixelX, (R.Bottom — _ R.Top + 1) * Screen.TwipsPerPixelY .BackColor = bkColor .Cls .ForeColor = fgColor picStatus.Print aText sb.Panels(Index).Text = aText sb.Panels(Index).Picture = .Image End With End Sub Private Sub Form_Load() PanelText StatusBar1, 1, “Сообщение 1”, _ QBColor(1), QBColor(11) End Sub
Совет 223. Как выровнять текст в командной кнопке
Вам никогда не приходилось выравнивать текст в командной кнопке? Если да, то вы наверняка добавляли соответствующие пробелы в свойстве Caption. Однако это можно сделать и по-другому с помощью API-функции SetWindowLong. Введите следующий код в стандартный BAS-модуль, а затем вызовите его, передавая в качестве аргументов командную кнопку и необходимую комбинацию значений для вертикального и горизонтального выравнивания:
Option Explicit Private Declare Function GetWindowLong Lib _ “user32” Alias “GetWindowLongA” (ByVal hWnd _ As Long, ByVal nIndex As Long) As Long Private Declare Function SetWindowLong Lib _ “user32” Alias “SetWindowLongA” (ByVal hWnd _ As Long, ByVal nIndex As Long, ByVal dwNewLong _ As Long) As Long Private Const BS_LEFT As Long = &H100 Private Const BS_RIGHT As Long = &H200 Private Const BS_CENTER As Long = &H300 Private Const BS_TOP As Long = &H400 Private Const BS_BOTTOM As Long = &H800 Private Const BS_VCENTER As Long = &HC00 Private Const BS_ALLSTYLES = BS_LEFT Or _ BS_RIGHT Or BS_CENTER Or BS_TOP Or _ BS_BOTTOM Or BS_VCENTER Private Const GWL_STYLE& = (-16) Public Enum bsHorizontalAlignments bsLeft = BS_LEFT bsRight = BS_RIGHT bsCenter = BS_CENTER End Enum Public Enum bsVerticalAlignments bsTop = BS_TOP bsBottom = BS_BOTTOM bsVCenter = BS_VCENTER End Enum Public Sub AlignButtonText(cmd As CommandButton, _ Optional ByVal HStyle As bsHorizontalAlignments = _ bsCenter, Optional ByVal VStyle As _ bsVerticalAlignments = bsVCenter) Dim oldStyle As Long ‘ получает текущий стиль oldStyle = GetWindowLong(cmd.hWnd, GWL_STYLE) ‘ очищает существующие установки выравнивания oldStyle = oldStyle And (Not BS_ALLSTYLES) ‘ устанавливает новый стиль и ‘ обновляет кнопку Call SetWindowLong(cmd.hWnd, GWL_STYLE, _ oldStyle Or HStyle Or VStyle) cmd.Refresh End Sub Private Sub Form_Load() Call AlignButtonText(Command1, bsLeft, bsTop) End Sub
Совет 224. Управление шириной столбцов элемента управления DBGrid в процессе выполнения программы
DBGrid — один из самых популярных элементов управления для вывода данных в виде таблицы. Однако, если изменить ширину столбцов сетки в процессе выполнения программы, Visual Basic не запомнит текущие значения и при следующем запуске программы выведет таблицу в неизменном виде. Здесь мы приводим текст подпрограммы, с помощью которой можно сохранять ширину столбцов для повторных запусков:
Option Explicit Sub DBGridLayout(Operation As String) ‘сохраняет ширину столбцов Dim lWidth As Long Dim clm As Column Dim lDefWidth As Long ‘ lDefWidth = DBGrid1.DefColWidth For Each clm In DBGrid1.Columns With cl Select Case LCase(Operation) Case “save” lWidth = .Width SaveSetting App.Title, “Cols” _ CStr(.ColIndex), lWidth Case “load” lWidth = GetSetting(App.Title, _ “Cols”, CStr(.ColIndex), _ lDefWidth) .Width = lWidth End Select End With Next clm End Sub
Как видно из вышеприведенного текста, подпрограмма использует функции SaveSetting и GetSetting для хранения текущих значений ширины столбцов в разделе VB Регистра. Для применения данной подпрограммы в своем приложении вызовите ее из событий Load и Unload родительской формы. Затем укажите операцию, которую должна выполнить подпрограмма, как это показано ниже:
Private Sub Form_Load() DBGridLayout “Load” End Sub Private Sub Form_Unload(Cancel As Integer) DBGridLayout “Save” End Sub
Совет 225. Простой способ запомнить события запуска VB-формы
Если вам трудно запомнить последовательность событий при запуске VB-формы, попробуйте запомнить следующую простую фразу:
I Like RAP (я люблю рэп),
которую можно расшифровать следующим образом:
I — Initialize
Like — Load
R — Resize
A — Activate
P — Paint
Если вам неудобно признаться в том, что вы любите рэп, можно всегда заменить эту фразу на другую, например: I Loathe RAP (я ненавижу рэп).
Совет 226. Обмен переменными между разными приложениями
Иногда возникает необходимость обмениваться переменными между различными приложениями, например при совместном использовании базы данных. Для этого создадим ActiveX EXE с модулем класса Class1. Здесь нельзя создать библиотеку ActiveX DLL, поскольку она выполняется внутрипроцессно (in-process) в каждом клиенте. Добавьте к проекту модель (команда Project|Add Module) и опишите переменную, которая будет передаваться в другое приложение, в качестве общей.
Код в ActiveX EXE будет выглядеть следующим образом:
********* Код модуля ********** Global gCon As Database Global glngNrOfObjects As Long ********* Код класса ********** Public Property Set DBConn(Con As Database) Set gCon = Con End Property Public Property Get DBConn() As Database Set DBConn = gCon End Property Private Sub Class_Initialize() ‘ эта переменная хранит количество ‘ созданных объектов glngNrOfObjects = glngNrOfObjects + 1 End Sub Private Sub Class_Terminate() ‘ уменьшение количества объектов glngNrOfObjects = glngNrOfObjects — 1 ‘ если нет никаких объектов, ‘ связь прерывается If glngNrOfObjects = 0 Then If Not gCon Is Nothing Then gCon.Close Set gCon = Nothing End If End If End Sub Теперь установите ссылку к библиотеке ActiveX EXE в своем проекте и используйте ее, например, так: *** Код приложения, использующего ActiveX EXE *** Dim clsDBConn As Class1 Private Sub Form_Load() Set clsDBConn = New Class1 ‘ связь устанавливается, когда ‘ создан первый объект If clsDBConn.DBConn Is Nothing Then Set clsDBConn.DBConn = Workspaces(0). _ OpenDatabase(“\VisStudio\Vb98\Biblio.mdb”) End If End Sub Private Sub Form_Unload(Cancel As Integer) Set clsDBConn = Nothing End Sub
Вам нет необходимости писать код для подсчета экземпляров объектов и для закрытия базы данных, если вы работаете с простой переменной, а не с ссылкой на объект. В этом случае также поменяйте Property Set на Property Let.
И наконец, главное. Не забудьте установить ссылку к объектам DAO, так как они используют объект базы данных.
КомпьютерПресс 12'1999