Visual2000 · Архив статей А.Колесова & О.Павловой
Андрей Колесов, Ольга Павлова
© 1998, Андрей Колесов, Ольга ПавловаБольшинство функций Win32 API выводит на экран сообщение об ошибках, возникающих при их некорректном использовании. Чтобы сделать эту информацию более содержательной, следует воспользоваться функциями GetLastError и FormatMessage.
Для этого введите в BAS-модуль VB-проекта следующие описания и функцию:
Option Explicit Public Declare Function GetLastError Lib "kernel32" () As Long Public Declare Function FormatMessage Lib "kernel32" Alias _ "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, _ ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _ ByVal lpBuffer As String, ByVal nSize As Long, _ Arguments As Long) As Long Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000 Public Function LastSystemError() As String ' ' системная ошибка Dim sError As String * 500 Dim lErrNum As Long Dim lErrMsg As Long ' lErrNum = GetLastError lErrMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, _ ByVal 0&, lErrNum, 0, sError, Len(sError), 0) LastSystemError = Trim(sError) ' End Function
Затем поместите командную кнопку на стандартную VB-форму и вызовите функцию LastSystemError:
Private Sub Command1_Click() ' MsgBox LastSystemError ' End Sub
Если не было зарегистрировано никакой ошибки, вы увидите сообщение со словами "The operation completed successfully".
При использовании данной функции следует помнить следующее:
В некоторых программах работа с датой реализована довольно интересным образом. Нажатие клавиши [+] увеличивает дату на один день, клавиши [-] — уменьшает на один день, клавиша [PgDn] прибавляет один месяц, а клавиша [PgDn] убавляет на один месяц. Попробуем реализовать это с помощью VB.
Вначале поместите на форму элемент управления TextBox (txtDate). Установите его свойство Text равным "", а свойство Locked — True. После этого введите следующий код в событие KeyDown:
Private Sub txtDate_KeyDown(KeyCode As Integer, Shift As Integer) ' ' KeyCode — специальный код клавиши (а не ASCII-код!) ' 107 = "+" KeyPad (цифровая клавиатура) ' 109 = "-" KeyPad ' 187 = "+" (в действительности это клавиша "=") ' 189 = "-" ' 33 = PageUp ' 34 = PageDown ' Dim strYear As String Dim strMonth As String Dim strDay As String ' If txtDate.Text = "" Then txtDate.Text = Format(Now, "d/m/yyyy") Exit Sub End If ' strYear = Format(txtDate.Text, "yyyy") strMonth = Format(txtDate.Text, "mm") strDay = Format(txtDate.Text, "dd") ' Select Case KeyCode Case 107, 187 ' добавляет один день txtDate.Text = Format(DateSerial(strYear, strMonth, strDay) + _ 1, "d/m/yyyy") Case 109, 189 ' убавляет на один день txtDate.Text = Format(DateSerial(strYear, strMonth, strDay) - _ 1, "d/m/yyyy") Case 33 ' увеличивает на один месяц txtDate.Text = Format(DateSerial(strYear, strMonth + 1, _ strDay), "d/m/yyyy") Case 34 ' уменьшает на один месяц txtDate.Text = Format(DateSerial(strYear, strMonth - 1, _ strDay), "d/m/yyyy") End Select ' End Sub
Этот способ коррекции даты очень полезен, так как гарантирует правильный формат даты в окне. Именно для того, чтобы избежать возможных ошибок при вводе, мы, установив свойство Locked равным True, заблокировали возможность редактировать в текстовом окне дату в явном виде.
Обратите внимание, что при вводе данных в событие KeyPress передается код символа ASCII (KeyAscii), а для событий KeyDown/KeyUp — код клавиши (KeyCode).
В первом случае мы получаем значимые символы в однобайтовой кодировке ANSI (событие KeyPress не реагирует на нажатие функциональных клавиш, клавиш редактирования, перемещения и пр., которые часто кодируются в двухбайтовой ANSI-кодировке). Нажатию одной и той же клавиши может соответствовать до четырех разных символов и их значений ASCII, например — "S s Ы ы". Код передается в виде ссылки (By Reference). Так что если вы измените его в этой процедуре, то объект (элемент управления) будет иметь дело с вашим значением. Например, такой код:
Sub Text1_KeyPress (KeyAscii As Interger) If KeyAscii = Asc("1") Then KeyAscii = Asc("2") End If
будет вводить в текстовое окно двойку вместо единицы.
Во втором случае в процедуру передается код, закрепленный за данной клавишей (без учета текущей раскладки клавиатуры и регистра). При этом события KeyDown/KeyUp реагируют на нажатие (или освобождение) ЛЮБОЙ клавиши клавиатуры. Но нужно иметь в виду, что коды клавиш малой цифровой клавиатуры идентичны кодам соответствующих клавиш редактирования и перемещения. Не очень понятно, почему, но эти коды клавиш отличаются от значений SCAN-кодов клавиатуры.
В программе можно применять код клавиш в цифровом виде (как мы делали в предыдущем примере) или использовать встроенные константы VB. Например, клавиша PageDown описывается константой vbKeyPageDown=34. Список этих констант и их значений можно найти либо в справочной системе (для поиска нужного раздела введите во вкладке Index слово "KeyCode" для десятичного варианта значения или "Key Code" для шестнадцатеричного) либо через Object Browser:
Однако в списке этих констант почему-то отсутствуют некоторые клавиши — ('-=;',./). Впрочем, код любой клавиши вы можете легко определить с помощью такой простой программки:
Sub Text1_KeyDown (KeyCode As Interger, Shift As Integer) Debug.Print KeyCode End If
Как видно из этого примера, в процедуры KeyDown/KeyUp передается также параметр Shift, значение которого отражает состояние клавиш Shift, Ctrl и Alt: при их нажатии устанавливается единица соответственно в 0-й, 1-й и 2-й разряд переменной. Например, комбинация клавиш Shift+Ctrl будет иметь значение 3 (двоичное 011).
В состав Win32 API входит одна очень занимательная функция, используя которую вы обнаружите, что в 32-разрядной версии Windows окно может иметь не только прямоугольную форму. На самом деле оно может быть любой конфигурации. Следующий пример демонстрирует работу с одной из так называемых функций региона (region functions) — SetWindowRgn.
Вначале введите такой код в раздел General Declarations:
Private Declare Function CreateEllipticRgn Lib "gdi32" _ (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, _ ByVal Y2 As Long) As Long Private Declare Function SetWindowRgn Lib "user32" _ (ByVal hWnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As Long
А затем напишите следующее для события Load:
Private Sub Form_Load() Show ' Вывод формы SetWindowRgn hWnd, CreateEllipticRgn(0, 0, 300, 200), True End Sub
Вот и все. Запустите данный пример на выполнение, и VB выведет на экран форму в виде эллипса.
После установки VB вы можете обнаружить, что инструментальные окна среды как бы "подключены" к основному окну и вы лишены возможности свободно управлять их размерами и размещением на экране. (В VB5 используется 9 таких окон: Immediate Window, Locals Window, Watches Window, Project Explorer, Properties Window, Object Browser, Form Layout, Toolbox и Color Palette.) Это означает, что для них установлен режим Dockable, снять который можно во вкладке Docking диалогового окна Options (меню Tools команда Options). Причем установка/снятие режима Dockable осуществляется отдельно для каждого окна (их список приведен во вкладке Docking).
Введя какую-либо информацию в текстовое окно, а затем нажав клавишу Enter, вы услышите звуковой сигнал. Чтобы избежать этого, запишите в событие KeyPress следующий код:
If KeyAscii = Asc(vbCr) Then KeyAscii = 0