16. УМЕНЬШИТЬ РАЗМЕР КОДА, ИСПОЛЬЗУЯ ОПЕРАТОРЫ IIF И SWITCH
VB4 16/32, VB5 Level: Intermediate
Часто бывает целесообразным заменить блок If...Then...Else более компактной функцией Iif:
' возвращает большую из двух сравниваемых величин maxValue = IIf(first >= second,first, second)
Switch - редко используемая функция, даже в тех многочисленных случаях, когда она более полезна нежели длиннющий блок If...ElseIf: ' надо узнать, х полижительный, отрицательный, или равен 0? Print Switch(x < 0, "negative", x > 0, _ "positive", True, "Null")
Заметим, что значение последней проверки всегда True, так как три условия являются взаимно исключающими и избыточными.
17. УСКОРЬТЕ ВАШ КОД ИСПОЛЬЗОВАНИЕМ CHOOSE
VB3, VB4 16/32, VB5 Level: Beginning
Вы можете использовать Choose там, где можно заменить массив или построить таблицы результатов, на стадии компиляции (compile-time), вместо того, чтобы делать это на стадии выполнения (run time). Например, если Вам надо знать значения факториалов чисел от 1 до 10, попробуйте следующий пример (Choose производит выбор факториала из набора имеющихся значений всесто того, чтобы высчитывать факториал каждый раз заново): Function Factorial(number As Integer) _ As Long Factorial = Choose(number, 1, 2, 6, _ 24, 120, 720, 5040, 40320, _ 362880, 3628800) End Function
18. GOSUBS РАБОТАЮТ МЕДЛЕННО В ОТКОМПИЛИРОВАННЫХ ПРОГРАММАХ
VB5 Level: Intermediate
Поскольку использование GoSubs относится к неструктурированному стилю программирования, то многие программисты стараются избегать его. Если Вы компилируете Вашу VB5 аппликуху в native code, у Вас появится еще одна причина избегать этот оператор, поскольку вызовы через GoSubs могут происходить в пять раз медленнее, чем вызовы обычной процедуры или функции.
19. ?ARRAYЋ - ОТНЫНЕ ЭТО ОШИБОЧНОЕ ИМЯ ДЛЯ ПЕРЕМЕННЫХ
VB5 Level: Intermediate
Если Вы, как и я, часто используете имя "array" для переменных, Вам придется пересмотреть Ваш код при переносе его под VB5. Это слово является теперь зарезервированным (reserved keyword) и не может быть использовано в качестве имени переменной. Вы можете легко переделать Ваш код при помощи команды Replace в IDE VB5, не забудьте при этом черкнуть "Find whole words only".
20. ЗАПУСК AUTOMATION MANAGER КАК HIDDEN ЗАДАЧИ
VB4 16/32, VB5 Enterprise Edition Level: Advanced
Если Вы мспользуете OLE Remote Automation, Вы должны заранее запустить Automation Manager на сервере до того как случится первая OLE remote communication. По умолчанию, это приложение visible, но Вы можете его спрятать, чтобы оно не мозолило глаза на таскбаре Чикаги. Для этого создайте ярлык для Automation Manager, который бы включал в командной строке переключатель /Hidden: C:\Windows\System\AutMgr32.Exe /Hidden С другой стороны, Вы можете поменять значение соответствующего ключа в регистре. Для более полной инфы, см. Статью Q138067 in the Microsoft Knowledge Base.
21. ПРОБЛЕМЫ СО ВСПЛЫВАЮЩИМИ МЕНЮ
VB4 16/32, VB5 Level: Advanced
Если Вы используете всплывающие меню (popup menus) в Ваших прогах, то опасайтесь бага, имеющегося в VB4 16/32 и VB5. Если у Вас есть две формы и одна из них вызывает вторую модальную через всплывающее меню, то из этой второй модальной Вы не сможете вызвать ни одного всплывающего меню, сколько бы их на ней ни было. Чтобы пофиксить это дело, используйте таймер на первой форме. Вместо показа фторой формы из всплывающего меню по событию Click, активизируйте таймер так, чтобы он показал эту вторую форму через несколько миллисекунд. Для более полной инфы, см. Статью Q167839 in the Microsoft Knowledge Base.
22. ИСПОЛЬЗОВАНИЕ КОЛЛЕКЦИИ ДЛЯ ОТФИЛЬТРОВЫВАНИЯ ДУБЛИРОВАННЫХ ЗНАЧЕНИЙ
VB4 16/32, VB5 Level: Intermediate
Этот код иллюстрирует, как использовать коллекции (Collection) для генерации уникального набора величин из набора, содержащего дубликаты. В этом примере, сканируется массив строк и сортируются все уникальные с использованием list-box контрола: Sub Remove_Duplicates(arr() As String) Dim i As Long Dim RawData As String Dim DataValues As New Collection
On Error Resume Next ' это вставлено для игнорирования ошибки 457 - Duplicate key For i = LBound(arr) To UBound(arr) RawData = arr(i) DataValues.Add RawData, RawData ' Если Run-time error 457 случилась, то повторяющееся значение игнорируется Next On Error GoTo 0
' Сохранение в List Box ' (свойство Sorted выставлено True) lstSortedData.Clear For Each DataValue In DataValues lstSortedData.AddItem DataValue Next End Sub
23. СОЗДАНИЕ ?УДАЛЕННО КОНТРОЛИРУЕМЫХЋ ФОРМ
VB3 Level: Intermediate
Иногда мне требуется котролировать одну форму, когда фокус находится на другой. Например, когда я жму ?ОКЋ на форме А, мне надо сделать resize на форме В. Итак, на каждой форме, которую мне надо ?удаленно контролироватьЋ, я делаю невидимый text box, назовем его TextCommand, в событии Change которого находится следующий код: Sub TextCommand_Change () Dim msg as string msg = Trim$(Me.TextCommand.Text) If Len(msg) = 0 Then Exit Sub
Select Case msg Case "COMMAND_RESIZE" Call MyFormResize Case "COMMAND_REPAINT" Call MyFormPaint ... End Select Me.TextCommand = "" End Sub
Вы можете удаленно контролировать форму, засылая соответствующее значение в ее TextCommand: Sub Command1_Click () formB.TextCommand = "COMMAND_RESIZE" DoEvents End Sub
Этот код можно использовать для отсылки мессагов из MDI формы к потомкам: Dim f As Form Set f = Me.ActiveForm f.TextCommand = "COMMAND_RESIZE"
Если Вы сидите под VB4 или VB5, Вы можете также использовать Public-свойства и методы формы.
24. ЗАПИСЬ ТЕКУЩЕЙ ПОЗИЦИИ И РАЗМЕРА ФОРМЫ ПРИ ПОМОЩИ SAVESETTING
VB4 16/32, VB5 Level: Intermediate
Функции SaveSetting и GetSetting облегчают написание сеттингов в аппликухах. Эти две функции восстанавливают и запоминают текущие позиции формы: Public Sub FormPosition_Get(F As Form) ' Считывает позицию формы F из ' ini/reg файла и соответственно ' позиционирует форму Dim buf As String Dim l As Integer, t As Integer Dim h As Integer, w As Integer Dim pos As Integer
buf = GetSetting(app.EXEName, _ "FormPosition", F.Tag, "") If buf = "" Then ' defaults для центрирования фромы F.Move (Screen.Width - F.Width) \ _ 2, (Screen.Height - F.Height) \ 2 Else ' выделить l,t,w,h и выставить форму pos = InStr(buf, ",") l = CInt(Left(buf, pos - 1)) buf = Mid(buf, pos + 1) pos = InStr(buf, ",") t = CInt(Left(buf, pos - 1)) buf = Mid(buf, pos + 1) pos = InStr(buf, ",") w = CInt(Left(buf, pos - 1)) h = CInt(Mid(buf, pos + 1)) F.Move l, t, w, h End If End Sub
Public Sub FormPosition_Put(F As Form) ' Пишет op,left,height и ' width позиции формы F в reg/ini файл аппликухи Dim buf As String buf = F.left & "," & F.top & "," & _ F.Width & "," & F.Height SaveSetting app.EXEName,_ "FormPosition", F.Tag, buf End Sub
Вам следует поместить эти процедуры в модуль и вызывать их из событий Load и Unload форм. Вы должны написать имя формы в ее свойство Tag, чтобы эти процедуры работали корректно
Sub Form_Load() FormPosition_Get Me End Sub Sub Form_Unload() FormPosition_Put Me End Sub
25. ЭФФЕКТИВНОЕ ИСПОЛЬЗОВАНИЕ ВНУТРЕННИХ VB КОНСТАНТ
VB4 16/32, VB5 Level: Beginning
Мне приходилось видеть некоторые советы по использованию числовых значений вместо соответствующих VB констант. Например, Вы можете вывести message box, используя числовые константы: rc = MsgBox(msg, 4 + 32 + 256, "Confirm Delete")
Но не легче ли прочесть следующее? rc = MsgBox(msg, vbYesNo + vbQuestion _ + vbDefaultButton2, _ "Confirm Delete")
Вы можете использовать следующие константы для check box: VbUnchecked =0 VbChecked =1 VbGrayed =2
Также полезно знать строковые константы вместо соответствующих chr$(символы ASCII): vbTab instead of Chr$(9) vbCr instead of Chr$(13) vbLf instead of Chr$(10) vbCrLf instead of Chr$(13)+Chr$(10)
26. ПРАВИЛЬНЫЙ ТЕСТ НА "FILE EXIST"
VB3, VB4 16/32, VB5 Level: Intermediate
Dir$ генерирует runtime error, если ему суют несуществующее имя диска. Например, Dir$ ("d:\win\himems.sys") умирает , если драйв d: не существует. Для проверки существования файла, добавьте обработчик ошибки: Function FileExist(filename As String) _ As Boolean On Error Resume Next FileExist = Dir$(filename) <> "" If Err.Number <> 0 Then FileExist _ = False On Error GoTo 0 End Function
27. ПРОЦЕДУРЫ, РАБОТАЮЩИЕ С ГРУППАМИ КОНТРОЛОВ
VB4 16/32, VB5 Level: Intermediate
Вы можете использовать почти забытую возможность VB иметь процедуру или функцию, работающую с неограниченным числом аргументов, что может быть полезно при работе с множеством контролов. Например, Вы можете enable/disable группу контролов одним вызовом процедуры: EnableAll True, Text1, Text2, _ Command1, Command2
Эта процедура проходит по всем контролам, передаваемым в качестве аргументов: Sub EnableAll(Enabled As Boolean, _ ParamArray objs() As Variant) Dim obj As Variant For Each obj In objs obj.Enabled = Enabled Next obj End Sub
28. УЛУЧШЕНИЕ СКРОЛЛИНГА РИСУНКОВ
VB3, VB4 16/32, VB5 Level: Intermediate
Во-первых, сделайте, чтобы событие Scroll скроллбара картинки обновляло координаты картинки (как будто бы она движется) когда Вы возите мышой по картинке. Затем, объявите следующие переменные на уровне формы: Dim StartX As Long, StartY As Long Dim Moving As Boolean
Наконец, объявите эти три события для PicPicture: Private Sub PicPicture_MouseDown_ (Button As Integer, Shift As _ Integer, x As Single, y As Single) StartX = x StartY = y Moving = True End Sub
Private Sub PicPicture_MouseMove_ (Button As Integer, Shift As _ Integer, x As Single, y As Single) If Moving Then PicPicture.Move _ PicPicture.Left + x - StartX, PicPicture.Top + y - StartY End If End Sub
Private Sub PicPicture_MouseUp_ (Button As Integer, Shift As _ Integer, x As Single, y As Single) Moving = False End Sub
Теперь Вы можете скроллить картинку мышой. Не забудьте проверить границы картинки.
29. ЗАШИФРОВАННЫЕ ПАРОЛИ
VB3, VB4 16/32, VB5 Level: Intermediate
Следующие две функции легко и эффективно шифрут/дешифруют текстовый пароль. Функции имеют два аргумента: число от 1 до 10 чтобы сдвигать позицию символа ASCII в пароле, и собственно строка пароля. Функция EncryptPassword проходит через каждый символ строки DecryptedPassword, проверяет символ на четность/нечетность, и сдвигает его вверх/вниз согласно параметру Number. Эту делает зашифрованную строку нечитабельной. Зашифрованный пароль ?укатываетсяЋ затем оператором XOR, который еще более запутывает строку. Я ограничил параметр Number числом 10, поскольку мне не надо делать проверку на ?неправильныеЋ символы ASCII. Функция DecryptPassword повторяет в обратном порядке процесс шифрования, применяя XOR, а затем сдвиг. Function EncryptPassword(Number As _ Byte, DecryptedPassword As String) Dim Password As String, Counter As Byte Dim Temp As Integer
Counter = 1 Do Until Counter = _ Len(DecryptedPassword) + 1 Temp = Asc(Mid(DecryptedPassword, _ Counter, 1)) If Counter Mod 2 = 0 Then 'see if even Temp = Temp - Number Else Temp = Temp + Number End If Temp = Temp Xor (10 - Number) Password = Password & Chr$(Temp) Counter = Counter + 1 Loop EncryptPassword = Password End Function
Function DecryptPassword(Number As _ Byte, EncryptedPassword As String) Dim Password As String, Counter As Byte Dim Temp As Integer
Counter = 1 Do Until Counter = _ Len(EncryptedPassword) + 1 Temp = Asc(Mid(EncryptedPassword, _ Counter, 1)) Xor (10 - Number) If Counter Mod 2 = 0 Then 'see if even Temp = Temp + Number Else Temp = Temp - Number End If Password = Password & Chr$(Temp) Counter = Counter + 1 Loop DecryptPassword = Password End Function
30. ПРОПИСНЫЕ-СТРОЧНЫЕ БУКВЫ - СОВЕТ ПО СЛЕЖЕНИЮ ЗА РЕГИСТРОМ БУКВ
VB4 16/32, VB5 Level: Intermediate
Если Вы используете левую стрелку на клаве, чтобы перейти к началу слова, а затем нажимаете букву, то в итоге Вы получаете две заглавных буквы (первая уже была, а вторую ввели Вы - я так понимаю??). Применив код, который использует преимущества встроенной в VB4/VB5 функции StrConv(), Вы получите автоматическое приведение букв в нужный регистр во время ввода: Private Sub Text1_Change() If Text1.Tag = "" Then Text1.Tag = Text1.SelStart Text1.Text = StrConv(Text1.Text, vbProperCase) Text1.SelStart = Text1.Tag Text1.Tag = "" End If End Sub