Глава 4
Ввод и вывод
информации
В этой главе
рассматриваются различные возможности ввода и вывода информации в Visual Basic.
В частности, рассматриваются вопросы работы с мышью и клавиатурой, ввод и вывод
информации на различные носители данных (жесткий диск, дискета), а также на
экран и принтер.
Экран
В предыдущей главе вы
уже познакомились с некоторыми элементами управления, используемыми для ввода и
вывода. Кроме них, Visual Basic предоставляет и другие возможности вывода
информации на экран. В данном разделе описывается системный объект,
представляющий экран Windows, а также диалоговые окна для ввода и вывода.
Объект Screen
В Visual Basic объект
Screen представляет собой весь экран Windows. Начиная с Visual Basic 5.0,
наряду с объектом Screen существует и свойство Screen объекта Global.
Поскольку имеется
только единственный экран Windows, переменные типа Screen обычно не
объявляются, а используется системный объект Screen. Однако если такая
необходимость возникла, то переменная типа Screen перед использованием должна
не только объявляться, но и содержать действительную ссылку на реальный объект.
Например:
Dim scr
As Screen Set scr » Screen
Свойства объекта
Screen приведены в табл. 4.1.
Таблица
4.1. Свойства объекта Screen
Свойство |
Описание |
ActiveControl |
Активный элемент управления |
ActiveForm |
Активная форма |
FontCount |
Количество доступных шрифтов |
Fonts() |
Возвращает имена всех
доступных шрифтов |
Height |
Высота экрана |
Mouselcon |
Позволяет установить
пользовательскую пиктограмму для курсора |
MousePointer |
Тип указателя мыши |
TwipsPerPixelX |
Количество твипов (twips) в
пикселе (разрешение по горизонтали) |
TwipsPerPixelY |
Количество твипов (twips) в
пикселе (разрешение по вертикали) |
Width |
Ширина экрана |
Mouselcon/MousePointer
Свойство MousePointer
определяет внешний вид курсора мыши. Можно ис пользовать либо стандартные
курсоры Windows, либо создавать собственные.
Если для свойства
MousePointer установлено значение vbCustom, то для ото
бражения курсора мыши будет использоваться
пиктограмма, определяемая
свойством Mouselcon:
Screen.Mouselcon
LoadPicture("c:\Pointer.CUR")
Screen.MousePointer °= vbCustom
При этом допускается
использовать файлы пиктограмм (*.1СО) и файлы курсоров (*.CUR). Анимационный
курсор (*.ANI) свойством MousePointer не поддерживается.
Свойства Mouselcon и
MousePointer используются для информирования пользователя об определенном
состоянии системы. Так, в начале продолжительной процедуры можно установить
значение свойства MousePointer равным vbHourglass ("Песочные часы").
Это информирует пользователя о выполнении длительной операции и о том, что ему
следует дождаться ее окончания. Однако в конце процедуры свойство должно быть
изменено, о чем не следует забывать.
Свойство MousePointer
имеет нс только объект Screen. Есть оно и у формы. Если процесс затрагивает
операционную систему, то соответствующий указатель мыши должен устанавливаться
для объекта Screen. Если же операция не выходит за рамки приложения, то курсор
изменяется в форме.
В некоторых случаях с
помощью этих двух свойств почти для каждого элемента управления можно
предусмотреть собственный курсор мыши.
Height/Width
Свойства Height и
Width используются для определения размера объекта Screen, т.е. размера экрана.
В качестве единицы измерения используется твип. Эта единица измерения,
общепринятая в Windows, связана с выводом информации на печать и подробно
описывается ниже:
HeightInTwips = Screen.Height WidthInTwips =
Screen.Width HeightInPixel = Screen.Height / Screen.TwipsPerPixelX WidthInPixel
= Screen.Width / Screen.TwipsPerPixelY
Для того чтобы
пересчитать размер в твипах в пиксели, используются свойства TwipsPerPixelX И
TwipsPerPixelY.
ActiveControl
При написании кода,
который может быть использован повторно, не следует указывать явные имена элементов
управления. Если при этом важно определить, для какого элемента управления
установлен фокус, то для этого используют свойство ActiveControl объекта
Screen.
Например, в форме
находится два текстовых поля и с помощью кнопки нужно удалить выделенный текст
только в активном поле:
Private Sub cmdDelete_Click()
Textl.SelText =
""
Text2.SelText =
"" End Sub
•'•'i'^" ir Г
Приведенное в примере
решение некорректно, так как удаляется выделенный текст в обоих текстовых
полях.
Для корректного
решения поставленной задачи следует заменить конкретное имя на ActiveControl:
Private Sub
cmdDelete_Click() Screen.ActiveControl.SelText = "" End Sub
С помощью этой
процедуры удаляется выделенный текст только в активном элементе управления.
Могут возникнуть проблемы
и при использовании элементов управления различных типов. Необходимо
обеспечить, чтобы используемые свойства для ActiveControl фактически имелись в
активном элементе управления. Например, процедура cmdDelete_ciick для кнопки не
будет функционировать, так как при щелчке на кнопке фокус установится именно
для этой кнопки, а поскольку она не имеет свойства SelText, то последует
сообщение об ошибке: "Объект не поддерживает это свойство или метод".
Если же осуществить вызов процедуры из меню, то проблема будет решена, так как
команды меню не могут принимать фокус:
Private Sub
mnuDelete_Click() Screen.ActiveControl.SelText = "" End Sub
При разработке
приложения следует иметь в виду, что в форме могут быть элементы управления
различных типов, например TextBox и PictureBox. Поэтому если при нахождении
курсора в текстовом поле попытаться изменить свойство ActiveControl. Picture,
возникает ошибка.
Type Of
Использование
ключевого слова TypeOf позволяет проверить тип активного элемента управления.
Обычно его используют вместе с оператором if. . .Then:
Private Sub mnuDelete_Click()
If TypeOf
Screen.ActiveControl Is TextBox Then
Screen.ActiveControl.Seltext
=• "" Elself TypeOf Screen.ActiveControl
Is PictureBox Then
Screen.ActiveControl.Picture
= LoadPicture() End If End Sub
В этом примере
проверяется, какой тип имеет активный элемент управления
— TextBox или PictureBox, и в зависимости от
результатов проверки удаляется его содержимое.
Типы элементов
управления указываются также в окне свойств рядом с именем, элемента
управления.
ActiveForm
Свойство ActiveForm действует
аналогично ActiveControl, но содержит ссылку на активную форму:
Screen.ActiveForm.ActiveControl.SelText
= ""
Окно InputBox
Текстовое поле
требуется для ввода разнообразной информации. Но иногда требуется ввести только
краткую информацию, например значения даты или времени. Создавать для этого
отдельное текстовое поле или форму нерационально. Для ввода небольших
фрагментов текста Visual Basic предлагает функцию InputBox.
Окно InputBox состоит из четырех
элементов:
.
• строка заголовка;
.
• приглашение к вводу (Prompt);
.
• поле ввода со значением, предлагаемым по умолчанию;
.
• две кнопки (ОК и Cancel).
Функция вызова окна
inputBox имеет следующий синтаксис с соответствующими именованными аргументами:
Возвращаемое_значение InputBox(prompt!, title] [, default] _ [,
xpos] [, уроз] [, helpfile, context])
Параметр Prompt
определяет текст, отображающийся в диалоговом окне как приглашение. Title
отвечает за надпись заголовка; если этот параметр не указан, то отображаться
название приложения. Параметр Default; определяет значение по умолчанию,
отображаемое в строке ввода. Параметры xpos и ypos указывают координаты
верхнего левого угол окна. По умолчанию окно отображается посредине экрана. Параметры
xpos и ypos нужно использовать совместно:
strReturn InputBox ("Вопрос",
"Заголовок", "Заданное значение") If strReturn "" Then Exit Sub'
Функция inputBox
возвращает строку, введенную пользователем. При нажатии кнопки Cancel
возвращается пустая строка.
Функция InputBox
имеет еще два необязательных параметра — HelpFile и Context, которые позволяют
открывать определенные файлы справочной системы.
Область применения
Возможно, это
диалоговое окно вам не слишком знакомо из других приложений. Оно почти не
встречается в стандартных приложениях Windows, так как выглядит не слишком
привлекательно. Вам также следует отказаться от использования InputBox в
готовом приложении. Однако это окно имеет смысл использовать на этапе
проектирования, если вам необходимо временно ввести информацию с помощью
InputBox. Большим преимуществом является то, что вызов этой функции легко
удалить из программы, так как он содержит только одну строку. Но переменная,
содержащая возвращаемое значение, и проверка этого значения нужны и в
окончательной редакции программы.
Окно MessageBox
Ддя вывода различных
сообщений имеется окно, подобное InputBox, — Mes sageBox. Почти все приложения
Windows используют MessageBox, так как этот компонент входит в состав Windows,
a Visual Basic только предоставляет возможность его вызова.
Вид окна MessageBox может быть различным
(рис. 4.5), но в его состав всегда ВХОДЯТ:I
.
• текст сообщения;
.
• заголовок;
.
• пиктограмма;
.
• набор кнопок.
Гчс. 4.^. Различные
варианты икни "... ',;.\;^ri,,x
MessageBox можно вызывать как процедуру и как
функцию.
Синтаксис
команды
MsgBox Prompt [, Buttons]
[, Title] [, Helpfile, Context]
Синтаксис
функции
Возвращаемое_значение
= MsgBox (Prompt [, Buttons] [, Title] _ [, Helpfile,
Context])
MsgBox "Здравствуй, пользователь",
vbExclamation, "Приветствие"_
'команда
ret = MsgBox ("Закончить?", vbCritical, "End") 'функция
Параметры Prompt и
Title не требуют пояснении. Параметр Buttons опреде ляет внешний вид
MessageBox. Значение параметра формируется из нескольких частей, которые можно
складывать:
Buttons
= Button + Icon + Default + Modal + Extras + Extras
Для категорий параметра Button, Icon, Default
и Modal можно использовать только одну из допустимых констант. А для категории
Extras допускается применение комбинации значений.
Таблица
4.2. Константы функции HsgBox
Константа |
Значение |
Описание |
Категория: Button |
|
|
vbOKOnly |
0 |
Только кнопка OK |
vbOKCancel |
1 |
Кнопки OK и Отмена |
vbAbortRetryIgnore |
2 |
Кнопки Стоп, Повторить и
Пропустить |
vbYesNoCancel |
3 |
Кнопки Да, Нет и Отмена |
vbYesNo |
4 |
Кнопки Да и Нет |
vbRetryCancel |
5 |
Кнопки Повторить и Отмена |
Категория: Icon |
|
|
vbCritical |
16 |
Отображает пиктограмму
Critical Message |
vbQuestion |
32 |
Отображает пиктограмму
Warning Query |
vbExclamation |
48 |
Отображает пиктограмму
Warning Message |
vbInformation |
64 |
Отображает пиктограмму Information Message |
Категория: Default |
|
|
vbDefaultButton! |
0 |
По умолчанию активна первая
кнопка |
vbDefaultButton2 |
256 |
По умолчанию активна вторая
кнопка |
vbDefaultButton3 |
512 |
По умолчанию активна третья
кнопка |
vbDefaultButton4 |
768 |
По умолчанию активна
четвертая кнопка |
Категория: Modal |
|
|
vbApplicationModal |
0 |
Модальное диалоговое окно
приложения |
vbSystemModal |
4096 |
Модальное диалоговое окно
системы |
Категория: Extras |
|
|
vbMsgBoxHelpButton |
16384 |
Дополнительная кнопка для
справки |
vbMsgBoxSetForeground |
65536 |
Отображение диалогового окна в фоновом ре |
|
|
жиме |
vbMsgBoxRight |
524288 |
Текст выровнен по правому
краю |
vbMsgBoxRtlReading |
1048576 |
Текст отображается справа налево (еврейский, |
|
|
арабский) |
Например, вы хотите, чтобы в окне MessageBox
отображались вопросительный знак, кнопки Да и Нет, и при этом кнопка Нет была
кнопкой по умолчанию. Кроме того, окно должно быть модальным окном приложения,
т.е. выполнение приложения продолжается только после закрытия окна. Для этого
следует просуммировать соответствующие значения. Так как всем символьным
константам Visual Basic соответствуют числовые значения, код, реализующий
перечисленные требования, мог бы выглядеть следующим образом:
type = 4 + 32 + 256 + О
MsgBox "Сообщение", type, "Заглавие"
Однако такой вариант
вызова, использующий числовые значения, без комментариев понять трудно, поэтому
лучше применять соответствующие константы:
type = vbYesNo Or vbQuestion
Or vbDefaultButton2 Or_ vbApplicationModal MsgBox "Сообщение", type,
"Title"
Оператор Or
Обратите внимание,
что корректное суммирование значении констант выполняется оператором Or. Однако
можно применить и операцию арифметического суммирования. В этом случае следует
использовать только одну константу из категории Button,Icon, Default и Modal.
После нажатия кнопки
пользователем следует проанализировать возвращаемое функцией значение:
ret = MsgBox
("Хотите?", vbYesNo Or vbQuestion, strUserName)
Возвращаемое функцией
значение позволяет определить, какую кнопку нажал пользователь.
Таблица 4.3. Значения, возвращаемые функции
MsgBox
Константа Значение
Нажата кнопка
vbOK |
1 |
OK |
vbCancel |
2 |
Отмена |
vbAbort |
3 |
Стоп |
vbRetry |
4 |
.Повторить |
vblgnore |
5 |
Пропустить |
vbYes |
6 |
Да |
vbNo |
7 |
Нет |
Теперь становится
понятен различный синтаксис вызовов функции. Синтаксис процедуры предназначен
для окна сообщения (MessageBox) с одной кнопкой, так как в этом случае
возвращаемое значение не столь важно. Однако при запросах требуется вызывать
MsgBox как функцию, так как возвращаемое значение используется для
определения.кнопки, нажатой пользователем:
Select Case MsgBox
("Вопрос", vbAbortRetryIgnore Or vbQuestion, "Заглавие")
Case vbAbort Call Abort Case vbRetry Call Retry Case vblgnore Call Ignore End
Select
Область применения
Следует корректно
использовать окно MessageBox в приложении. Обычными для него являются вопросы
типа "Хотите ли вы сохранить изменения в ...?" (Да/Нет/Отмена).
Вопрос должен формулироваться четко и ясно, чтобы пользователь мог дать на него
однозначный ответ.
Кнопка Default (кнопка,
которая является активной по умолчанию) должна определяться таким образом,
чтобы при случайном нажатии клавиши [Enter] действия, реализуемые в процедуре
обработки нажатия кнопки по умолчанию, нс могли нанести большого вреда.
Например, не следует в окне с вопросом "Удалить все внесенные
изменения?" (Да/Нет) назначать кнопку Да кнопкой по умолчанию.
Окно MessageBox
используется также для того, чтобы сообщить пользователю о результатах
выполнения программой определенных действий, например о том, что
"Регистрация в базе данных нс удалась". В этом случае следует
выводить только те сообщения, которые действительно важны (например, при
невыполнении важной операции).
Клавиатура
Основными
устройствами, с помощью которых пользователь взаимодействует с приложением и
операционной системой, являются клавиатура и мышь. Клавиатура, как правило,
используется для ввода данных, а мышь — для управления рабочей средой. В этом
разделе подробно рассматривается клавиатура.
Фокус
Основной проблемой
при использовании клавиатуры является то, что для обслуживания множества
элементов управления имеется только одна клавиатура. Поэтому система должна
определить, какому элементу управления передается вводимая с клавиатуры
информация. В связи с этим в Windows используется понятие "фокус".
Если говорят, что элемент управления имеет фокус, это означает, что Ввод
информации с клавиатуры относится к этому элементу.
Элемент, имеющий фокус,
можно распознать по различным визуальным признакам. Чаще всего это мигающий
курсор или пунктирная рамка.
Фокус устанавливается
в результате щелчка на элементе управления. После этого элемент управления
может принимать информацию от клавиатуры.
Несмотря на то, что
Windows ориентирована работу с мышью, диалоговые окна и меню следует
разрабатывать с учетом возможности использования клавиатуры. Рабочий процесс
можно ускорить, если при длительном вводе с клавиатуры предоставить возможность
перемещать фокус также с помощью клавиатуры, без использования мыши.
Горячие клавиши
В Windows почти во
всех надписях на элементах управления есть подчеркнутые символы. С помощью
клавиши [Alt] и этого символа можно переместить фокус на этот элемент
управления или выполнять соответствующее действие. Например, посредством
нажатия клавиш [Alt+F] можно вызвать команду меню File, не пользуясь
мышью.
В Visual Basic при
помощи свойства Caption можно задать горячую клавишу путем установки перед
нужной буквой символа амперсанд (коммерческое И — &), воспользовавшись
окном свойств:
rnnuFile.Caption ° "SFile"
Для того чтобы
использовать амперсанд в надписи, нужно поставить два таких знака.
IblDragDrop.Caption "DragsSDrop"
UseMnemonic
Можно также
отобразить символ & в тексте Caption, не прибегая к указанию двух знаков
амперсавда. Для этого надо установить значение свойства UseMnemonic равным
False.
Клавиша табуляции
Перемещать фокус
можно также с помощью клавиши [Tab]. При нажатии этой клавиши происходит
переход к следующему элементу управления формы, при нажатии [Shift+Tab] — к
предыдущему. Порядок перехода между элементами управления в Visual Basic по
умолчанию совпадает с порядком добавления элементов в форму, но при
необходимости его можно изменить.
Tablndex
Все элементы
управления, для которых возможно установить фокус, обладают свойством Tablndex.
Элемент управления, у
которого свойство Tablndex равно 0, получает фокус сразу после загрузки формы.
После каждого нажатия клавиши [Tab] фокус переходит к элементу со следующим
значением Tablndex.
Последовательность
переходов при нажатии клавиши [Tab] следует создавать таким образом, чтобы
пользователь мог проследить ее логически, а не искать активный элемент
управления. Для этого следует корректно присваивать значения свойству Tablndex,
помня, что Visual Basic препятствует заданию одинакового индекса Tablndex для
двух элементов управления.
Элемент управления
Надпись (Label) также имеет свойство Tablndex, хотя и не может принимать фокус.
Благодаря этому свойству, можно назначать горячие клавиши
другим элементам
управления, не имеющим собственного свойства Caption (например, текстовое
окно). Для этого значение свойства Tablndex надписи должно быть на единицу
меньше, чем значение такого же свойства самого элемента управления.
На рисунке вы видите
диалоговое окно открытия файлов Windows 95. При открытии окна фокус установлен
для поля ввода File name (Имя файла). Надпись File name включена
в Tabпоследовательность (последовательность перехода) с этим полем, т.е.
нажатием комбинации клавиш [Alt+N] можно передать фокус текстовому полю File
name.
TabStop
Для удаления элемента
управления из последовательности переходов табуляции нужно установить равным
False значение его свойства TabStop. В этом случае фокус элементу управления
можно установить только с помощью мыши.
События, связанные с клавиатурой
Ввод с клавиатуры
может обрабатываться не только Windows, но и непосредственно элементами
управления. Для этого необходимо обрабатывать события: KeyDown, Keypress и
KeyUp. При нажатии клавиши для активного элемента управления генерируются
соответствующие события.
Keypress
В качестве параметра
процедуре обработки события Keypress передается переменная KeyASCll, содержащая
ANSIкод нажатой клавиши. Такое имя (KeyASCll) немного вводит в заблуждение, но
различие между ASCII и ANSI кодом клавиши важно только для символов с кодом
больше 127.
Private Sub
Textl_KeyPress (KeyAscii As Integer) MsgBox KeyAscii End Sub
В примере код нажатой клавиши выводится в
окне сообщений, если фокус при надлежит элементу управления с именем Textl.
Если нажата, например, клавиша [А], то в окне сообщений выводится значение 65.
Обратите внимание, что KeyASCll — это не
свойство, а переменная. Следова тельно, выражение вида Textl .KeyAscii не может
использоваться в коде.
Значение переменной
KeyASCll можно не только считывать, но и устанавливать. Поэтому возможна замена
введенного с клавиатуры символа другим:
KeyAscii = Asc(UCase(Chr(KeyAscii)))
В этом примере
функция Chr преобразует ANSIкод клавиши в соответствующий текстовый символ. С
помощью функции ucase этот символ преобразуется в прописной, а затем функция
Asc преобразует его в ANSIкод. Это значение опять присваивается переменной
KeyASCll, и соответствующий символ появляется в элементе управления. Таким образом
все вводимые с клавиатуры символы преобразуются в прописные.
KeyUp/KeyDown
Событие Keypress
вызывается только при нажатии клавиш, имеющих ANSI код. А нажатие, например,
клавиш управления курсором или функциональных это событие не вызывает. Для
обработки нажатия этих клавиш следует использовать СОбыТИЯ KeyUp И KeyDown.
Private Sub
Textl_KeyDown(KeyCode As Integer, Shift As Integer) MsgBox KeyCode End Sub
Процедурам обработки
этих событий передаются две переменные: KeyCode и Shift. Параметр KeyCode содержит
клавиатурный код нажатой клавиши, a shift позволяет определить состояние клавиш
[Shift], [Ctrl] и [Alt].
На рисунке показаны
значения, возвращаемые переменной KeyCode для клавиш стандартной клавиатуры.
Значения кодов
отдельных клавиш можно добавить в программу как константы, воспользовавшись
каталогом объектов.
Таблица 4.4.
Константы параметра shift Константа Значение Описание
vbShiftMask 1
vbCtrlMask 2 vbAltMask 4 Нажата клавиша [Shift] Нажата клавиша [Ctrl] Нажата
клавиша [Alt]
В качестве констант
для аргумента shift используются вышеуказанные
значения. При работе
с клавиатурой события происходят в такой
последовательности:
KeyDown,Keypress,
KeyUp.
KeyPreview
Обычно события
клавиатуры генерируются для активного элемента управления. Но нажатие некоторых
клавиш, например функциональных, должна обрабатывать форма, а не активный
элемент управления. Поэтому форма также может обрабатывать события KeyDown,
Keypress и KeyUp, но для этого необходимо установить равным
True значение
свойства формы KeyPreview. В этом случае все события клавиатуры сначала будет
обрабатывать форма, а лишь затем активный элемент управления.
Private Sub Form_KeyDown(KeyCode As Integer,
Shift As Integer) If KeyCode
»~vbKeyF4 Then
MsgBox "Нажата
F4" Elself KeyCode vbKeyF4 And
Shift =
vbShiftMask Then
MsgBox "Нажаты F4 и Shift" End If End ^ub
В данном примере
значение свойства KeyPreview формы равно True, поэтому все нажатия клавиш
сначала будет обрабатывать форма. Если нажать клавишу [F4] или [Shift+F4], то
процедура FormJKeyDown проанализирует нажатие клавиши и выведет соответствующее
сообщение независимо от того, для какого элемента управления установлен фокус.
SendKeys
Visual Basic
позволяет не только обрабатывать реальные нажатия клавиш клавиатуры, но и
имитировать такие нажатия. С помощью оператора SendKeys код, имитирующий
нажатие клавиши, записывается непосредственно в буфер клавиатуры. Система при
этом не отличает такой ввод от "настоящего" ввода.
ScndKey Ctrl [, Wait]
С помощью именованного
параметра Wait можно определить режим ожидания обработки имитации нажатия
клавиши. Если значение параметра равно False (по умолчанию), то управление
возвращается процедуре немедленно после посылки сообщения о нажатии клавиш.
Если же его значение равно True, сообщение должно быть обработано, прежде чем
управление будет передано процедуре.
Реальный ввод с
клавиатуры либо имитация нажатия клавиш с помощью оператора SendKeys всегда
передается активному элементу управления. Для того чтобы вводимые символы
передавались нужному приложению, необходимо сначала передать ему фокус.
SendKeys
"+1F1)" ' Посылает Shift F1 в буфер клавиатуры
Эта строка имитирует
нажатие клавиш [Shift+Fl].
AppActivate
В
Visual Basic для передачи фокуса приложению существует оператор AppActivate:
AppActivaf Title [, Wait]
Параметр Title
оператора — это текст строки заголовка (значение свойства Caption) приложения,
которое нужно активировать. Текст должен слово в слово совпадать со значением
свойства Caption. При этом не имеет значения вид написания — прописными буквами
или строчными.
Private Sub Comn>andl_Click()
ret =
Shell("calc.exe", vbNormalFocus)
AppActivate
"Калькулятор", False
SendKeys
"1(+>2 = "C %(F4)", True
Textl.Text »
Clipboard.GetText() End Sub
В данном примере
запускается стандартная программа — калькулятор Windows. Затем суммируются
числа 1 и 2, результат вычисления копируется в буфер обмена и калькулятор
закрывается.
Мышь
Вторым важным
устройством ввода в Windows является мышь. .Все действия, выполняемые мышью
(щелчки, перемещения) также можно анализировать, для чего генерируется ряд
событий.
Таблица 4.5. События мыши
Событие |
Описание |
Click |
Одинарный щелчок мыши |
DblClick |
Двойной щелчок |
MouseDown |
Нажатие кнопки мыши |
MouseUp |
Отпускание кнопки мыши |
MouseMove |
Перемещение указателя мыши |
DragDrop |
Отпускание кнопки мыши в
режиме Drag&Drop |
|
(перетаскивание) |
DragOver |
Перемещение мыши в режиме
Drag&Drop (перетаскивание) |
Событие Click
Самым важным событием
мыши является Click. Оно наступает, когда пользователь щелкает мышью на
элементе управления. Однако для Windows Click состоит из двух событий: нажатия
и освобождения кнопки мыши.
Событие Click может
наступить и при изменении значения определенного свойства элемента управления.
Например, для ListBox событие click вызывается и тогда, когда с помощью клавиш
перемещения курсора выбирается новый элемент списка. ,:
Многие элементы
управления могут обрабатывать событие click: Form, CommandButton, Label,
PictureBox,OptionButton, ListBox, ComboBox и т.д.
Private Sub Comniandl_Click ()
Событие click можно также
вызывать программно — для этого следует изменить свойство Value
(CommandButton).
Событие DblClick
Событие DblClick
вызывается, если выполняются два щелчка за промежуток времени, определяемый
значением параметра Скорость двойного нажатия, который
устанавливается на
вкладке Кнопки мыши диалогового окна СвойствагМышь. Если в этом
промежутке времени не регистрируются два щелчка, генерируется не событие
Dbiciick, а два последовательных события Click. С помощью двух последовательных
нажатий кнопки мыши, вызывающих события Click, можно выделить элемент списка,
однако только после двойного щелчка, вызвавшего событие Dbiciick, будет
выполнена соответствующая операция, например открытие файла или запуск
программы.
События MouseDown и MouseUp
Если требуется более
детальный анализ нажатия кнопки мыши, то следует обрабатывать отдельно нажатие
и отпускание кнопки мыши. После нажатия кнопки мыши на активном элементе
управления генерируется событие MouseDown. При этом процедуре обработки этого
события передаются четыре параметра: Button, Shift, x и Y. Событие MouseUp
функционирует аналогично MouseDown, но наступает при отпускании кнопки мыши.
Private Sub Form_MouseDown(Button As Integer,
Shift As Integer, _
X As Single, Y As Single) Select Case
Button Case
vbLeftButton
MsgBox "Нажата
левая кнопка" Case
vbRightButton
MsgBox "Нажата
правая кнопка" Case
vbMiddleButton
MsgBox "Нажата средняя кнопка" End Select End Sub
Параметр Button определяет
состояние кнопки мыши. Он может принимать одно из следующих значений: vbLeftButton,
vbRightButton или, если имеется третья кнопка мыши, vbMiddleButton. Параметр
Shift позволяет определить, были ли нажаты клавиши [Shift] (vbShiftMask),
[Ctrl] (vbCtrlMask) и [Alt] (vbAltMask) при нажатии или
отпускании кнопки мыши. Переменные X и Y содержат значения координат текущей
позиции курсора мыши на элементе управления.
Событие MouseMove
При перемещении мыши
наступает множество событий MouseMove. Процедуре обработки этого события
передаются такие же переменные, как и при обработке событий MouseUp и
MouseDown. Аргумент Button позволяет определить, какая кнопка мыши была нажата
не только при обработке событий MouseUp и MouseDown, но и при обработке события
MouseMove. Таким образом, можно узнать была ли нажата кнопка во время
перемещения мыши. Обрабатывая события MouseUp, MouseDown и MouseMove, можно
создать простейшую программу рисования.
При нажатии левой
кнопки мыши с помощью метода PSet ставится точка в том месте формы, в котором в
данный момент находится указатель мыши. После этого курсор принимает форму
перекрестия:
Private Sub
Form_MouseDown(Button As Integer, Shift As Integer, _ X As Single, Y As Single)
If
Button = vbLeftButton Then Formi.MousePointer = vbCrosshair Forrol.PSet (X,Y)
End If End Sub
При перемещении мыши
наступает последовательно несколько событий MouseMove. Если при перемещении
была нажата левая кнопка мыши, то точки, в которых эти события произошли,
соединяются линией с помощью метода Line:
Private Sub
Form_MouseMove(Button As Integer, Shift As Integer, _ X As Single, Y As Single)
If Button = vbLeftButton Then Forml.Line
(X, Y) End If End Sub
При
отпускании кнопки мыши курсор принимает первоначальный вид:
Private Sub Form_MouseUp(Button As Integer,
Shift As Integer, _
X As Single, Y As Single) Formi.MousePointer = vbDefault End Sub
Этот небольшой пример
демонстрирует возможности использования событий мыши.
Последовательность событий
Последовательность
генерации событий мыши зависит от типа элемента управления, для которого эти
события генерируются. Например, для элементов управления ListBox и
commandButton события наступают в следующем порядке: MouseDown, Click,
MouseUp. Для FileListBox, Label или PictureBox события
наступают в другой последовательности: MouseDown, MouseUp, Click. При
двойном щелчке события происходят в последовательности: MouseDown, MouseUp,
Click, DblClick, MouseUp.
Файлы
' Итак, вы
познакомились с некоторыми средствами ввода информации. Однако эту информацию
зачастую требуется не только анализировать, но и сохранять. Для сохранения
информации предназначены операторы обработки файлов, позволяющие считывать и
сохранять данные на различных носителях (гибкий либо жесткий диск и т.п.).
Процесс открытия и сохранения файлов состоит из нескольких этапов:
.
• получение дескриптора файла (handle);
.
• открытие файла;
.
• чтение или запись данных;
.
• закрытие файла.
Дескриптор
файла
Чтобы работать с
файлами, нужно понимать, как связывается система или приложение с файлом. Для
этого имеется канал ввода/вывода. При открытии файлу ставится в соответствие
канал с определенным номером. Таким образом, каждый открытый файл имеет
собственный канал, с помощью которого записываются или считываются данные.
Следовательно, для ввода и вывода данных в файл имеет значение не имя файла, а
номер канала. Кроме того, операционная система должна иметь сведения о наличии
свободных каналов, которые можно использовать для открытия файла.
FreeFile
Функция Visual Basic FreeFile возвращает
номер свободного канала, который можно использовать для работы с файлом. Fr**Tile[(KangeNumber)]
Если свободных
каналов нет (открыто максимально допустимое количество файлов), возникает
ошибка выполнения.
intFH FreeFile ()
В этом примере
переменной intFH присваивается целое значение, которое можно использовать для
открытия файла. Необязательный параметр RangeNumber позволяет определить
диапазон значений, из которого выбирается очередной свободный номер канала.
Если его значение равно 0 (по умолчанию), то возвращается номер канала из
диапазона 1 — 255, если 1, то из диапазона 256 — 511.
Типы
доступа
В Visual Basic реализованы три типа доступа к
файлам:
.
• последовательный (Sequential) — для чтения и записи
текстовыхфайлов;
.
• произвольный (Random) — для чтения и записи текста или
структурированных двоичных файлов с записями фиксированной длины;
.
• двоичный (Binary) — для чтения и записи
произвольноструктурированных файлов. При создании коммуникационных каналов
система должна знать,
какой тип доступа к каждому конкретному файлу
нужно использовать и какова структура данных этого файла.
Последовательный
доступ
Последовательный доступ используется
главным образом при работе с текстовыми файлами. Любая информация считывается
или сохраняется в текстовом виде построчно. В тексте могут находиться символ
перевода строки (vbCrLf или chr (13) & Chr (10)) или табулятор (vbTab или
chr (9)). Эти символы используются для форматирования текста.
Способ открытия файла
с последовательным доступом (для чтения, записи или добавления) задается при
вызове оператора Open:
Open Имя файла For [Input I Output I Append] As filehandle
Таблица 4.6. Различные
операционные возможности для последовательного доступа Ключевое слово |
Описание |
Input |
Открытие только для чтения иэ
файла |
Output |
Открытие для записи в файл |
Append |
Открытие для добавления к
файлу |
Если файл не существует и открывается для чтения (For
input), то Visual Basic выдает сообщение об ошибке, а если для записи или
добавления (Output или Append), то создается новый файл. Если файл с указанным
именем существует, то в режиме Output его содержимое удаляется, а в режиме
Append файл открывается для добавления:
Open "C:\README.TXT" For Input
As intFHl Open "C:\DATA\TEXT.TXT" For Output As intFH2 Open
"C:\USERS.TXT" For Append As intFH3
В конце строки указывается
номер канала, возвращаемый функцией FreeFile. В некоторых операционных
системах, например в Windows 95/98, можно исполь зовать длинные имена файлов.
Чтение из файла
Для считывания данных
из файла, открытого для последовательного доступа, существует несколько
возможностей. В общем случае это осуществляется с помощью оператора input,
имеющего несколько разновидностей:
.
• Line lnput# считывает одну строку;
.
• I при t # считывает последовательность символов, обычно
записанных с помощью оператора Write#;
.
• input $ считывает определенное количество символов.
Существует несколько
вариантов чтения всей информации из файла. Перед чтением нужно открыть файл с
помощью оператора Open.. . For:
intFH = FreeFile Open
"С:\Text.Txt" For Input As
intFH
'1ый вариант Do Until
EOF(intFH)
Line Input #intFH,
strString
strText = strText
& strString & vbLf Loop
'2ой вариант StrText
= Input$(LOF(intFH), intFH) Close *intFH
Оба варианта приводят
к одинаковому результату.
В первом варианте
оператор Input выполняется в цикле, пока не будет достигнут конец файла.
Функция EOF
(End Of
File) возвращает значение True при достижении конца файла. При этом на каждом
шаге цикла считывается отдельная строка и к ней добавляется символ конца
строки, который отбрасывается оператором Line input.
Во втором варианте весь файл считывается
функцией lnput$. Функция LOF (Length Of File) позволяет определить длину файла
в байтах.
Заметим также, что
независимо от вида оператора Input указывается не Имя файла, а только номер
канала, т.е. дескриптор файла (intFH).
Close
Оператор Close
предназначен для закрытия открытого файла или канала.
Запись
в файл
В Visual Basic для
записи информации в файл используются операторы print# и Write».
Print»
Оператор Print#
функционирует почти так же, как его "коллега" для экрана, с той лишь
разницей, что данные не выводятся на экран, а сохраняются в файле, открытом для
записи или добавления (Open.. .For Output или Open.. .For Append).
Vfintffilehandle, [(Spc(n) I
Tab[(n)]l] [expression] [charpos]
Синтаксис оператора
на первый взгляд выглядит сложно:
Print #intFH, Textl.Text
Print #intFH, "Фрагмент I", " Фрагмент 2"
Print #intFH, "Это составляет "; "единое целое"
Для форматирования
записываемой в файл информации следует поразному разделять данные в операторе
print. Если в операторе данные разделять запяты ми (,), то в файле они будут
разделены символами табуляции:
Print #intFH, "Фрагмент I", "
Фрагмент 2"
'соответствует
Print #intFH, "Фрагмент I"; Tab; "Фрагмент 2"
Если же в операторе
для разделения данных использовать точку с запятой (;), то данные в файл
записываются без разделителей:
Print #intFH, "Это составляет ";
"единое целое"
'соответствует
Print #intFH, "Это составляет единое целое"
Write»
Оператор Write# имеет
такой же синтаксис, что и print#. Отличие состоит только в форматировании
вывода. Если Print» сохраняет данные в виде обычного текста, то writer
заключает текстовые строки в кавычки, а цифры выводятся без кавычек:
Print #intFH,
"Анна", "Киев", 17 ' в файле будет: Анна Киев 17 Write
#intFH, "Анна", "Киев", 17 ' в файле будет:
"Анна","Киев",17
Данные, сохраненные с
помощью оператора write*, можно считать оператором Input».
Произвольный доступ
Доступ типа Random
Access несколько утратил свое значение после появления в версии Visual Basic 3.0
средств доступа к базам данным. В отличие от последовательного доступа, при
котором данные в файлах хранятся в неструктурированном виде, произвольный
доступ предполагает, что файл имеет постоянную структуру. Это позволяет
считывать данные в произвольном порядке.
Произвольный доступ
реализуется посредством оператора Open. Open Имя_файла For Random [Acc««e Доступ] [Блокировка]
As
[#]HandJe [ben = Длина_записи}
Параметр Len
определяет длину записи. Если это значение меньше, чем реальная длина записи,
то возникает ошибка, если больше — то при записи файла используется больше
дискового пространства, чем необходимо.
Параметр Access
позволяет задать права доступа к открываемому файлу.
Таблица 4.7. Виды
доступа при произвольном доступе
Доступ Пример
Без указанияOpen "DATE.DAT For
Random As intFH
Чтение (Read) |
Open "DATE.DAT' For
Random Access Read As intFH |
Запись(Write) |
Open "DATE.DAT' For
Random Access Write As intFH |
Чтение и запись |
Open "DATE.DAT' For Random Access Read Write As intFH |
(Read Write) |
|
Если
права доступа не указаны, то по умолчанию используется Read Write. Так как этот
тип доступа обычно предназначен для работы с файлами, которые могут
использоваться многими пользователями или приложениями, то следует обеспечить
целостность данных при коллективном использовании. Для этого следует установить
параметр Lock, определяющий права доступа к открытому файлу. Этот параметр
может принимать следующие значения:
.
• SharedФайл
может использоваться всеми процессами для считывания и записи.
.
• Lock ReadНикакой
другой процесс не может считывать данные из файла. Данный параметр можно
установить, если в данный момент никакой другой процесс не выполняет операцию
чтения.
.
• Lock WriteНикакой
другой процесс не может записывать данные в файл. Данный параметр можно
установить, если в данный момент никакой другой процесс не выполняет операцию
записи.
.
• Lock Read
WriteНикакой другой процесс не может считывать или записывать. Данный параметр
можно установить, если в данный момент не выполняются операции чтения или
записи.
Параметр Len задает длину одной записи. Для задания
длины можно использовать функцию Len:
Open "ADDRESS.DAT" For Random Access Write
As 1 Len = 27 Open "ADDRESS.DAT" For Random Access Write As 1 Len = Len(Varname)
При этом важно, чтобы
при открытии файла была известна длина набора данных, что может быть
проблематичным, если происхождение файла неизвестно.
Ввод и вывод
Get, Put
Для
записи и чтения данных используются соответственно операторы put и Get.
Put #fS,lehandler,
Ноыер_записи, Переменная Get
ffilehandler, Номер_эаписи, Переменная
В данном примере в
файл записываются данные из переменной Addres s, причем номер записи равен 7, а
затем в переменную Address считывается вторая запись файла.
Put #intFH, 7,
Address 'сохраняет 7ую запись Get #intFH, 2, Address 'считывает 2ую запись
Для того чтобы в
одной записи сохранить несколько значений различных типов, следует использовать
пользовательские типы данных:
(General)(Declaration)
Type Person
FirstName As String *
20
Name As String * 20
CustomerN As Integer
End
Type
Private
Customer As Person 'Процедура Private Sub Commandl_Click()
intFH = FreeFile
Open
"C:\LORE.DAT" For Random As intFH Len = Len(Customer)
Get tintFH, 2,
Customer
Close #intFH End
Sub
Двоичный доступ
Двоичный доступ
незначительно отличается от произвольного доступа. Разница состоит только в
том, что двоичный доступ возможен не к определенному набору данных, а к
отдельному байту внутри любого файла.
Open
Для открытия
двоичного файла также используется оператор Open.
Open Имя_фачла For Binary [Асеева Доступ] [Блокировка)
As [f]Handle
При печати из Visual Basic
используются три компонента:
.
• код Visual Basic, управляющий процессом печати;
.
• подсистема печати Windows, которая готовит документ и
передает его на принтер;
.
• устройство печати (принтер) с определенными техническими
характеристиками.
В настоящей главе
рассматриваются различные типы шрифтов, использующиеся при печати, возможности
программного вывода на принтер, а также управление процессом печати Windows
(диалоговое окно принтера, назначение стандартного принтера и др.).
Шрифты
Windows
поддерживает следующие типы шрифтов, различаемые по способу вывода шрифта на
экран или принтер:
.
• экранные шрифты;
.
• принтерные шрифты.
Технологии шрифтов Windows
Различия в шрифтах
вызывают проблему отображения данных на экране, если, например, в документе
применяется принтерный шрифт, не являющийся экранным. В Windows используются
шрифты следующих типов:
.
• растровые;
.
• векторные;
.
• TrueType (контурные);
.
• принтерные.
Шрифты Windows можно
подразделить также на масштабируемые и не масштабируемые. Размер
масштабируемого шрифта может изменяться произвольно. Для немасштабируемых
шрифтов размер символов может принимать только строго фиксированные значения,
заданные в файле шрифта.
Растровый шрифт
Для растрового шрифта
все символы хранятся в файле в виде растровых изображений и выводятся на экран
или принтер как массивы точек. Растровые шрифты не являются масштабируемыми.
Для того, чтобы уменьшить объем файла шрифта, следует ограничить набор
доступных размеров и максимальный размер символов шрифта.
В окне настройки
шрифтов (Панель управления\Шрифты) растровые шрифты легко узнать по
пиктограмме в виде красной буквы А с указанными в названии размерами.
Векторный шрифт
Векторные шрифты
создаются путем соединения заданных точек прямой линией. В связи с тем, что
расстояние между точками может легко изменяться, векторные шрифты являются
масштабируемыми. Шрифты этого типа поставляются Windows (начиная с версии 3.0).
В окне настройки
шрифтов (Панель управления\Шрифты) векторные шрифты также отображаются
пиктограммой в виде красной буквы А, но без указания размера. (Размер может не
указываться и для некоторых растровых шрифтов.) В Windows 3х поставлялись
векторные шрифты "Modem", "Script" и "Roman", а
начиная с Windows 95 — только "Modem".
Шрифт TrueType (контурный)
Начиная с версии 3.1,
Windows поддерживает шрифты TrueType. Для шрифтов этого типа заданные точки
соединяются прямыми или кривыми линиями, формируя контурное очертание символа.
Изображение символа получается путем закрашивания этого контура. Поэтому
шрифтовые файлы относительно малы. Шрифты этого типа являются свободно
масштабируемыми.
Преимущество этой
технологии в том, что созданные шрифты могут выводиться как на экран, так и на
принтер, при этом соблюдается принцип WYSIWYG ("What you see is what you
get" — "Что видите, то и получаете").
Поскольку эта
технология известна под названием "TrueType", на пиктограмме шрифтов
этого типа изображены две буквы т — серая и голубая.
Принтерные шрифты
В отличие от шрифтов
других видов, принтерные шрифты хранятся не в файле, а встроены в устройство
печати. Количество шрифтов зависит от модели принтера. Некоторые модели
позволяют подключать дополнительные шрифты.
Принтерные шрифты не
видны в окне настройки шрифтов (Панель управления\Шрифты). Их можно
увидеть только в диалоговом окне выбора шрифта, где рядом с именем шрифта
расположена пиктограмма с изображением принтера.
Если для
форматирования текста документа используется принтерный шрифт, то для его
отображения на экране Windows использует экранный шрифт, наиболее близкий по
начертанию к принтерному. Если же выбранный экранный шрифт далек от исходного
принтерного, то могут возникнуть неожиданные эффекты (например, полное
искажение текста документа), что нужно учитывать при выборе шрифта.
Объект Font
Для выбора и
установки параметров шрифта (наименование, размер, дополнительные атрибуты) в
Visual Basic существует объект Font. Этот объект определяет вид шрифта другого
объекта (TextBox, Form, Printer и т.д.).
Объект Font имеет ряд
свойств, с помощью которых выполняются нужные установки.
Таблица 4.8. Свойства объекта Font
Свойство |
Описание |
Name |
Название шрифта |
Size |
Размер шрифта |
Bold |
Полужирное начертание |
Italic |
Курсивное начертание |
StrikeThrough |
Перечеркивание |
Underline |
Простое подчеркивание |
Weight |
Толщина символов шрифта |
Font. Name
Свойство Name объекта
Font содержит имя шрифта. Чтобы просмотреть список всех шрифтов, доступных для
использования, можно воспользоваться свойством Fonts объекта Printer или Screen
(принтерные или экранные шрифты):
For i = 0 То
Screen.FontCount 1 IstFont.AddItem
Screen.Fonts(i) Next i
Свойство FontCount возвращает количество доступных шрифтов.
Font. Size
Свойство size
указывает размер шрифта в пунктах и может принимать значения в диапазоне от 1
до 2160.
Bold, Italic, Underline, Strike Through
Свойства Bold,
Italic, Underline и StrikeThrough позволяют установить атрибуты шрифта:
полужирный, курсив, подчеркивание и перечеркивание. Возможными значениями для
этих свойств являются True или False.
Значение свойства
Weight, задаваемое пользователем или разработчиком, округляется до одного из
двух фиксированных значений: 400 (обычная толщина) или 700 (полужирный).
Объект Font заменяет
свойства FontSize, FontName, FontBold элементов управления Visual Basic 3.0,
которые для совместимости остались в Visual Basic
6.0. Но обратите
внимание на различное написание имен свойств Font. StrikeThrough (версия 5.0) и
FontStrikethru (версия 3.0).
FontTransparent
Некоторые элементы
управления и объекты Visual Basic (например, Form, pictureBox, Printer)
обладают специфическим свойством, связанным с отображением шрифтов —
FontTransparent. Если его значение равно False, то при выводе текста фон под
символами не отображается; в противном случае символы отображаются поверх
существующего фона.
BackStyle
Функцию, аналогичную
FontTransparent, для некоторых элементов управле ния (например. Label)
выполняет свойство BackStyle. Если его значение равно О, то фон элемента
управления будет прозрачным.
Свойство Font
Кроме объекта Font, в
Visual Basic есть и свойство Font. Это свойство содержит ссылку на объект Font
и может использоваться так же, как и объект Font.
Диалоговое окно изменения вида шрифта
Начиная с Windows
версии 3.1, файл COMMDLG.DLL входит в комплект поставки системы. Этот файл (или
его 32разрядная версия COMDLG32.DLL) содержит стандартные диалоговые окна
Windows, одно из которых используется для установки параметров шрифта. Это
диалоговое окно отображается с помощью метода ShowFont или свойства Action:
CommonDialogI. ShowFont
ИЛИ
CommonDialogI.Action = 4
Однако такая попытка
открытия окна (без предварительной настройки параметров) вызывает ошибку под
номером 24574 — "No fonts exist." ("Нет шрифтов"). Это
связано с тем, что диалоговое окно должно "знать", какого вида шрифты
— принтерные или экранные — следует отображать. Поэтому перед открытием
диалогового окна нужно установить свойство Flags равным cdlCFScreenFonts, cdiCFPrinterFonts
или cdlCFBoth, после чего диалоговое окно будет отображать шрифты указанного
типа (типов). Если не задать значение этого свойства, то возникает ошибка
выполнения.
CommonDialogI.Flags
•= cdiCFPrinterFonts CommonDialogI.ShowFont
Выбор шрифта можно
ограничить присвоением свойству Flags значений дополнительных констант.
Например, константа cdlCFForceFontExist задает вызов сообщения об ошибке при
попытке пользователя выбрать несуществующий шрифт или стиль, а константа
cdlCFLimitSize указывает, что диалоговое окно будет отображать размеры шрифтов
из диапазона, задаваемого свойствами Min и Мах:
CommonDialogI.Flags = cdiCFPrinterFonts Or
cdlCFForceFontExist Or _
cdlCFbimitSize
CommonDialogI.Min !« 8 CommonDialogI.Max = 20 CommonDialogI.ShowFont
Возможности
диалогового окна можно при желании расширить. Константа cdlCFEffects позволяет
отобразить дополнительные параметры форматирования для перечеркивания,
подчеркивания и цвета.
Обработка результатов
Заданные
пользователем значения параметров шрифта должны быть обработаны программой. Для
этого приложение считывает значения свойств FontName, FontSize, FontBold,
Fontltalic, PontStrikethru, FontUnderline и Color объекта ComrnonDialog:
CommonDialogI.Flags =
cdlCFScreenFonts Or cdlCFEffects CommonDialogI.ShowFont With txtText.Font .Name
= CommonDialogI.FontName
.
•Size = CommonDialogI.FontSize
.Bold = CommonDialogI.FontBold
.
•Italic
CommonDialogl.FontItalic
.
•Strikethrough
ConunonDialogI .FontStrikethru
•Underline
CommonDialogI.FontUnderline End With txtText.ForeColor = CormnonDialogI
.Color
После установки всех
необходимых параметров в диалоговом окне пользователь может завершить его
работу либо кнопкой ОК, т.е. принять все изменения, либо кнопкой Отмена,
чтобы отказаться от них. Программная обработка нажатия каждой кнопки
описывается в главе 5 "Отладка".
Печать
В этом разделе
рассматриваются предлагаемые Visual Basic различные способы форматирования
документа и вывода его на печать.
Метод PrintForm
С помощью метода
PrintForm на принтер выводится форма в виде растрового изображения с установленным
в системе разрешением (чаще всего 96 dpi). Метод PrintForm может использоваться
только для печати форм. При этом на принтер, установленный по умолчанию,
выводится только содержимое формы, без строки заголовка и рамки.
Все элементы
управления выводятся на печать так, как отображаются на экране, т.е. с
соответствующими надписями, границами, видами шрифтов и т.д. Невидимые во время
выполнения элементы управления на печать не выводятся. Содержимое элемента
управления pictureBox выводится на печать только в том случае, если значение
свойства AutoRedraw равно True.
Преимущества
Преимущество метода
PrintForm заключается в том, что форма выводится на принтер в том виде, в
котором она отображается на экране, и для выполнения этого достаточно одной
строки кода.
Недостатки
Недостаток метода,
как это ни парадоксально, состоит в том, что в большинстве случаев форма в том
виде, в котором она отображается на экране, чаще всего не нужна на бумаге.
Еще одной проблемой
является то, что формы могут иметь любой размер, поэтому не всегда возможно с
помощью метода PrintForm полностью напечатать ее на листе формата А4. В
зависимости от установленного разрешения экрана форма имеет соответствующие
максимальные размеры. Например, при разрешении 1280х 1024 точек форма имеет
максимальную ширину 27 см и высоту 34 см, и элементы управления, находящиеся за
пределами отображенной области формы, на печать не выводятся.
Если указанные
ограничения для вас не существенны, то можно поступить следующим образом.
Сначала, воспользовавшись оператором Load, загрузить форму не отображая ее на
экране. Затем инициализировать форму и вывести ее на печать с помощью метода
PrintForm. И наконец, удалить форму из памяти с помощью оператора Unload:
Load frmPrint
frmPrint.lblOutput.Caption "Выводимый
текст"
frmPrint. picOutput. Picture = LoadPicture ("c:\bild.bmp")
frmPrint.PrintForm Unload frmPrint
Объект
Printer
Объект Printer — это
объект, предназначенный для вывода на печать текста и графики.
Преимущества
В отличие от метода
PrintForm, объект Printer позволяет выводить документ на' печать с разрешением,
установленным для принтера, а не для экрана, благодаря чему можно достичь
лучшего качества печати. Большое количество методов и свойств объекта Printer
позволяет программисту полностью управлять процессом печати. Кроме того, этот
объект можно использовать для печати многостраничных документов.
Недостатки
Главным недостатком объекта Printer,
вытекающим из его же достоинства, является необходимость программирования
процесса печати, требующего написания объемного кода.
Наиболее важным
методом объекта printer является Print, с помощью которого текст передается на
принтер:
Printer.Print
"Hello" Printer.Print "World"
Вывод осуществляется,
начиная с верхнего левого угла печатной страницы, с использованием текущих
параметров объекта Printer. Для изменения вида шрифта используются свойства
объекта Font:
Printer.Font.Name = "Times New
Roman" Printer.Font.Size = 12 : Printer.Font.Underline = True
Printer.Print = "Hello world"
Для создания печатного документа нужно, кроме
форматирования, установить также позицию точки вывода.
Объект printer — это
независимый от устройства объект (deviceindependent). Это значит, что объект
"не знает", на какое устройство вывода осуществляется печать. Поэтому
для установки позиции должны использоваться также независимые от устройства
единицы измерения. С этой целью была введена единица измерения твип (twip). Независимо
от модели принтера, 567 твипов составляют 1 сантиметр. Благодаря этому можно
разрабатывать программы, качество печати которых не зависит от текущих
драйверов печати.
ScaleMode
Если единица измерения твип кажется вам
непривычной, то с помощью свойства ScaleMode можно установить и другую.
Константы vbCentimeters, vbMillimeters или vbPixels позволяют использовать
знакомые вам единицы измерения.
CurrentX/CurrentY
Для изменения позиции
точки вывода используются свойства CurrentX 'и CurrentY. Они подобны свойствам
Тор и Left, посредством которых задается расстояние от левого верхнего края
печатаемой области до точки вывода. Ширина и высота печатаемой области в
условных единицах измерения устанавливаются свойствами ScaleWidth И
ScaleHeight.
TextHeight/TextWidth
При использовании
пропорциональных шрифтов ширина слова зависит не только от количества букв, так
как ширина букв может быть разная (например, W и i). В этом случае для
правильного вывода текста следует определять фактическую ширину и высоту
строки. Для этого используются методы TextHeight и TextWidth объекта Printer:
strOutputText = "Hello world" nTextWidth
= Printer.TextWidth(strOutputText) nPrinterWidth = Printer.ScaleWidth
Printer.CurrentX = (nPrinterWidth
nTextWidth) / 2 Printer.Print strOutputText Printer.EndDoc
В примере выполняется
центрирование текста на странице при печати.
Tab
При выводе на печать для позиционирования
текста могут использоваться табуляторы.
Если в операторе
Print выводимые значения разделяются точкой с запятой (;),. то они печатаются
один за другим, без разделителя, а если запятой (,), — каждое очередное
значение печатается в начале следующей зоны печати. Зоны печати в Visual Basic
начинаются через каждые 14 символов (т.е. в столбце 0, столбце 14, столбце 28 и
т.д.). Изменить ширину зоны позволяет функция Tab:
Printer.Print
"Hello"; " World" Printer.Print "Hello", "World"
Printer.Print "Hello"; Tab(8); "World"
Для печати
графических объектов используются методы pset. Line и Circle объекта
Printer.
Printer.Line (1, 1)(10, 5), , В
PamtPicture
Готовые графические
изображения различных форматов можно выводить на печать с помощью метода
PaintPicture. Для этого ему нужно указать имя элемента управления, обладающего
свойством picture, и, при необходимости, позицию и размер изображения:
Printer.ScaleMode
«= vbCentimeters Printer.PaintPicture picPictPrinter.Picture, 5, 5
NewPage/EndDoc
После направления
всех данных на печать с помощью объекта Printer готовая страница пока еще
находится в оперативной памяти. Для запуска процесса печати этот объект должен
получить сообщение о том, что формирование этой страницы завершено. Для этого
предназначен метод Newpage. После того, как все страницы сформируются,
вызывается метод EndDoc, который направляет сформированный документ на принтер:
Printer.Print
"Страница 1" Printer.NewPage Printer.Print "Страница 2"
Printer.EndDoc
KWDw
Для того чтобы
отменить или прервать печать, используется метод KillDoc.
Процесс печати
В настоящем разделе
рассматриваются возможности управления процессом печати в Windows с помощью
диалогового окна установки параметров принтера и печати.
Диалоговое окно печати
Элемент управления
CommonDialog позволяет использовать стандартные диалоговые окна Windows, среди
которых есть диалоговое окно установки параметров принтера и печати. Элемент
управления CommonDialog предоставляет ряд свойств для управления этим диалоговым
окном.
Для отображения
диалогового окна его свойству Action присваивают значение 5 или используют
метод ShowPrinter:
CommonDialogI.ShowPrinter
ИЛИ
CommonDialogI.Action 5
С помощью этого
диалогового окна пользователь может выбрать новый принтер по умолчанию,
количество и номера печатаемых страниц и число копий.
В отличие от других
стандартных диалоговых окон, большая часть параметров, устанавливаемых в этом
окне, не анализируется программистом, а передается непосредственно системе
печати. Программист должен анализировать только параметры, устанавливаемые в
группе Печатать.
Flags
Если свойству Flags
присвоить значение cdlPDPageNums и задать значения свойств Min и
Мах, то с помощью свойств FromPage и ТоРаде можно определить значения
полей Страницы С и По.
Copies
Значение по умолчанию
в поле Копии\Число копий можно установить, воспользовавшись свойством
Copies:
CommonDialogI.Flags =
cdlPDPageNums Or cdlPDCollate Or cdlPDNoSelection CommonDialogI.Copies == 2
CommonDialogI.Min = 0 CornmonDialogI .Max = 10 CommonDialogI.ShowPrinter
nCopies = CommonDialogICopies nFromPage = CommonDialogI.FromPage nToPage "
CommonDialogI.ToPage
PrinterDefault
Если значение
свойства PrinterDefault равно True, то установки, сделанные пользователем,
будут использованы в качестве установок принтера по умолчанию.
TrackDefault
Если значение
свойства TrackDefault равно False, то объект Printer всегда будет указывать на
тот же принтер, независимо от изменения настроек принтера по умолчанию в панели
управления. В противном случае объект Printer настроится на другой принтер
согласно внесенным изменениям.
Семейство
Printers
В Visual Basic 4.0 введен объект Collection
(семейство), который представляет собой упорядоченный набор компонентов, на
который можно ссылаться как на единое целое.
Visual Basic
использует семейство для управления принтерами, установленными в системе.
Наряду с принтером, установленным по умолчанию, можно использовать любой
другой, имеющийся в семействе. Любой принтер системы можно назначить принтером
по умолчанию:
Private Sub
Form_Load() Dim obj Printer As Printer
For Each objPrinter In Printers
IstPrinter.Addltern
objPrinter.DriverName Next objPrinter End Sub
Sub
lstPrinter_Click()
Set Printer = Printers(IstPrinter.Listlndex)
Printer.Print "Hello" End
Sub
В данном примере при загрузке формы все
установленные принтеры отображаются в окне списка IstPrinter. Пользователь
может выбирать один из них и назначить :его принтером по умолчанию.
Для поиска в
семействе принтера с необходимыми параметрами следует воспользоваться
свойствами ColorMode
(vbPRCMMonochrome ИЛИ vbPRCMColor), Devic'eNam& (имя принтера).
Duplex (двухсторонняя печать). Orientation (ориентация печати) иди PrintQuality
(качество печати).
Dim
obj Printer As Printer For Each objPrinter In Printers . If
objPrinter.DeviceName "Microsoft
Fax" Then Set Printer
objPrinter Exit For
End If Next objPrinter
С помощью этой процедуры можно найти факс и
назначить его принтером по умолчанию.
При необходимости
параметры принтера можно изменить: Printer.PaperBin ~ vbPRBNManual '
Printer.Duplex vbPRDPSimplex
Printer.PrintQuality " vbPRPQHigh Printer.PaperSize •• vbPRPSA4
С помощью объекта Printer и семейства
Printers можно управлять процессом печати в Windows и задавать нужные параметры
печати из приложения.
Глава 5
Отладка
Английский термин
"debugging" (отладка) связывают с инцидентом, произошедшим в
Министерстве обороны США. Когда в одной из первых вычислительных машин
Пентагона возникла ошибка при вычислениях, был проверен текст программы, однако
ошибка не была выявлена. Причина была обнаружена при проверке самой
вычислительной машины. Между контактами одного из реле был зажат жучок
(насекомое) — поанглийски bug, что и послужило причиной ошибки. После удаления
жучка (debugging) ошибка была устранена. Даже если этой истории и не было на
самом деле, ее стоило выдумать, т.к. она довольно удачно разъясняет
возникновение термина "debugging".
Типы ошибок
При
отладке и выполнении программы могут возникать ошибки четырех типов:
• Синтаксические
Ошибки,
связанные с неправильным синтаксисом оператора (например, if без
Then).
• Ошибки в структуре программы
Ошибки такого типа
появляются в результате некорректного написания многострочных операторов
(например. For без Next). По сути это синтаксические ошибки, но Visual Basic
обрабатывает ошибки этого типа несколько иначе.
• Ошибки, возникающие во время выполнения
программы
Это ошибки,
проявляющиеся во время работы программы (например, ошибка
деления на ноль).
• Логические ошибки
Ошибки такого типа
самые каверзные. Программа выполняет вычисления,
но выдает
неправильный результат.
Синтаксические
ошибки
Причиной
возникновения синтаксической ошибки могут быть неправильно написанные ключевые
слова, ошибки применения разделителей или недопустимые комбинации операторов.
Visual Basic распознает синтаксические ошибки сразу же после того, как курсор
покидает эту логическую строку. Логическая строка может состоять из нескольких
физических строк, разделенных символом подчеркивания (_).
При обнаружении
ошибки Visual Basic выдает сообщение с подробным пояснением ошибки. Такие
сообщения достаточно информативны и позволяют легко определить причину
возникновения ошибки и устранить ее.
Проверка синтаксиса
Проверку синтаксиса
можно включить или отключить с помощью опции Auto Syntax Check вкладки Editor
диалогового окна Tools\0ptions. Отключать проверку синтаксиса имеет
смысл только в тех редких случаях, когда строка кода формируется путем
копирования готовых фрагментов из других мест программы. В этом случае при
перемещении курсора в окне кода постоянно появляются раздражающие сообщения об
ошибках, причина которых и так известна разработчику. В большинстве случаев
отключать проверку синтаксиса не следует.
Строка с
синтаксической ошибкой выделяется красным цветом. Повторная проверка синтаксиса
проверенных строк кода выполняется только после внесения в них изменений.
Контекстная
подсказка
В Visual Basic 6.0
встроены средства, которые позволяют не только обнаружить синтаксическую
ошибку, но и избежать ее при написании кода. Это, в частности, механизм
контекстной подсказки или Quicklnfo. Quicklnfo — это небольшое окно,
похожее на окно ToolTips, в котором автоматически отображается полный синтаксис
вводимого оператора. Благодаря окну Quicklnfo программист всегда имеет
перед собой список аргументов процедуры.
При формировании вложенш |
ций |
вводимый |
аргумент |
для |
удобства |
всегда выделяется жирным ШРШ|) |
'. 2 показан момент |
редакт |
ирова |
ния |
|
аргумента Prompt). |
|
|
|
|
|
Если
окно Quicklnfo занимает много места и мешает при
работе, режим отображения контекстной подсказки можно отключить с помощью опции
Auto Quick Info диалогового окна Tools\0ptions (вкладка
Editor).
Автоматическое отображение списка элементов
Для уменьшения
количества ошибок при написании имен, свойств и методов объектов, а также полей
структур Visual Basic автоматически отображает список доступных элементов.
Содержимое списка зависит от типа объекта. Например, список будет одинаковым
для всех объектов CommandButton независимо от того, какой форме они принадлежат
и какую функцию выполняют.
Вы можете выбрать
элемент из списка либо ввести его имя с клавиатуры. В процессе ввода указатель
списка автоматически перемещается к нужному элементу. Тип элемента списка
(свойство или метод) указывает пиктограмма рядом с именем.
Выбрать нужный
элемент в списке можно также с помощью клавиш управления курсором. Нажатием
клавиши [Tab] выделенный элемент вводится в текущую строку, причем текстовый
курсор остается в этой строке. Для ввода выбранного элемента и перехода на
следующую строку следует нажать клавишу [Enter].
Автоматическое
отображение списка элементов можно отменить отключением опции Auto List
Members диалогового окна Tools\0ptions (вкладка Editor).
Этот же список можно
вызвать, воспользовавшись кнопкой List Proper ties/Metods панели
инструментов Edit или комбинацией клавиш [Ctrl+J]. Список констант
открывается кнопкой List Constants или комбинацией клавиш
[Ctrl+Shift+J].
Дополнение слова
Аналогично
автоматическому списку элементов действует и функция допол
нения слова. Если в окне кода введено
несколько начальных символов свойства,
метода или элемента
структуры, которых достаточно для их однозначной
идентификации. Visual Basic может
дополнить недостающие символы. Для
этого c;ic;i\cr
щелкнуть на кнопке Complete Word панели инструментов Edit
или нажать клавиши
[Ctrl+Пробел].
Visual Basic не
дополнит имя недостающими символами, если введенных символов недостаточно для
однозначной идентификации.
Цветовые коды
Дополнительные
возможности при написании и отладке программы предоставляет цветовая кодировка
элементов кода. Visual Basic позволяет выделять различным
шрифтом и цветом
фрагменты кода. Задать параметры шрифта и цвета можно на вкладке Editor
Format диалогового окна Tools\0ptions.
Таблица 5.1. Элементы
кода, цвет которых можно изменять
Элемент |
Описание |
Normal Text |
Текст окна кода |
Selection Text |
Выделенный текст |
Syntax Error Text |
Текст ошибочной строки кода |
Execution Point Text |
Текст в точке выполнения |
Breakpoint Text |
Текст в строке с точкой останова |
Comment Text |
Комментарий |
Keyword Text |
Ключевое слово Basic |
Identifier Text |
Имена процедур и переменных |
Bookmark Text |
Текст строки с закладкой |
Call Return Text |
Текст обратного вызова |
При вводе кода Visual Basic автоматически
устанавливает расстояние между отдельными словами. Например, возле знака
равенства автоматически вставляются пробелы:
Commandl.Caption=="CnpaBKa" ' до
форматирования Commandl.Caption = "Справка" ' после форматирования
Осторожно!
При написании
программы не стоит полагаться на то, что Visual Basic сам правильно расставит
все пробелы. Например, могут возникнуть сложности при использовании символа
коммерческого И, или амперсанда (&). Он может применяться как соединитель
строки (в таком случае он отделяется пробелами) или же как идентификатор
переменных типа Long (используется без пробелов):
Labell.Caption =
Numbers & " Штук; Номер: " & &Н100&
Обратите внимание,
что в данном примере символ амперсанда (&) выполняет три различные функции.
Сначала он служит идентификатором переменной Number типа Long, затем выступает
как оператор соединения и, наконец, как разделитель для шестнадцатеричных
чисел.
Ошибки в структуре программы
Ошибки в структуре
программы — это синтаксические ошибки в многострочных операторах цикла и
ветвления. Такие ошибки образуют отдельную группу ошибок, так как не
распознаются Visual Basic при вводе. Однако при компиляции программы
распознавание ошибки такого типа не представляет большой проблемы. В этом
случае Visual Basic распознает такой незавершенный многострочный оператор,
выдает сообщение об ошибке и выделяет ошибочный оператор. При этом
"точность попадания" очень хорошая, за исключением вложенных
конструкций.
Сообщение об ошибке в структуре программы
К сожалению, , 'шибок Visual Basic не
является безукоризненным.
Иногда отображаются
сое» которые вводят разработчика в заблуждение. В таких случаях для обнар\
<.. ', стоящей причины требуются интуиция и опыт.
Начиная с версии \ |
ic 4.0, приложение не компилируется
полностью, если |
его запускают из среды |
т' нажатием клавиши [F5]
или щелчком на кнопке |
Run панели инструмен: |
случае ошибки в структуре
программы на этапе |
выполнения выявляются только при
обращении к процедуре, содержащей ошибочную структуру. Если же запуск программы
осуществляется с помощью команды Start With Full Compile меню Run или нажатием [Ctrl+F5], то все ошибки в структуре
программы обнаруживаются сразу при компиляции проекта. При компиляции Visual
Basic также определяет имена объектов, не связанных с элементами управления, и
выявляет переменные, которые не были явно объявлены (если была установлена
ОПЦИЯ Option Explicit).
Проверка на отсутствие синтаксических
ошибок и ошибок в структуре программы осуществляется и при создании
выполняемого файла (команда Make *.EXE меню File).
Ошибки, возникающие
при выполнении программы
В идеальном случае
программа не должна бороться с ошибками в период выполнения. Однако разработчик
должен предусмотреть вероятность появления сбойных файлов, переполнения памяти или
ввода пользователем некорректных данных. Все это может послужить причиной
возникновения ошибок при выполнении программы (Runtime Errors).
При обнаружении такой
ошибки Visual Basic выводит соответствующее сообщение и приостанавливает
выполнение программы. Если приложение было запущено из среды разработки, то
существует возможность переключиться в режим отладки с помощью кнопки Debug либо
в режим проектирования с помощью кнопки End.
Среда разработки
относительно "мягко" реагирует на ошибки периода выполнения. Если же
такая ошибка возникает после запуска выполняемого ЕХЕфайла, то приложение
немедленно закрывается. Хотя сообщение об ошибке и появляется, перейти в режим
отладки невозможно. Это довольно драматическая реакция, возможно, на совершенно
безобидную ошибку.
Перехват ошибок
периода выполнения следует предусмотреть на этапе разработки приложения. Для
этого создаются специальные процедуры — обработчики ошибок (error handlers).
Все ошибки периода выполнения можно разделить на две группы: ожидаемые, обработка
которых предусмотрена разработчиком, и неожиданные, появление которых не всегда
могут предвидеть даже опытные программисты.
Ожидаемые
ошибки времени выполнения
Обработка ошибок
производится в три этапа:
.
• подготовка перехвата;
.
• проверка и устранение ошибки;
.
• продолжение выполнения программы.
Подготовка
перехвата
Первым шагом является
расстановка "ловушек". В Visual Basic для этого предназначен оператор
On Error.
On Error { GoTo label I
Resume Next I GoTo 0 } Выполнение оператора On Error активизирует режим обработки ошибок.
Это означает, что при возникновении ошибки периода выполнения после ввода в
программу этой строки выполняется предусмотренная в программе процедура
обработки ошибки. Выполнение программы не прерывается и стандартное сообщение
об ошибке не выводится. Метка (label), указанная в операторе, должна находиться
в той же процедуре, что и оператор On Error. Если в качестве метки указан ноль
(0), то предусмотренная разработчиком процедура обработки ошибок отключается и
включается стандартный механизм обработки ошибок. Опция Resume Next подробно
описывается в следующем разделе.
Проверка
и устранение ошибки
Оператор On Error не
выполняет непосредственно никакой обработки ошибок, а лишь передает управление
ответственному за обработку ошибок фрагменту программы. Для обеспечения
перехвата всех ошибок в процедуре оператор On Error, no возможности, должен
находиться в самом ее начале.
Обработка ошибки
должна выполняться сразу после ее обнаружении. Сначала следует установить тип
ошибки. Для этого в Visual Basic существует объект Err, свойство которого
Number содержит код последней возникшей ошибки.
Для совместимости с
предыдущими версиями Visual Basic свойство Number объекта Err является
свойством по умолчанию. Поэтому переменные ErrNumi и ErrNum2 будут содержать
одинаковое значение:
Dim ErrNumi As
Integer, ErrNum2 As Integer
ErrNumi
= Err ErrNum2 = Err.Number
Список кодов ошибок,
которые можно перехватывать и обрабатывать, вы найдете в системе справок Visual
Basic. После определения типа ошибки по ее коду (свойство Number объекта Err)
следует попытаться устранить ошибку или обработать ее так, чтобы она не мешала
выполнению программы.
Продолжение выполнения программы
Завершив обработку
ошибки, следует продолжить нормальное выполнение программы. Ключевое слово
Resume позволяет вернуться в строку, вызвавшую ошибку, для ее повторного
выполнения, а оператор Resume Next возвращает в следующую за строкой с ошибкой
строку.
Resume [{ Next
I label )]
Оператор Resume Next
можно использовать, вместе с оператором On Error, и тогда каждая строка,
вызвавшая ошибку, игнорируется:
On Error Resume Next
Однако такая
простейшая обработка ошибок не позволяет определить источники ошибки и
исправить ее.
Обработка ошибок выполнения
Оператор On Error
Итак, в начале
процедуры помещается оператор On Error для перехвата возникающих ошибок. В нем
указывается метка, к которой происходит переход при возникновении ошибки.
Обычно эта метка находится в конце процедуры и перед ней помещается оператор
Exit. Благодаря этому оператору, при безошибочном выполнении процедура в этом
месте завершает свою работу, и фрагмент процедуры после метки выполняется
только после возникновения ошибки.
Обработка
При обработке ошибок
возникшая ошибка анализируется и выполняются соответствующие действия.
Например, при делении на нуль это может быть прекращение текущих вычислений;
при ошибках обращения к диску может отображаться диалоговое окно для принятия
пользователем решения о прекращении операции или повторном выполнении.
Возврат
После корректной обработки ошибки программа
должна продолжить свое выполнение. Чтобы программа продолжала выполняться в
строке, в которой возникла, а затем была устранена ошибка, в обработчике
указывается оператор Resume.
Процедура с
обработчиком ошибок может выглядеть следующим образом:
Sub Error_Test() On
Error GoTo.ErrLabel 'Включает обработку ошибок
For i •= 4 То 0 Step
1
Е = 2 / i 'Вызывает деление на нуль Next
i Exit Sub
ErrLabel:
"Метка
Select Case Err.Number 'Проверка ошибки Case 11
'Деление на нуль i = 1 Err.Clear
Resume
"Возврат Case Else MsgBox Err.Description Stop End Select End Sub
Оператор On Error
должен заканчиваться Resume или другим оператором завершения обработки ошибок,
иначе при компиляции возникнет ошибка в структуре программы. Для этого могут
использоваться следующие операторы:
.
• Resume/Resume Next/Resume label;
.
• Exit Sub/Exit Function/Exit Procedure;
.
• End/Stop.
Чтобы обработчик ошибок не выполнялся всегда,
следует поставить перед меткой обработчика оператор Exit Sub, Exit Function или
Exit Procedure. В результате в этом месте происходит выход из процедуры, и
остальная часть кода выполняется только при появлении ошибки.
Свойство Description объекта Err возвращает
текст системного описания ошибки. Это можно использовать для вывода текста
сообщения об ошибке в обработчике ошибок, поскольку системный вывод сообщения
об ошибке при использовании обработчика ошибок не производится.
Типичным примером
использования обработчика ошибок может быть обработка свойства CancelError элемента
управления CommonDialog. Если значение свойства CancelError равно True, то при
щелчке на кнопке Cancel в одном из диалоговых окон элемента управления
CommonDialog возникает ошибка. Если значение этого свойства равно False, ошибка
не возникает, но различить нажатие кнопок ОК и Cancel в диалоговых окнах
CommonDialog будет затруднительно.
Function OpenFileO As
String On
Error GoTo Cancel
CommonDialoql.CancelError = True
CommonDialogI.Filter
= "Все файлы (*.*) I *.*"
CommonDialogI.ShowOpen OpenFile =
CommonDialogI.filename Exit Function
Cancel: If Err.Number = cdlCancel Then
OpenFile = "" MsgBox Err.Description Exit Function Else MsgBox
Err.Description Stop End If End Function
В этом примере
функция возвращает имя файла. Если работу с диалоговым окном открытия файла
завершить нажатием кнопки Cancel, то возвратится пустая строка. Значение
свойства CancelError можно задать и в окне свойств.
Обработка ошибок при вложенных вызовах
процедур
Вложенный вызов
процедур влияет на обработку ошибок. Если вызываемая процедура или функция не
имеет собственного обработчика ошибок, то Visual Basic ищет его в вызывающей
процедуре. Если данная процедура содержит обработчик ошибок, то возникшая
ошибка будет обработана. В зависимости от результатов обработки выполнение
программы можно продолжить либо с помощью оператора Resume (для повторного
вызова процедуры или функции), либо с помощью оператора Resume Next (для
продолжения выполнения программы со следующей за вызовом процедуры строки).
На рисунке видно, что
обработка ошибки, возникшей в ProcedureA, выполняется оператором On Error
вызвавшей ее процедуры Commandl_Click. В общем случае поиск обработчика ошибок
осуществляется сначала в текущей процедуре, а затем — в вызывающей.
При использовании
обработчиков ошибок в процедурах, вызывающих другие процедуры, следует помнить,
что ошибки, возникающие в вызываемых процедурах или функциях, также должны
обрабатываться.
Если в обработчике
ошибок используется оператор Resume Next, то выполнение приложения продолжается
в строке, следующей за строкой вызова процедуры; если же используется оператор
Resume, то происходит возврат в строку вызова процедуры.
Окно стека вызова
процедур приложения можно открыть с помощью команды Call Stack... меню View
или комбинации клавиш [Ctrl+L] в режиме прерывания (Break).
Окно стека вызова
процедур содержит список всех активных процедур. При этом процедура обработки
события находится в конце списка, а текущая — в самом начале.
Глобальная обработка ошибок
Если вы предусмотрели
в своей программе обработку ошибок, то можете обнаружить, что ошибка одного и
того же типа может возникать при выполнении различных фрагментов программы. В
этом случае затраты на программирование и размер программы можно сократить
путем создания единого обработчика ошибок.
Visual Basic
позволяет реализовать единый обработчик ошибок, так как ошибки вызываемых
процедур могут перехватываться в обработчике ошибок вызывающей процедуры.
Однако эта задача усложняется тем, что в Visual Basic метка обработчика ошибок
должна быть локальной. Хотя обработчик ошибок вызываемой процедуры может
содержать вызов других процедур (например, глобального обработчика ошибок),
оператор возврата также должен быть локальным и поэтому не может находиться в
глобальном обработчике.
Приведенный пример
показывает, каким образом можно реализовать единый обработчик ошибок. Функция
анализирует передаваемый ей код ошибки и возвращает числовое значение,
определяющее, какой из операторов
— Resume, Resume Next
или Exit Sub — следует применить в вызвавшей эту функцию процедуре:
Function FileError(ErrValue As Integer) As
Integer ' Номер ошибки
Описание ' 0 Resume '
1 Resume Next ' 2
Неустранимая ошибка '
3 Нераспознанная ошибка Dim
ВохТур As Integer,
Txt As String, ret As Integer
BoxType = vbExclamation
Select Case
ЗначениеОшибки
Case
ERR_DEVICEUNAVAILABLE
Txt =
"Устройство недоступно!"
BoxTyp = vbYesNo Or
vbCritical Case ERR_DISKNOTREADY
• = 71
Txt = "Диск не готов! "
Case ERR_DEVICE10 ' = 57
Txt = "Внутренняя ошибка диска."
ВохТур vbYesNo Or vbCritical
Case ERR_BADFILENAME, ERR_BADFILENAMEORNOMBER '
= 64/ 52 Txt =
"Недействительное имя файла." Case ERR_PATHDOESNOTEXIST' = 76
Txt = "Путь недействительный." Case ERR_BADFILEMODE '=54 Txt =
"Недействительный доступ." Case ERR_FILEALREADYOPEN ' = 55 Txt =
"Файл уже открыт." Case ERR_INPUTPASTENDOFFILE ' = 62 Txt =
"Попытка считывания после конца файла." Case
Else
FileError = 3
Exit Function End
Select
ret = MsgBox(Txt, BoxType, "Ошибка
диска!") Select
Case ret
Case vbOK, vbRetry
FileError = 0 'означает RESUME Case vblgnore
FileError = 1 "означает RESUME NEXT Case
vbCancel, vbAbort
FileError = 2 'означает EXIT SUB Case Else
FileError = 3
'означает прекращение End Select End Function
Функция, приведенная
в примере, обрабатывает некоторые наиболее распространенные ошибки, возникающие
при работе с файлами и дисками. Возвращаемые ею значения затем анализируются в
вызвавшей ее процедуре:
Sub SomeProcedure ()
On Error GoTo ErrHandle
Exit
Sub
ErrHandle: Select Case
FileError(Err.Number) Case 0
Resume Case 1
Resume Next Case 2
Exit Sub Case 3
Call MercyfulExit ' Обработка нераспознанных
ошибок End Select End Sub
Процедура
SomeProcedure содержит локальный обработчик ошибок, который вызывает глобальный
обработчик. Продолжение выполнения программы зависит от значения, возвращаемого
глобальной функцией обработки ошибки. Для ошибок, обработка которых не
предусмотрена в глобальном обработчике ошибок, можно создавать локальный
обработчик. В данном примере это выполняется при возникновении нераспознаваемой
ошибки (глобальный обработчик возвращает значение 3). При возникновении
нераспознаваемой ошибки выход из программы должен происходить с минимальной
потерей информации.
Неожиданные ошибки выполнения
Профессионально
разработанные приложения должны перехватывать и обрабатывать все возможные
ошибки. Поэтому появление ошибок в окончательной версии программы
свидетельствует о недостаточно Основательном тестировании программы.
Для всех ожидаемых
ошибок должны быть предусмотрены соответствующие обработчики. При появлении
неожиданных ошибок разработчик, как минимум, должен вывести сообщение об
ошибке, чтобы в дальнейшем эту ошибку можно было проанализировать и подготовить
для нее свой обработчик (сделать ошибку ожидаемой). Для выявления неожиданных
ошибок при тестировании приложения моделируются различные экстремальные
ситуации и проверяется работоспособность программы. При выводе сообщения о
неожиданной ошибке можно воспользоваться свойством Description объекта Err,
которое содержит системное описание ошибки:
MsgBox Err.Description
Свойство Description
можно использовать и для задания собственных сообщений об ошибке:
Err.Description = "Отсутствует компонент
X!"
Возникновение ошибок
выполнения можно и сымитировать. Для этого предназначен метод Raise объекта Err:
Err.Raise 11
Такое использование
метода Raise вызывает ошибку выполнения "деление на ноль" (код 11).
После вызова метода Raise можно проверить корректность обработки ошибки данного
типа обработчиком.
Во время работы с
OLEобъектами или другими программами иногда нужно знать имя приложения, в
котором произошла ошибка:
Err.Source = "РазделА" sQuelle =
Err.Source
Для каждого модуля
или компонента приложения можно предусмотреть задание собственного значения
свойства Source. Благодаря этому при обработке ошибок можно точно локализовать
источник ошибки.
Метод
Clear позволяет очистить значения всех свойств объекта Err:
Err.Clear
В предыдущих версиях
это выполнялось присвоением объекту Err значения О (Err = 0).
Целью обработчика
неожиданных ошибок должно быть обеспечение продолжения работы с программой на
срок, достаточный хотя бы для ее корректного завершения.
Логические ошибки
Самым "крепким
орешком" среди всех возможных являются логические ошибки. При их появлении
код выполняется корректно, но желаемый результат не достигается.
Обнаружив логическую
ошибку, вы можете либо исправить ее, либо определить, какую задачу программа
может решить, и довольствоваться этим.
Sub LogicalError Const
One = 1 Const Two =
3 Const Three = 2
Const Four = 4
Result
= (Four + Three)/Two One MsgBox Result
End Sub
В данном примере
после выполнения арифметических действий функция MsgBox выведет результат 1, а
не 2.5, как ожидалось, так как при определении констант перепутаны значения.
Для
выявления причин логической ошибки и ее устранения требуется обширное
тестирование. Visual Basic предлагает некоторые эффективные инструменты для
поиска источников ошибок.
Инструменты отладки (Debugging Tools)
Предположим, вы едете
в автомобиле и неожиданно слышите странный шум в двигателе. На полном ходу,
т.е. в режиме выполнения (Run mode), едва ли можно обнаружить неисправность.
Поэтому вы припарковываете машину и выключаете двигатель — аналогично режиму
проектирования (Design modeIDesign mode). Но и теперь невозможно обнаружить неисправность,
потому что двигатель не работает. Вы включаете двигатель, проверяете его в
различных режимах и, если обладаете определенным опытом и знаниями, сможете
легко обнаружить и устранить неисправность. Подобный режим есть и в Visual
Basic и называется он режимом прерывания (Break mode), или режимом отладки.
Почти все исследования с помощью инструментов отладки могут выполняться только
в этом режиме.
Режим отладки
Набор команд меню Run
и назначение многих кнопок панели инструментов зависит от состояния среды
разработки. В режиме проектирования приложение можно только запустить, все же
остальные возможности недоступны. При запуске
можно
выбрать один из двух вариантов: без полной компиляции или полную
компиляцию всех процедур; Приложение запускается нажатием клавиши [F5]
или кнопки Start в среде разработки Visual Basic.
Переход в режим отладки выполняется нажатием клавиш [Ctrl+Break] или
щелчком на кнопке Break. В режиме отладки можно выбирать один из
вариантов:
продолжать программу или перейти в режим разработки.
В режим выполнения
можно перейти, нажав повторно клавишу [F5] или щелкнув на кнопке Continue. Обратите
внимание, что в режиме отладки кнопка Start носит название Continue.
Название текущего
режима отображается в квадратных скобках в строке заголовка Visual Basic.
В режим отладки вы
попадаете и тогда, когда во время выполнения программы, запущенной из среды
разработки, возникла необрабатываемая ошибка выполнения. При этом выдается
сообщение об ошибке с возможностью выбора одного из вариантов: завершение
выполнения или переход в режим отладки.
Большое преимущество
режима отладки заключается в том, что выполнение программы приостанавливается в
месте возникновения ошибки. Другим важным моментом является то, что при этом
сохраняются значения всех текущих переменных.
В среде разработки
Visual Basic инструменты поиска ошибок объединены в меню Debug. Воспользовавшись
командой Toolbars меню View, можно отобразить панель инструментов
Debug для доступа к основным средствам отладки.
Точка останова
Большинство
инструментов отладки можно использовать только в режиме отладки. Перевести
приложение в такое состояние можно, щелкнув на кнопке Break или кнопке Debug,
доступной в диалоговом окне сообщения об ошибке выполнения.
Visual Basic
предоставляет еще одну возможность переключения приложения в режим отладки. Это
возможно благодаря точке останова (Breakpoint). Точка останова — это выделенная
строка программы, на которой автоматически останавливается выполнение
программы. По достижении этой строки программы Visual Basic также переходит в
режим отладки.
В Visual Basic 5.0
была введена новая возможность установки и удаления точек прерывания в
программе — с помощью полоски индикатора. Для отображения полосы индикатора
следует установить опцию Margin Indicator Bar во вкладке Editor
Format диалогового окна Tools\0ptions.
Рис. ?. 12. VL '.'Htii/iifiKci
tiii.inchi индикатора в диалоговом окне опций
Полоса индикатора
Полоса индикатора
появляется слева в окне кода после установки опции Margin Indicator Bar. Если
щелкнуть левой кнопкой мыши на этой полосе, то в этом месте появится красная
точка и находящаяся рядом строка закрашивается красным цветом. Установить и
удалить точки останова можно также с помощью контекстного меню или кнопки
Toggle Breakpoint панели инструментов.
Точки останова можно поместить в любой строке
кода, включая заголовок процедуры (Sub/Function/Property) и строку End. Точки
останова нельзя устано вить только в строках комментариев или пустых строках.
Среда разработки предоставляет еще ряд других
возможностей установки и удаления точек останова. При этом текстовый курсор
всегда должен находиться в соответствующей строке кода.
На панели инструментов Debug находится
кнопка Toggle Breakpoint,
позволяющая установить или удалить точку
останова на текущей строке.
Это можно сделать
также нажатием клавиши [F9). Установку или удаление точки останова для текущей
строки можно выполнить и с помощью команды Toggle Breakpoint меню Debug.
Удалить все точки останова во всем проекте можно с помощью команды Clear
All Breakpoints меню Debug. Установленные в среде разработки точки
останова не сохраняются вместе с программой и не включаются в ЕХЕфайл при его
создании.
Оператор
Stop
Использование
оператора Stop аналогично установке в программе точки останова. Если этот
оператор встречается в программе, то Visual Basic переключается в режим
отладки. Однако этот оператор целесообразно использовать только при разработке
приложения. В ЕХЕфайлах он выполняет действие, аналогичное оператору End, т.е.
приводит к немедленному завершению программы.
Область
применения
Точки останова предназначены для
принудительной остановки программы в нужном месте и перехода в режим отладки. В
результате становятся доступными все средства отладки.
Даже сама установка
точки останова может помочь при отладке программы. Например, если точка
установлена на заголовке процедуры, но переход в режим отладки не произошел,
это значит, что данная процедура не вызывается при выполнении. Аналогично и для
ветвлений: если в операторе if.. .Then точка останова находится в ветви True и
программа не прерывается, то значит это условие не выполняется. Однако прежде
всего точки останова используются для приостановки выполнения программы в
определенном месте.
Следующий оператор
В режиме отладки
Visual Basic особым образом выделяет строку, которая должна выполняться
следующей. Сама строка выделяется желтым цветом, а на полосе индикатора рядом с
ней появляется желтая стрелка.
Рис. л 14. Выделение
следующей строки выполнения
Если выполнение программы прерывается
в точке останова, то оба выделения комбинируются. При этом важно, что строка с
точкой останова выделяется и как следующий оператор для выполнения, т.е. эта
строка еще не выполнялась, а только подлежит
обработке. Чтобы
продолжить выполнение программы с любой другой строки, необходимо желтую
стрелку полосы индикатора просто перетащить мышью на нужную строку.
Если попытаться
установить желтую стрелку на строку, которая не может быть выполнена, курсор
мыши примет вид, указывающий на невозможность переноса. После отпускания кнопки
мыши данная строка не выделяется.
предлагает ряд других возможностей задания
текущей строки
этом текстовый курсор
должен находиться в требуемой строке кода. В меню Debug есть команда Set
Next Statement, после вызова которой строка кода, в которой находится
текстовый курсор, становится следующей выполняемой строкой. Для вызова этой
команды используется также комбинация
клавиш [Ctrl+F9j.
Если при просмотре программы вы потеряли из виду текущую строку выполнения, то
с помощью команды меню Debug\Show Next Statement можно вернуть ее
в поле зрения в окне кода.
Рис. 5.1?.
Перемещение маркирования для следующей строки выполнения
Область применения
Маркирование
следующей выполняемой строки позволяет получить различную информацию. Если
после возникновения ошибки выполнения вы переходите в режим отладки, то
маркировка показывает строку, в которой возникла ошибка.
Особый интерес
представляет выделение следующей выполняемой строки при пошаговом выполнении. В
этом случае можно точно проследить очередность выполненных операторов, что
важно, например, в операторах ветвления, когда необходимо точно установить,
какая ветвь программы выполняется.
Полезным может быть и
перенос следующей выполняемой строки. При изменении значения переменной можно
проверить правильность выполнения программы при новом значении переменной. Для
этого не нужно заново запускать приложение — достаточно повторить нужную часть
кода.
Пошаговое выполнение программы
Если программа
находится в режиме отладки, то она будет работать медленнее, так как все строки
выполняются пошагово. При этом можно непосредственно наблюдать за результатами
выполнения каждой строки. Пошаговое выполнение является важным средством поиска
ошибок и отладки программы. Существует несколько различных команд пошагового
выполнения.
Команды пошагового
выполнения можно вызвать из меню Debug либо из панели инструментов
Debug.
I'm'. .^. 16.
Варианты пошагового выполнения
Шаг с заходом
При пошаговом
выполнении строки кода выполняются одна за другой. После выполнения одной
строки кода маркер следующей строки перемещается на одну строку. Шаг с заходом
(команда Step into) позволяет не только выполнить соответствующий
оператор. Если это оператор вызова процедуры или функции, он дает возможность
перейти в эту процедуру. Для этого следует нажать кнопку Step into на
панели инструментов Debug или клавишу [F8].
Логическая
последовательность строк программы сохраняется.
Благодаря этому можно
отслеживать последовательность выполнения
строк при вызове
процедуры, например, в операторах ветвления.
Режим разработки
В результате нажатия
кнопки Step into в режиме разработки программа также переходит в режим
выполнения. Visual Basic не может самостоятельно решить, какую из
многочисленных процедур обработки события следует выполнить, поэтому после
возникновения события, для которого существует процедура обработки. Visual
Basic перейдет в режим отладки.
Шаг
с обходом
Шаг с обходом подобен шагу с заходом.
Различие проявляется только при вызове текущей процедурой других процедур. Если
при шаге с заходом осуществляется переход в вызываемую процедуру, то шаг с
обходом выполняет вызов процедуры как единичный оператор, т.е. без захода.
Шаг с обходом выполняется нажатием кнопки Step
Over на панели
инструментов Debug или комбинации
клавиш [Shift+FS].
Этот вид пошагового
выполнения представляет интерес при поиске ошибки в процедурах, содержащих
вызовы других процедур. Сначала можно протестировать текущую процедуру без
захода в вызываемые. Если же выяснится, что ошибка возникает в вызываемой
процедуре, то при следующем проходе следует войти в эту процедуру.
Шаг
с выходом
Команда Step Out меню Debug позволяет
выполнить оставшуюся часть текущей процедуры и возвратиться в точку вызова.
Для вызова команды Step Out можно воспользоваться
также кнопкой
панели инструментов Debug либо комбинацией
клавиш [Ctrl+Shift+FS].
Эта команда доступна только в режиме отладки.
Если текущая строка
находится в вызванной процедуре, то с помощью команды Step Out остальная
часть процедуры не выполняется пошагово. Отличие команды Step Out от
команды Continue состоит в том, что после выхода из процедуры
переключение в режим выполнения не происходит, если эта процедура была вызвана
другой. Если же текущая процедура не была вызвана другой процедурой, то
происходит переход в режим выполнения и Visual Basic ожидает возникновения
события, выполнение процедуры обработки которого начнется в режиме отладки.
Выполнить
до текущей позиции
Команда Run To
Cursor меню Debug позволяет выполнить программу от текущей
выполняемой строки до строки с установленным в ней текстовым курсором. Если
текстовый курсор находится в выполняемой строке, то результат выполнения этой
команды будет таким же, что и команды Continue. Для вызова команды
Run To Cursor используется также комбинация клавиш [Ctrl+F8]. Команда Run
To Cursor используется, как правило, при отладке программ, содержащих
циклы. Она позволяет сразу перейти к выполнению нужного оператора, тогда как
при пошаговом выполнении команду Step into иногда приходится вызывать несколько
раз.
Область
применения
Пошаговое выполнение является важным
инструментом поиска ошибок. При пошаговом выполнении можно наблюдать за работой
программы и одновременно анали тропить результаты действия операторов
программы.
Основную функцию выполняет команда Step
Into, с помощью которой можно построчно выполнять программу.
С помощью команды Step Over пошагово
выполняется только текущая процедура. Это эффективно в том случае, если нужно
протестировать только текущую процедуру.
Вызываемая процедура выполняется за один шаг.
Командой Step Over можно начинать поиск ошибки для ее локализации. При
возникновении ошибки в вызываемой процедуре ее следует проверить с помощью
команды Step Into.
Задачей команды Step
Out является выход из процедуры без пошагового выполнения всех ее
операторов. Эта команда используется, если при выполнении процедуры вы ошибочно
вошли в вызываемую процедуру или если оставшуюся часть процедуры не нужно
выполнять пошагово.
Команда Run To
Cursor также может помочь, если проверяемая процедура содержит циклы. В
этом случае их просмотр командой Step Into может занять слишком много
времени, что особенно неприятно, если большая часть цикла выполняется
корректно. Эта команда используется всегда, когда нужно пропустить пошаговое выполнение
некоторых частей кода.
Список вызовов
При поиске ошибок
часто нужно знать последовательность вызова процедур. В окне Call Stack отображается
список имен всех выполняемых в данный момент процедур. Первым отображается имя
текущей процедуры. За ним следует список процедур в той последовательности, в
которой они были вызваны. Имя процедуры обработки события указывается в конце
списка. Таким образом образуется список всех вызванных процедур Sub, Function
или Property. После завершения процедура удаляется из списка.
Окно Call Stack позволяет отобразить
команда Call Stack... меню View, которая доступна только в режиме
отладки. Для открытия окна можно воспользоваться также комбинацией клавиш
[Ctrl+LJ или соответствующей кнопкой на панели Debug.
С помощью кнопки Show
этого окна осуществляется переход в окно кода
к выбранной в списке
процедуре.
Кроме этого, на
полосе индикатора зеленым треугольником отмечается строка, содержащая вызов
процедуры.
Область применения
Как правило, каждой
процедуре передаются параметры. Если вызванная процедура содержит ошибку,
связанную с неправильно заданным параметром, то благодаря списку вызовов можно
легко определить, какая процедура или функция передала этот параметр.
Если процедура
вызывается другой процедурой неоднократно, то Visual Basic выделяет строку, из
которой выполнен текущий вызов. Это значительно облегчает поиск ошибки в
вызывающей процедуре. Благодаря списку вызовов можно просмотреть всю цепочку
вызова процедуры.
Отображение значений
Кроме контроля хода
выполнения программы важной задачей инструментов отладки Visual Basic является
проверка значений выражений. Для реализации механизма просмотра (watch) Visual
Basic предлагает несколько способов.
Контроль значений
возможен только в режиме отладки. Более того, контролируемое выражение доступно
только в определенных местах; например, значение локальной переменной можно
проверить только в процедуре, в которой она объявлена. При попытке проверить
значение выражения за пределами области определения появляется сообщение
"Out of context" ("Вне контекста").
Data Tips
Самый простой вариант
просмотра значения переменной или выражения — использование окна Data Tips, впервые
введенного в предыдущей версии Visual Basic. Для открытия этого окна достаточно
установить курсор мыши на соответствующем выражении в окне кода.
Однако окно Data
Tips отображается только для переменных, значение которых в данный момент
можно определить.
По умолчанию это окно
содержит значение одной переменной. Если же необходимо увидеть значение
выражения, его следует выделить, а затем установить на нем курсор мыши.
Quicklnfo
В режиме отладки
можно также использовать команду Quicklnfo меню Edit, которая
позволяет отобразить синтаксис для переменной, функции, оператора, метода или
процедуры, выбираемых в окне кода. Вызвать эту команду,
действующую и в режиме
проектирования, можно также с помощью комбинации клавиш [CtrI+I].
Parameterlnfo
Команда Parameter
Info меню Edit позволяет получить информацию о параметрах
используемой функции или оператора.
Обратите внимание на различие между
рисунками 5.21 и 5.22. Команда
Quicklnfo отображает описание текущей функции,
в то время как Parameterlnfo отображает
описание функции,
которая является параметром процедуры. Эта функция активизируется командой Parameterlnfo
меню Edit. При этом текстовый курсор должен находиться в
контролируемом выражении. Для активизации функции можно также использовать
комбинацию клавиш
rCtrl+Shin+11.
Quick
Watch
Еще одну возможность
просмотра значений выражений предоставляет сохра нившееся из предыдущих версии
окно Quick Watch, вызываемое командой Quick Watch меню Debug
либо комбинацией клавиш [Shift+F9]. При вызове команды текстовый курсор должен
находиться внутри имени контролируемой переменной. Для открытия окна можно
также воспользоваться соответствующей кнопкой панели инструментов Debug.
Завершить работу с
диалоговым окном Quick Watch можно нажатием кнопки Cancel. Обычно данное
окно используется не только для просмотра значения переменной, но и для
добавления этой переменной в окно просмотра (Watch Window).
Добавление контрольного значения
Часто при поиске
ошибки необходимо постоянно контролировать значения выражения. В этом случае
вместо того чтобы открывать каждый раз окно для просмотра значения, гораздо проще
и удобнее постоянно видеть значение выражения на экране. Для этого
предназначена команда Add Watch... меню Debug. После выполнения
этой команды отображается диалоговое окно Add Watch, позволяющее не
только добавить нужное выражение в окно просмотра, но и определить
дополнительные параметры просмотра и выполнения программы. Например, в полях
группы Context можно задать область определения переменных в контрольном
выражении. Опции группы Watch Type определяют, как ведет себя Visual
Basic при изменении значения выражения: просто отображает это изменение (по
умолчанию); переходит в режим отладки, если значение становиться равным True,
или переходит в режим отладки, если значение выражения изменилось.
Добавить переменную в
окно просмотра можно также из диалогового
окна
Quick Watch, воспользовавшись
кнопкой Add.
Диалоговое окно Add
Watch позволяет внести изменения в контролируемое выражение. После внесения
изменений соответствующее выражение появляется и окне просмотра.
Редактирование контрольного значения
Значения параметров,
устанавливаемые при добавлении выражения в окно контрольного значения, можно
изменить с помощью команды Edit Watch... меню Debug. В результате
выполнения этой команды отображается диалоговое окно Edit Watch, похожее
на окно Add Watch.
Это же окно можно вызвать с помощью
комбинации клавиш [Ctrl+W]. Оно также позволяет не только редактировать, но и
удалять контролируемые выражения (кнопка Delete).
Область применения
Рассмотренный
механизм контроля значений переменных имеет большое значение. При поиске ошибок
разработчику требуется как можно больше информации. Благодаря информации о
текущем состоянии программы он легко может выявить источник ошибки.
Представьте себе, что
константе присвоено ошибочное значение. При выполнении программы определить
ошибку не так просто. Однако контролируя текущее значение константы, вы сможете
быстро обнаружить такую ошибку.
Если в операторах
ветвления не выполняется требуемая ветвь, то проверяя условие ветвления, можно
легко определить, почему не выполняется переход на нужную ветвь программы, а
при неожиданном выходе из цикла можно выяснить причину такого выхода.
Окна режима отладки
Среда разработки
Visual Basic предоставляет разработчику три окна отладки программы. Окно
контрольного значения (Watch Window) отображает список контролируемых
выражений и их текущие значения. Окно отладки (Immediate Window) позволяет
выполнять однострочные операторы. В окне локальных переменных (Locals Window)
отображаются все объявленные переменные и их значения текущей процедуры.
Внимание
Содержимое окон
режима отладки, за исключением окна отладки, обновляется только при
переключении в режим отладки. В режиме выполнения в них отображаются значения,
сохранившиеся с момента завершения последнего режима отладки.
Окно контрольного значения
Как уже упоминалось,
после вызова команды Add Watch... или Edit Watch... меню Debug
открывается окно контрольного значения со списком контролируемых выражении.
Это окно открывается
с помощью команды меню View\Watch Window.
Проще всего для
добавления выражения в список воспользоваться методом Drag & Drop для
перетаскивания выражения из окна кода в окно контрольного значения. В первом
столбце окна отображается контролируемое выражение и пиктограмма, отражающая
способ просмотра контролируемого выражения, который устанавливается в
диалоговом окне Add Watch.
Пиктограмма,
изображающая очки (тип просмотра Watch Expression), показывает, что
будет отображаться только текущее значение выражения, которое будет
автоматически обновляться при переходе в режим отладки. Пиктограмма руки со
знаком равенства (тип просмотра Break When Value Is True) показывает,
что если значение контролируемого выражения становится равным True или
ненулевым, то осуществляется автоматический переход в режим отладки. Пиктограмма
руки с треугольником (знак Д (дельта), или символ приращения) обозначает, что
выполнение программы прерывается при изменении значения выражения.
Выражение,
отображаемое в первом столбце окна контрольного значения, можно не только
просматривать, но и редактировать. Причем для этого (за исключением случаев
изменения области или типа просмотра) не надо вызывать диалоговое окно Edit
Watch — достаточно щелкнуть на требуемом выражении.
Во втором столбце
отображаются текущие значения выражений. Обратите внимание, что текущее
значение отображается только в режиме отладки. В этом режиме можно изменять и
значение выражения (если это допускается). Для этого достаточно щелкнуть на
нужном значении, а затем внести изменения.
Третий столбец
отображает тип данных соответствующего выражения. Обратите внимание, что хотя
сравниваются значения двух переменных типа Single и Integer, типом данных
результата является Boolean, так как выражение может возвращать только True ИЛИ
False.
В последнем столбце
указывается объект, которому принадлежит выражение или переменная. Это значит,
что значение отображается, если при просмотре область действия указанного
объекта больше или равна текущей области действия.
Объекты
Окно контрольного
значения может отображать не только значения простых выражении, но и сложные
структурированные объекты.
Если перед именем
объекта отображается знак плюс, то после щелчка на плюсе отображаются все
свойства объекта.
Окно локальных переменных
Окно локальных
переменных функционирует аналогично окну контрольного значения. Однако если в
окно контрольного значения необходимо явно добавлять выражения, то в окне
локальных переменных все локальные переменные отображаются автоматически.
Для открытия этого
окна следует вызвать команду Locals Window меню
View или щелкнуть на
соответствующей кнопке панели инструментов
Debug.
В первом столбце
отображаются имена локальных объектов и переменных. В первой строке приводится
главный объект (форма, модуль или модуль класса), т.е. объект, которому принадлежит
выполняемая процедура или функция.
На рис 5.30 вы видите значения свойств
объекта Me, характеризующего соответствующую форму, а также значения свойств
элемента управления Commandl. Во втором столбце выводятся текущие значения,
которые можно редактировать,
если
они не защищены от
записи. В третьем столбце указывается тип данных соответствующей переменной.
Преимуществом этого окна по сравнению с окном контрольного значения
является то, что все
локальные переменные и объекты отображаются автоматически.
Окно
отладки
В режиме отладки в это окно можно вводить и
выполнять код Visual Basic. Однако многострочные конструкции, например For. .
.Next, использовать нельзя. Для открытия окна отладки следует вызвать команду Immediate
Window меню View или воспользоваться комбинацией клавиш [Ctrl+G]. В
этом окне можно не только изменять содержимое переменных или свойств, но и
применять методы объектов, что позволяет, например, сымитировать логическую
ошибку или вызывать процедуру. Для выполнения оператора нужно перейти на новую
строчку клавишей [Enter]; текстовый курсор при этом может не находиться в конце
строки.
После выполнения
строка из окна не удаляется, поэтому ее можно выполнять несколько раз с
измененными, при необходимости, значениями. В окне отладки можно осуществлять
не только ввод, но и вывод, воспользовавшись методом Print. Для этого оператору
Print передается требуемое выражение, и после нажатия клавиши [Enter] результат
отобразится в следующей строке.
Обратите внимание,
что с помощью перетаскивания можно перемещать выражения из окна кода в окно
отладки и наоборот.
Оператор Print
Вместо оператора
Print можно использовать вопросительный знак (?), как это было в старых
диалектах Basic. В окне отладки сохраняются последние 200 строк, которые можно
редактировать или выполнять повторно.
Объект Debug
Окно отладки можно
использовать и подругому. В этом случае, используя объект Debug и его метод
Print, сообщения окну посылают из программного кода. Возможность такого вывода
в окно отладки имеет несколько преимуществ. Вопервых, выводить таким образом
контрольные значения можно не только в режиме отладки, но и в режиме
выполнения, что позволяет выводить выражения, не останавливая выполнение
программы. Вовторых, выведенные значения, отображаемые в окне отладки, можно
просмотреть даже после остановки программы. Это важно в случаях, когда
поведение программы при пошаговом выполнении отличается от поведения при
нормальном выполнении, например при передаче фокуса или при приеме данных в
режиме реального времени. В этом случае можно выполнять различные процедуры,
одновременно наблюдая результаты выполнения программы:
If.X=0 Then
Call Left
Debug.Print
"Поворот налево, Х="; X Else
Call
Right
Debug.Print
"Поворот направо, X="; X End If
Объект Debug является
системным объектом, и поэтому ключевое слово Debug нельзя использовать для
задания имен других объектов.
Окно
отладки можно также использовать для циклического вывода текущих значении. Но
помните о том, что в этом окне сохраняются только последние 200 строк.
Скорость
Следует помнить, что
при частом использовании окна отладки для вьшода информации может замедлиться
выполнение программы. Однако после удаления операторов Debug. print или после
создания ЕХЕфайла скорость выполнения восстанавливается.
Метод Assert
Метод Assert
приостанавливает выполнение программы и переключает среду разработки в режим
отладки, если проверяемое логическое выражение становится равным False. Рис.
5.33 демонстрирует метод Assert в действии. Когда значение параметра х
становится равным 0 (равнозначно False), то выполнение приостанавливается. Хотя
это же действие можно выполнить и с помощью оператора Stop, преимущество
объекта Debug состоит в том, что он работает только при запуске приложения из
среды разработки. Другими словами, строки с обращением к объекту Debug при
создании ЕХЕфайла воспринимаются как строки комментария. Поэтому удалять
обращения к объекту Debug перед созданием исполняемого файла не нужно.
Область применения
Окна режима отладки
предоставляют широкие возможности для контроля состояния программы.
В окне контрольного
значения обычно контролируются переменные и выражения, являющиеся вероятными
источниками ошибок.
В окне локальных
переменных отображаются имена и значения всех локальных переменных активного
объекта. Окно отладки позволяет непосредственно выполнять отдельные операторы и
выводить значения выражений. Так, например, можно выводить значение свойства
Number объекта Err для определения номера ошибки после ее возникновения.
Благодаря тому, что окно отладки отображается и в режиме выполнения, с помощью
метода print объекта Debug можно контролировать значения выражений во время
выполнения программы.
Закладки
С помощью закладок можно помечать
определенные строки кода, а затем быстро
перс\о.'1ить
к этим строкам. Строка с закладкой соответствующим образом выделяется. Команды
Next Bookmark и Previous Bookmark меню Edit позволяют легко
перемещаться между закладками. Это удобно, если необходимо переходить от одного
участка кода к другому. Если закладки больше не нужны, их можно
удалить, вызвав
команду Clear All Bookmarks.
Л/с. /^.34. Команды работы с
закладками в меню Edit
Рис. ?.35. Зик
iuiii<a считывания в окне кода
Соглашения по коду
Современные средства
разработки, в частности Visual Basic, предлагают большое количество различных
средств отладки. Однако избегать ошибок следует еще на этапе разработки
программы. При этом хорошую услугу может оказать стандартизированное присвоение
имен переменным, формам, элементам управления. При создании
приложения разработчик должен стремиться не
только создать работоспособную программу, но и сделать это "красиво",
т.е. код должен быть понятен и другим разработчикам даже при минимуме
комментариев.
Важной составной
частью "хорошего кода" является соглашение об именах. Использование
этого соглашения на первый взгляд приносит только дополнительные издержки, но
они оправдываются при поиске ошибок и сопровождении проекта. При коллективной
работе стандарт имен также дает дополнительные гарантии взаимопонимания
разработчиков. Поэтому никогда не следует игнорировать этот стандарт, так как
рано или поздно сэкономленное на этом время придется затратить опять.
Присвоение имен переменным
Цель использования
стандарта имен — сделать более понятными область действия, тип данных и назначение
переменной. При присвоении имени часто используется общепризнанная
"венгерская нотация". В соответствии с этой нотацией имя состоит из
одного или нескольких префиксов и базового имени:
<ПрефиксХБазовое_имя>
Ограничения имен
При задании имен в
Visual Basic действуют следующие ограничения:
.
• имя должно начинаться с буквы;
.
• имя может содержать только буквы, числа и символ
подчеркивания;
.
• максимальная длина имен форм и элементов управления — 40
символов,имена переменных и типов могут иметь длину до 255 символов;
.
• в качестве имен нельзя использовать зарезервированные слова
Visual Basic.
Тип данных
Одним из самых важных
отличительных признаков переменной является ее тип данных, поэтому он должен
отражаться в имени переменной. Обычно в качестве префикса используются
трехзначные комбинации символов, хотя для наиболее часто используемых типов
практичнее использовать только один символ.
Таблица 5.2. Префиксы
типов данных Тип данных Префикс Пример
Boolean |
bin |
bInFound |
Byte |
byt |
bytRasterData |
Collection (семейство) |
col |
colWidgets |
Currency |
cur |
curRevenue |
Date |
dtm |
dtmStart |
Double |
dbl |
dblTolerance |
Error |
err |
errOrderNum |
Integer |
int |
intQuantity |
Тип данных |
Префикс |
Пример |
Long |
Ing |
IngDistance |
Object |
obj |
objCurrent |
Single |
sng |
sngAverage |
String |
str |
strFName |
Пользовательский |
udt |
udtEmployee |
Variant |
vnt |
vntCheckSum |
В больших проектах,
содержащих множество собственных типов данных, имеет смысл присвоить каждому
типу собственный знак типа, начинающийся с символа "и".
Написание имен
переменных с суффиксом устарело. Поэтому уже в Visual Basic 4.0 новые типы
данных не имеют собственных суффиксов. Использование префиксного написания
имеет то преимущество, что одинаковые типы данных можно записывать в алфавитной
последовательности непосредственно один под другим.
Структуре <Тип
данныхХБазовое имя> соответствует, например, fLongDistance для
переменной типа Double с базовым именем LongDistance.
Dim ICounter As Long
Dim sMessage As String Dim cPayment As Currency
При преобразовании
типов Visual Basic пытается преобразовывать их, по возможности, автоматически:
cPayment = ICounter ilndex •=
CInt(ICounter)
Благодаря
использованию префикса типа легко локализовать ошибки преобразования.
Тип данных Variant
Использовать тип
данньк variant следует осторожно. Вопервых, его внутренние функции
преобразования работают медленнее, чем соответствующие функции Visual Basic
(например, ccur и т.п.). Во вторых, при неявных преобразованиях типа могут
возникать каверзные ошибки:
Dim
vntA As Variant Dim vntB As Variant
Dim
vntA As Variant Dim vntB As Variant
vntA =• "2.5" vntB
= "7"
Debug.Print vntA + vntB ' Результат
2.57 Debug.Print
vntB + vntA ' Результат 72.5
Тип Variant введен в
Visual Basic для облегчения начинающим программистам работы с различными типами
данных, однако опытные программисты могут легко обойтись и без него.
Область действия
Область действия
переменной также\ должна отражаться в ее имени. Для этого используются
префиксы, приведенные в табл. 5.3.
Таблица 5.3. Префиксы области действия
Префикс |
Область действия |
9 |
Глобальная |
Я1 |
Модуль, форма, класс |
отсутствует |
Локальная |
Обратите
внимание, что локальные переменные не имеют собственного префикса, что отличает
их от переменных модуля, класса, формы или глобальных.
Структуре <0бласть действияХТип данныхХБазовое
имя> соответствует, на пример, miRecordCount для переменной формы, модуля
или класса типа Long с базовым именем RecordCount.
Запись
имени
. При задании базовых
имен также следует соблюдать определенные правила. Имя переменной должно
отражать ее содержимое. Только имена "i", "j" и
"k" принимаются в качестве счетчика:
For i = 0 То 5
sResult = MatchHormal (i) Next
Избегайте непонятных
сокращений типа vntADatum, vntActD или vntAD. При необходимости сокращения
следует отказываться от гласных. Значительно повышает читабельность имен
использование прописных и строчных букв. При написании префикса строчными
буквами понятно, где заканчивается префикс, а где начинается базовое имя.
Сравните, например:
giformheight
giFormHeight
Рассмотрите следующий
пример:
vntActualDate (текущая дата)
vntActualTime (текущее время)
vntBeginDate (начальная дата)
vntBeginTime (начальное время)fs24 RvntEndDa te (конечная дата) vntEndTime
(конечное время)
Удачно ли выбраны
имена? Сравните их с этими именами:
vntDateActual
(текущая дата)
vntDateBegin (начальная дата) vntDateEnd
(конечная дата) vntTimeActual (текущее время) vntTimeBegin (начальное время)
vntTimeEnd (конечное время)
Вторая запись может
показаться несколько необычной, однако используемые имена переменных записаны в
алфавитном порядке.
Константы
В первых версиях
Visual Basic константы записывались прописными буквами. Теперь для них
используются как прописные, так и строчные буквы (например, vbKeyFl). Но все же
для констант, определяемых пользователем, рекомендуется применять прописные
буквы:
Const PI = 3.14159265
Если константа
объявляется с заданием типа данных, то в качестве префикса можно использовать
описанные выше сокращения:
Const rPI As Single
•= 3.14159265
Функции и аргументы
Функции возвращают
значения определенного типа, следовательно имена функций также могут содержать
сокращения для соответствующего типа данных.
При передаче
аргументов, наряду с типом данных, важное значение имеет и вид передачи.
Поэтому при передаче аргументов также может использоваться префикс,
определяющий вид передачи аргумента — как ссылки или как значения.
Таблица 5.4. Префиксы
передачи аргументов Префикс Вид передачи
ByVal
г ByRef
Следующий пример
показывает правило определения имени функции и ее параметров в соответствии со
структурой <ВвдПередачи><ТипДанных><БазовоеИмя>:
Function
IDaysCount(ByVal vdFirstDate As Date, ByVal vdLastDate As Date) _ As Long
End Function
Присвоение имен объектам
Имена присваивают не
только переменным, но и объектам. И эти имена также должны отражать основные
особенности объекта.
Элементы управления
В элементах
управления и формах используются правила, сходные с правилами присвоения имен
для переменных и констант.
Формы
Для различных типов
форм, встречающихся в проекте, используются следующие префиксы:
Таблица 5.5. Префиксы
типов форм Префикс Тип формы frm |
Обычная |
mdifrm |
MDIформа |
cfrm |
Дочерняя MDIформа (MDIChild) |
dfrm |
Диалоговая форма |
Элементы управления
Для обозначения
элементов управления в Visual Basic используются следующие сокращения:
Таблица 5.6. Префиксы типов элементов
Элемент управления |
Префикс |
Пример |
3D Panel |
pnl |
pnlGroup |
ADO Data |
ado |
adoBiblio |
Animated button |
ani |
aniMailBox |
Check box |
chk |
crikReadOnly |
Combo box, dropdown list box |
cbo |
cboEnglish |
Command button |
cmd |
cmdExit |
Common dialog |
dig |
dIgFileOpen |
Communications |
corn |
comFax |
Элемент управления (если
конкретный |
ctr |
ctrCurrent |
тип неизвестен) |
|
|
Data |
dat |
datBiblio |
Databound combo box |
dbcbo |
dbcboLanguage |
Databound grid |
dbgrd |
dbgrdQueryResult |
Databound list box |
dblst |
dblstJobType |
Data combo |
dbc |
dbcAuthor |
Data grid |
dgd |
dgdTitles |
Data list |
dbl |
dblPublisher |
Элемент управления |
Префикс |
Пример |
Data repeater |
drp |
drpLocation |
Date picker |
dtp |
dtpPublished |
Directory list box |
dir |
dirSource |
Drive list box |
drv |
drvTarget |
File list box |
fil |
filSource |
Flat scroll bar |
fsb |
fsbMove |
Form |
frm |
frmEntry |
Frame |
fra |
fraLanguage |
Gauge |
gau |
gauStatus |
Graph |
gra |
graRevenue |
Grid |
grd |
grdPrices |
Hierarchical flexgrid |
flex |
flexOrders |
Horizontal scroll bar |
hsb |
hsbVolume |
Image |
img |
imglcon |
Image combo |
imgcbo |
imgcboproduct |
ImageList |
ils |
ilsAllIcons |
Label |
Ibl |
IblHelpMessage |
Lightweight check box |
Iwchk |
IwchkArchive |
Lightweight combo box |
Iwcbo |
IwcboGerman |
Lightweight command button |
Iwcmd |
IwcmdRemove |
Lightweight frame |
Iwfra |
IwfraSaveOptions |
Lightweight horizontal scroll
bar |
Iwhsb |
IwhsbVolume |
Lightweight list box |
Iwlst |
IwlstCostCenters |
Lightweight option button |
Iwopt |
IwoptIncome Level |
Lightweight text box |
Iwtxt |
IwoptStreet |
Lightweight vertical scroll
bar |
Iwvsb |
IwvsbYear |
Line |
lin |
linVertical |
List box |
1st |
IstPolicyCodes |
ListView |
Ivw |
IvwHeadings |
MAPI message |
mpm |
mpmSentMessage |
MAPI session |
mps |
mpsSession |
MCI |
mci |
mciVideo |
Menu |
mnu |
mnuFileOpen |
Элемент управления |
Префикс |
Пример |
Month view |
mvw |
mvwPeriod |
MS Chart |
ch |
chSalesbyRegion |
MS Flex grid |
msg |
msgClients |
MS Tab |
ntst |
mstFirst |
OLE container |
ole |
oleWorksheet |
Option button |
opt |
optGender |
Picture Ъох |
pie |
pi с VGA |
Picture clip |
cip |
elpToolbar |
ProgressBar |
prg |
prgLoadFile |
Remote Data |
rd |
rdTitles |
RichTextBox |
rtf |
rtfReport |
Shape |
shp |
shpCircle |
Slider |
sid |
aldScale |
Spin |
spn |
spnPages |
StatusBar |
sta |
staDateTime |
Syslnfo |
sys |
sysMonitor |
TabStrip |
tab |
tabOptions |
Text box |
txt |
txtLastName |
Timer |
tmr |
tmrAlarm |
Toolbar |
tib |
tIbActions |
TreeView |
tre |
treorganization |
UpDown |
upd |
updDirection |
Vertical scroll bar |
vsb |
vsbRate |
Если используются однотипные элементы управления, но
разных разработчиков, то это тоже можно указать в префиксе:
atabDialogTab "Элемент управления
фирмы А btabDialogTab 'Элемент управления фирмы В
Правила
наименования команд меню
В приложениях часто
используются меню. Для этого элемента управления применяются несколько отличные
правила наименования. В качестве префикса используется mnu, а имя должно отображать
структуру меню:
File mnuFile File/Open mnuFileOpen Edit/Copy
mnuEditCopy Edit/Insert mnuEditInsert
При использовании
такого правила именования взаимосвязанные имена записываются одно под другим в
алфавитном порядке, и каждое имя дополнительно отражает позицию команды в
дереве меню:
File ' mnuFile
File/Open mnuFileOpen Edit/Copy mnuEditCopy Edit/Insert mnuEditInsert
Для того, чтобы имена
были короче, можно использовать горячие клавиши вышестоящих уровней меню.
Дублирование
имен
Иногда (хотя этого
следует избегать) элементу управления присваивают имя, являющееся
зарезервированным словом Visual Basic.
Select.Caption =
"Hello" 'Эта строка вызывает ошибку
В этом примере
зарезервированное слово Select используется как имя объекта, что приводит к синтаксической
ошибке. Если же обращаться к элементу управления с указанием его родителя
(например, формы) либо как к внешнему объекту, заключив его имя в квадратные
скобки, то такой доступ возможен:
Me.Select.Caption =
"Hello" ' С указанием родителя (форма) [Select].Caption =
"Hello" ' Как к внешнему объекту
Объекты
базы данных
Объекты базы данных являются важной составной
частью Visual Basic, поэтому их также следует снабжать соответствующими
префиксами.
Таблица 5.7. Префиксы типов объектов базы
данных
Объект базы данных |
Префикс |
Пример |
Container |
con |
conReports |
Database |
db |
dbAccounts |
DBEngine |
dbe |
dbeJet |
Document |
doc |
docSalesReport |
Field |
fid |
fIdAddress |
Group |
grp |
grpFinance |
Index |
ix |
idxAge |
Parameter |
prm |
prmJobCode |
QueryDef |
qry |
qrySalesByRegion |
Recordset |
rec |
recForecast |
Объект базы данных Префикс Пример
Relation rel relEmployeeDept
TableDef tbd tbdCustomers
User usr usrNew
Workspace wsp wspMine
Dim dbBooks As Database
Set dbBooks = OpenDatabase ("BIBLIO.MDB")
Объекты 01Е
Число
приложений, обладающих OLEавтоматизацией, стремительно растет. Поэтому
становится трудно подбирать трехсимвольные префиксы. Для того, чтобы найти
определенный префикс, используются первые три символа имени объекта:
Dim rngRange As Range
Dim wkbMap As Workbook
Если используются
OLEобъекты из других приложений, желательно указывать происхождение объекта.
Dim wobApp As Object
'Microsoft WordBasic Dim xlbApp As Object 'Microsoft Excel Basic
В этом случае
структура префикса также зависит от вида приложения и среды, но решающим
фактором всегда является последовательное использование установленных правил.
OLEсервер
При работе с
OLEсервером особое значение имеет совместимость при присвоении имен, поскольку
в интерфейсах с клиентскими OLE приложениями программисты используют внутренние
имена OLE серверов. Поэтому в любом случае нужно избегать сокращений, используя
имена объектов во множественном числе. Собственные константы также должны
начинаться единым префиксом.
Порядок кодирования
Кроме правильного
назначения имен, существуют и другие способы избежания проблем. К ним
относятся, наряду с комментариями, явное объявление переменных и структурное
форматирование кода.
Option Explicit
Обычно в языках
высокого уровня все переменные должны объявляться явно. Однако Visual Basic
допускает использование не объявленных явно переменных. Для того чтобы не
забыть объявить переменную, используйте опцию Option Explicit, добавляя ее в
раздел (General) (Declarations) контейнера. Но для того, чтобы не делать
это самим и не забыть
это сделать, установите опцию Require Variable Declaration вкладки
Editor диалогового окна Tools\0ptions (рис. 5.36).
Только для нового контейнера
После этого во всех
вновь создаваемых контейнерах (формах, модулях, классах) в секции объявлений
автоматически добавляется строка Option Explicit. Однако это не происходит в
уже существующих контейнерах.
Option
Explicit Defint AZ
Л/с 5.3(i.
Установки Require Variable Declaration
Явное объявление
переменных сокращает время разработки, так как благодаря этой опции можно
быстро определить описку:
iVariable = 5 iVariabel =. iVariable + 10
Debug.Print iVariable ' Результат 5
Данный пример
демонстрирует, насколько трудно обнаружить описку, если вместо имени iVariable
случайно использовать имя iVariabel.
Defint
Для дополнительной
гарантии можно использовать операторы вида Defint. Если в секции (General)
(Declarations) ввести строку Defint AZ, то все переменные, для которых при
объявлении не указан тип данных и имена которых начинаются символом от А до Z,
автоматически считаются переменными типа integer. Это позволяет легко
предугадать поведение программы в отношении переменных, для которых при
объявлении не указан тип данных и не производится автоматическое преобразование
типа переменных Variant.
vntTest
30 vntTest vntTest + 20
vntTest vntTest & " штук"
vntTest " vntTest 5 ' Ошибка 13:
несовместимый тип данных
В приведенном примере
еще относительно легко установить тип данных, которые содержатся в настоящий
момент в переменной типа Variant. Поэтому очевидно, что в четвертой строке
попытка вычитания числа из символьной строки невозможна. Однако если бы строки
находились в разных местах программного кода, то найти ошибку было бы сложнее.
Dim iTest As Integer, sTest As String
sTest = "30"
iTest = CInt(sTest) + 20
sTest = CStr (iTest) & " штук"
sTest = sTest 5 ' Ошибка 13: несовместимый тип данных
В приведенном примере
используются явно объявленные переменные с указанием типа данных и явные
преобразования. Благодаря правильному назначению имен переменным (корректные
префиксы) в этом примере легко обнаруживается ошибка, связанная с вычитанием
числа из символьной строки.
Структурное
форматирование кода
При написании кода
операторы также следует располагать по определенным правилам. Конечно, это не
жесткое требование и вы можете располагать операторы как угодно, однако
правильно структурированный код не просто легче воспринимается — это может
помочь и при поиске ошибок.
Sub
Test ()
For i ° iStart To iEnd
Веер If ...
Then
MsgBox "True" Else
MsgBox
"False" End If Next i End Sub
Благодаря приведенному в примере построению
можно быстро обнаружить ошибку структуры. Синтаксическая конструкция
заканчивается в том же столбце, в котором начинается. Вложенные конструкции
вставляются дальше.
Операторы Sub и End Sub находятся в столбце
слева, ограничивая процедуру. Цикл For.. .Next расположен на один отступ
табуляции правее. В свою очередь, операторы If.. .Then.. .Else записаны еще
дальше, чтобы показать, что они находятся внутри цикла. Еще больший отступ
используется для операторов MsgBox. Благодаря такому расположению ясно, что они
находятся в различных ветках оператора If... Then. . . Else.
Visual Basic позволяет легко выполнять
подобное форматирование, автоматически устанавливая после перевода строки
текстовый курсор в том же столбце, в котором начиналась предыдущая строка.
Настройка этой опции осуществляется во вкладке Editor диалогового окна
настройки Tools\0ptions.
Значение параметра Tab
Width определяет размер отступа. Значение по умолчанию — четыре символа.
Опция Auto Indent определяет, будет ли текстовый курсор после перевода
строки автоматически переходить в тот же столбец, в котором начиналась
предыдущая строка. Если эта опция отключена, то в новой строке курсор всегда
устанавливается в первом столбце.
Разделители строк
Для разделения одной
логической строки на несколько физических в Visual Basic существует специальная
комбинация символов (Пробел + Символ подчеркивания), называемая разделителем.
Использование разделителей может быть полезным для улучшения читабельности
программы, особенно если некоторые длинные операторы не помещаются полностью на
экране. Однако следует учитывать, что в одной логической строке может быть
только 24 разделителя, т.е. логическая строка ограничивается максимум 25
физическими строками.
Благодаря
использованию разделителей возможно форматирование кода таким образом, чтобы
длинная строка полностью появлялась на экране и ее можно было редактировать, не
используя полосы прокрутки:
Declare Function
RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (
_ ByVal hKey As Long, _ ByVal IpSubKey As String, _ ByVal Reserved As Long, _
ByVal IpClass As String, _ ByVal dwOptions As Long, _ ByVal sampesired As Long,
_ IpSecurityAttributes As SECURITY_ATTRIBUTES, _ phkResult As Long, _
IpdwDisposition As Long) As Long
Такое форматирование позволяет нагляднее
оформлять, например, объявления функций API.
При использовании
разделителя строк важным является пробел перед ним. Подчеркивание —
единственный небуквенный и нецифровой символ, допустимый в имени, поэтому если
он добавляется прямо к слову, то считается составной частью имени:
dummy Shell(Left(App.Path, 2) S Path_HORK_ ,
vbNormalFocus) ' Разделитель не распознается
dummy Shell (Left (App. Path, 2) S PathJTORK _ ,
vbNormalFocus) ' Разделитель с пробелом перед ним распознается правильно
Однако слишком частое
использование разделителей делает код программы слишком длинным, что, в свою
очередь, может затруднить его просмотр.
Создание
длинных символьных строк
Разделители не
действуют внутри символьных строк:
Dim sMessage As String
sMessage
° "Это сообщение должно _
выводиться позже в
MsgBox!" ' разделитель строки находится внутри символьной строки ' и
поэтому не распознается Visual Basic.
Поэтому при составлении
длинных строк или операторов SQL используется следующий способ:
Dim sMessage As String
sMessage =° "Это сообщение должно"
sMessage • sMessage & " выводиться позже" & vbCriLf
sMessage = sMessage & " в MsgBox!"
MsgBox sMessage, vbOK, "Длинное сообщение"
В этом примере символьная строка составляется
последовательно. Благодаря этому на экране помещается весь текст. Кроме того,
для разделения сообщения на несколько строк можно добавлять символы перевода
строки.
Символ объединения строк
Visual Basic
позволяет не только разбивать одну логическую строку на несколько физических,
но и объединять в одной строке несколько операторов. Для объединения операторов
в одну строку используется символ двоеточия (:).
х 1: у = 2 'Соединенная строка остается наглядной
MsgBox
"Hello": For i = 1 То 3: Веер: х = у. + 1: Next i 'Скорее
запутывает
Аналогично
разделителю строк, символ объединения строк используется для повышения
читабельности кода. Благодаря объединению простых операторов в одну строку,
программа становится короче и на экране помещается большая часть кода.
Использовать этот
символ следует осмотрительно, так как слишком длинная строка может только
запутать пользователя.
Операторы & и +
В Visual Basic
оператор + (плюс) может использоваться как для математического сложения, так и
для соединения (конкатенации) строк. Поэтому при сложении лучше использовать
символ +, а при соединении строк — символ &. В противном случае могут
возникнуть неожиданные последствия, особенно при использовании переменных типа
Variant:
vntVarA =
"40,04" 'Строка vntVarB = 27
'Целое Debug.Print vntVarA + vntVarB 'Результат 67,04 Debug.Print
vntVarA & vntVarB 'Результат 40,0427
Кроме того, следует
помнить, что символ & используется еще и в качестве суффикса для переменных
типа Long. Поэтому не нужно надеяться на автоматическую вставку пробела
редактором Visual Basic, если оператор & присоединен непосредственно к
имени:
Debug.Print vntVarAS
vntVarB 'Выводит переменные vntVarA и vntVarB Debug.Print vntVarAS &
vntVarB 'Выводит строковое объединение переменных vntVarA и vntVarB
В первой строке
символ & интерпретируется как идентификатор типа Long, а не как оператор
соединения. В третьей строке первый символ & определяет тип переменной
Long, а второй символ & является оператором соединения.
Комментарии
Для выделения
комментариев в Visual Basic используйте оператор Rem или символ'.
Перед заголовком
процедуры обычно помещается комментарий с описанием процедуры. Такой блок имел
бы следующее построение:
' Цепь: Функция определения содержания
кислорода в образце. ' Исх. данные: .0xy: Масса кислорода в мг
' fLi quid: Пробный объем в л ' Результат: iOxygenPercent: Доля кислорода в
пробном объеме в ' процентах
Function iOxygenPercent (fOxy As Double,
fLiquid As Double) As Integer
Dim i As Integer
'Счетчик цикла > ***************** ' Вычисление End
Function
Перед заголовком обычно описывается задача
процедуры, а затем назначение используемых входных и выходных параметров. В
конце оператора после символа можно добавить комментарий. Обратите внимание,
что оператор Rem может добавляться в строку только после символа :.
Отдельные разделы в
процедуре также можно снабжать комментариями.
Глава 6
Обмен данными между приложениями
Одно из основных
достоинств Windows — средства поддержки работы в многозадачном режиме,
позволяющие одновременно вьтолнять несколько приложений и других процессов. Для
организации передачи данных и связи между программами в Windows созданы
инструменты и структуры, обеспечивающие простое решение указанных задач.
Одна из таких
возможностей — обмен данными через буфер обмена (Clipboard). Команды Cut (Вырезать),
Copy (Копировать) и Insert (Вставить), которые имеются в меню Edit
(Правка) всех программ, работающих в среде Windows, используют буфер обмена
для временного хранения данных. При копировании данных с помощью буфера обмена
связь между документами не устанавливается. Это означает, что изменения данных
в источнике не отражаются автоматически в приемнике данных. Устранить этот
недостаток позволяет механизм DDE (Dynamic Data Exchange) — динамический обмен
данными, который обеспечивает согласованный протокол обмена данными между
приложениями, работающими в среде Windows.
Буфер обмена
Буфер обмена является
общим хранилищем данных для всех приложений Windows. Поэтому данными,
помещенными в буфер обмена, можно воспользоваться в любом приложении Windows.
Однако при этом следует учитывать формат данных. Содержимое буфера обмена можно
просмотреть с помощью программы CLIPBRD.EXE, входящей в состав Windows 95/98.
Если команды вызова этой программы нет в системном меню Windows 95/98, то
программу следует установить.
Поскольку буфер
обмена обеспечивает обмен данными между различными приложениями, он должен
поддерживать форматы данных различных типов. Предположим, текст из приложения
Windows нужно переместить в графический редактор, т.е. преобразовать отдельные
символы в графические изображения. В буфере обмена и в
приложенииисточнике никаких преобразований не
производится. Приложениеисточник только копирует данные в буфер обмена в нескольких
форматах, а приложениеприемник выбирает данные в соответствующем формате.
Доступные форматы для содержимого буфера обмена можно выбрать командой меню
View (Вид) программы CLIPBRD.EXE.
Доступ к буферу
обмена Windows из приложения Visual Basic обеспечивает объект Clipboard.
Чтобы каждый элемент
управления получал данные в понятном для него формате, например, объект TextBox
— символьные строки, a PictureBox — графические изображения, следует
использовать соответствующие методы объекта clipboard. Методы SetText и GetText
соответствующих объектов предназначены для работы с текстом, а методы GetData и
SetData — для работы с графикой. Используя различные методы, разработчик при
передаче информации может обеспечить совместимость форматов данных для выбранного
элемента управления.
Для записи и
считывания текстовых данных в объект clipboard и из него предназначены методы
SetText и GetText.
Метод SetText
Метод SetText
записывает текстовую строку в буфер обмена и заменяет текущее содержимое
буфера. При этом существует возможность определить формат строки, хранимой в
буфере:
Clipboard.SetText
text[, format] Скопировать
содержимое выделенного текстового поля (TextBox) в буфер обмена можно следующим
оператором:
Clipboard.SetText Textl.Text
Метод GetText
Метод GetText
возвращает содержимое буфера обмена в виде текстовой строки. Вызывается этот
метод как функция:
Text = Clipboard.Q«tT«xt([format])
Чтобы заменить
выделенный текст в текстовом поле содержимым буфера обмена, следует
воспользоваться методом GetText:
Textl.SelText •= Clipboard.GetTextО
Обмен графическими
данными между приложениями обеспечивают методы SetData И GetData
объекта Clipboard.
Метод SetData
Метод SetData
предназначен для вставки в буфер обмена графического изображения в заданном формате:
Clipboard.SetData picture!, format]
В приведенном примере
показывается, как скопировать графическое изображение из объекта PictureBox в
буфер обмена:
Clipboard.SetData Picturel.Picture
Метод GetData
Метод GetData
позволяет получить содержимое буфера обмена в виде графического изображения:
target = Clipboard.GetData([format])
Замену содержимого
элемента управления PictureBox содержимым буфера обмена в графическом формате
выполняет следующий оператор:
Picturel.Picture = Clipboard.GetData
В табл. 6.1 указаны
именованные константы форматов, которые должны использоваться при копировании
графических данных в буфер обмена и вставке из него. Чем больше форматов данных
поддерживает буфер, тем больше вероятность того, что приложениеприемник сможет
корректно импортировать данные.
Visual Basic
поддерживает форматы данных, перечисленные в следующей таблице.
Таблица. 6.1.
Константы форматов Clipboard Константа Значение Описание
vbCFLink |
&HFFFFBFOO |
Информация обмена DDE |
vbCFRTF |
&HFFFFBF01 |
RTFформат (Rich Text Format) |
vbCFText |
1 |
Текст (по умолчанию) |
vbCFBitmap |
2 |
Растровое изображение (*.ВМР)
|
vbCFMetafile |
3 |
Метафайл (*.WMF) |
vbCFDIB |
8 |
Независимое от устройства растровое изображе |
|
|
ние (*.DIB) |
Константа |
Значение |
Описание |
vbCFPalette |
9 |
Цветовая палитра |
vbCFEMetafile |
14 |
Расширенный метафайл (*.EMF) |
vbCFFiles |
15 |
Список имен файлов (Microsoft Windows Explorer) |
Форматы, задаваемые
константами vbCFBitmap,
vbCFMetafile, vbCFEMetafile, vbCFDiB и vbCFPalette, используют методы SetData
и GetData. Форматы, задаваемые константами vbCFLink, vbCFRTF и vbCFText,
применяются при использовании методов SetText И GetText.
Если при считывании
данных из буфера обмена формат явно не указан, нужный формат выбирается
автоматически. Для явного копирования данных из буфера обмена в виде растрового
изображения следует указывать константу vbCFBitmap:
Picturel.Picture =
Clipboard.GetData(vbCFBitmap)
Если объект Clipboard
содержит изображение не в растровом формате, то содержимое pictureBox просто
очищается. Поэтому, выполняя вставку данных из буфера, следует сначала
определить, содержит ли буфер данные нужного формата, и лишь затем принимать
решение о возможности вставки.
Метод GetFormat
Буфер обмена — это не
простое хранилище данных. Он имеет несколько областей, в которых хранятся
данные в нескольких форматах. Для проверки формата данных, хранящихся в буфере,
используется метод GetFormat.
Метод GetFormat
возвращает значение True или False в зависимости от того, содержит ли объект
clipboard данные указанного формата. Недостаток метода в том, что за один вызов
метода невозможно определить формат данных, которые хранятся в буфере, так как
для проверки каждого возможного формата следует выполнять отдельный запрос:
х = Clipboard.GetFormat(vbCFMetafile)
Метод GetFormat
возвращает True, если в буфере обмена есть данные указанного формата.
Метод Clear
Если буфер обмена
содержит данные, то после вызова метода SetData или SetText данные указанного
формата переписываются в объект, но в буфере сохраняются данные в других
форматах. Чтобы в буфере не находились одновременно данные из нескольких
приложений, перед экспортом данных в Clipboard следует удалить все его
содержимое. Для этого применяется метод Clear:
Picturel. Picture LoadPictureC'PICT.WMF") Clipboard.Clear
Clipboard.SetData Picturel.Picture, vbCFMetafile Clipboard.SetData
Picturel.Image, vbCFBitmap
В данном примере
выполняется копирование данных в нескольких форматах в буфер обмена. Сначала в
элемент управления PictureBox помещается метафайл (PICT.WMF). Затем после
очистки буфера обмена в него копируется загруженный метафайл (свойство
Picture). Свойство Image всегда содержит растровое изображение, даже если в
PictureBox загружен файл другого формата, и именно в таком формате (константа
vbCFBitmap) изображение помещается в буфер обмена.
Использование методов
Применять
рассмотренные методы в Visual Basic достаточно просто. Однако следует помнить,
что стандартные команды приложения Cut, Copy и Insert должны
функционировать так же, как аналогичные стандартные команды Windows. To есть,
команда меню должна работать не только с определенным, известным по имени
элементом управления, но и с любым активным элементом управления, находящимся в
форме. Кроме того, должны быть доступны только те действия, которые имеют смысл
в данный момент. Другими словами, если нет вьвделенного текста или изображения,
команды копирования и вырезания должны быть недоступны.
Решить первую
проблему можно с помощью свойства формы ActiveControl, которое всегда содержит
ссылку на активный элемент управления.
При выполнении
команды Cut исходные данные копируются в Clipboard и затем удаляются из
активного элемента: Clipboard.SetText ActiveControl.SelText ActiveControl.SelText =
""
При вызове же команды
Copy данные не удаляются:
Clipboard.SetText
ActiveControl.SelText
Однако активный
элемент управления не всегда содержит данные в текстовом формате, как показано
в приведенных примерах. Поэтому сначала нужно обязательно проверить тип
элемента управления, чтобы решить, какие методы объекта clipboard нужно
вызывать: для обработки текста или для обработки данных в других форматах. Тип
элемента управления определяет выбор допустимых свойств и методов. Если
активным элементом управления является PictureBox, использование свойства SelText
приводит к возникновению ошибки. Подобная проверка возможна с помощью условного
оператора if.. .Then с использованием ключевого слова TypeOf, которое позволяет
установить тип элемента управления.
После проверки типа
активного элемента управления данные в соответствующем формате можно копировать
в буфер обмена:
Private Sub n>nuEditCut_Click()
Clipboard.Clear If TypeOf Screen.ActiveControl Is TextBox Then If
Screen.ActiveControl.SelText
<> "" Then
Clipboard.SetText Screen.ActiveControl.SelText End If Elself TypeOf
Screen.ActiveControl Is PictureBox Then
Clipboard.SetData Screen.ActiveControl.Image, vbCFBitmap
Clipboard.SetData Screen.ActiveControl.Image, vbCFDIB Clipboard.SetData
Screen.ActiveControl.Image, vbCFPalette End If
'При копировании приведенная ниже часть кола
отсутствует If
TypeOf Screen.ActiveControl Is
TextBox Then
Screen.ActiveControl.SelText = "" Elself TypeOf Screen.ActiveControl
Is PictureBox Then
Screen.ActiveControl.Picture LoadPicture() End If End Sub
При вставке данных из
буфера обмена следует также проверять, чтобы элемент управления получал данные
в нужном ему формате:
Private Sub
mnuEditPaste_Click() If TypeOf Screen.ActiveControl Is TextBox Then
Screen.ActiveControl.SelText
= Clipboard.GetText Elself TypeOf
Screen.ActiveControl Is PictureBox Then
Screen.ActiveControl.Picture = Clipboard.GetData End If End Sub
Обычно если какойлибо элемент
управления не может в данный момент выполнить требуемых от него действий, этот
элемент управления должен быть недоступен. Поэтому нужно проверять, какая
команда меню может быть выполнена в данный момент: вырезания и копирования или
вставки. В зависимости от этого соответствующие команды в меню должны быть
доступны или недоступны.
Лучше всего такую проверку выполнять путем
обработки события Click команды меню Edit. Это событие наступает, как
только пользователь откроет соответствующее меню. В процедуре обработки события
можно поместить подпрограмму, определяющую состояние команды меню. Например,
можно проверить, позволяет ли текущее состояние программы выполнить требуемое
действие.
В приведенном примере
выполняются две проверки: содержит ли вообще активный элемент управления
данные, которые можно вырезать или скопировать, и есть ли в буфере обмена
данные нужного формата:
Private Sub mnuEdit_Click
() mnuEditCut.Enabled * False / ; mnuEditCopy.Enabled False mnuEditInsert.Enabled ° False If TypeOf
ActiveControl Is TextBox Then If Clipboard.GetFormat(vbCFText) Then
mnuEditInsert.Enabled » True End If
If
Len(ActiveControl.SelText) > 0 Then
mnuEditCut.Enabled
" True
mnuEditCopy.Enabled °
True End If
Elself TypeOf ActiveControl Is PictureBox Then If
ActiveControl.Picture
<> 0 Then mnuEditCut.Enabled =
True
mnuEditCopy.Enabled = True End If If
Clipboard.GetFormat(vbCFBitmap)
Or
Clipboard.GetFormat(vbCFMetafile)
Then mnuEditInsert.Enabled = True End If End If End Sub
Пример можно
переписать в более компактном виде, учитывая следующую особенность Visual
Basic: значение 0 для данных логических (Boolean) типов всегда считается False,
а все другие значения интерпретируются как True:
Private Sub mnuEdit Click ()
If TypeOf
ActiveControl Is TextBox Then
mnuEditCut.Enabled =
ActiveControl.SelLength mnuEditCopy.Enabled
ActiveControl.SelLength
mnuEditInsert.Enabled =
Clipboard.GetFormat(vbCFText)
Elself TypeOf ActiveControl Is PictureBox Then
mnuEditCut.Enabled =
ActiveControl.Picture mnuEditCopy.Enabled =
ActiveControl.Picture
mnuEditInsert.Enabled =
Clipboard.GetFormat(vbCFBitmap)
_
Or
Clipboard.GetFormat(vbCFMetafile) End If End Sub
В этом примере
вначале проверяется тип активного элемента управления. Если это элемент
TextBox, то возможность копирования и вырезания зависит от того, выделен ли в
поле какойлибо текст. Для этого анализируется свойство SelLength, содержащее
количество выделенных символов. Следует заметить, что анализ как таковой
отсутствует — вместо этого значение свойства прямо присваивается свойству
Enabled. Если ни один символ не выделен, свойство SelLength содержит значение
о, которое интерпретируется как False; любое же ненулевое значение будет
воспринято как True. Возможность вставки данных в текстовое поле определяется
наличием в буфере обмена данных в текстовом формате (vbCFText). Это позволяет
проверить метод GetFormat. Поскольку этот метод возвращает True, если требуемый
формат доступен, возвращаемое значение также присваивается соответствующему
свойству элемента управления.
Аналогично
выполняются установки, если активным элементом управления является PictureBox.
Если PictureBox не содержит никакого изображения, свойство Picture возвращает
значение 0 (False). Если же изображение есть, свойство Picture не равно 0 (т.е.
True).
Трудно решить, какой
из двух вариантов, представленных в примерах, лучше. Первый вариант содержит
больше проверок и поэтому более длинный, но зато более понятен. Второй вариант
компактнее, но его трудно читать, и без комментариев
другим программистам
может быть трудно сразу понять логику присвоении. Тем не менее, оба варианта
имеют право на существование. Нужно только хорошо обосновать, почему выбирается
тот или иной способ.
Поиск ошибок
Проблемы, возникающие
при разработке приложений, работающих с буфером обмена, помогает решить
программа CLIPBRD.EXE. В частности, с ее помощью можно осуществлять поиск
ошибок. Содержимое буфера обмена в этом случае обследуется как бы
"независимым третьим лицом", что позволяет определить причину
возникновения проблемы.
Динамический обмен данными (DDE)
Кроме буфера обмена,
Windows предоставляет и другую возможность обмена данными между приложениями,
называемую динамическим обменом данными (Dynamic Data Exchange, DDE). При таком
обмене выполняется не статический перенос данных, как при использовании объекта
Clipboard, а создается устойчивая связь, с помощью которой данные обновляются
при их изменении в источнике.
Пользователь может
сам создать DDEсвязь. Для этого сначала в исходном приложении следует выделить
нужные данные и скопировать в буфер обмена, а затем вставить эти данные из
буфера в приложениеприемник. В отличие от обычной вставки, в этом случае вместо
команды Paste (Вставить) меню Edit (Правка), необходимо
использовать команду Paste Special (Специальная вставка) с установленной
опцией Paste Link (Связать). В результате в приемник вставляется не
копия данных из приложенияисточника, а ссылка на источник, и в окне приемника
отображаются данные из приложенияисточника.
Буфер обмена
используется при этом только для создания связи, так как установленная DDEсвязь
не зависит от буфера обмена. Программные DDE связи также создаются без
использования объекта Clipboard.
Не все приложения
Windows поддерживают динамический обмен данными. Наличие такой возможности у
приложения можно определить по нескольким признакам. Один из них — присутствие
специальных команд в меню приложения. Например, в редакторе Word,
поддерживающем этот механизм, в меню Edit есть команда Paste Special,
с помощью которой в Wordдокументе можно создать связь с другими объектами
(например, рабочими листами Excel).
Visual Basic
позволяет создавать DDEсвязи как во время выполнения, так и во время разработки
приложения. Создание связи во время проектирования происходит с помощью команды
меню Edit\Past Link. Поскольку организацию связи во время проектирования
берет на себя Visual Basic, мы рассмотрим только создание связи во время
выполнения разрабатываемого приложения.
Первоначально
технология DDE предназначалась только для пользователя — для создания активных
связей между документами. При этом предполагалось, что некоторые важные
предпосылки DDE должны выполняться автоматически. Если связь создается вручную
через буфер обмена, должны выполняться оба приложения (источник и приемник) и
должны быть загружены все используемые документы. Но при программном создании
связи это не обязательно. Чтобы импортировать данные из
Excelтаблицы
в приложение Visual Basic, нужно обеспечить только, чтобы приложение Microsoft
Excel выполнялось и соответствующая таблица была загружена.
Основной задачей
приложенияприемника является создание связи и прием данных. Исходное приложение
только предоставляет эти данные, поэтому разработчика больше интересует
приложениеприемник. Следует учитывать, что информация может передаваться и от
приемника источнику. Поэтому в дальнейшем приемником будет именоваться сторона,
создающая DDEсвязь.
Visual Basic как приемник
При организации
DDEсвязей приложения Visual Basic могут выступать и как источники, и как
приемники. Однако управлять DDE связью разработчик может только в том случае,
если приложение Visual Basic выступает в роли приемника.
Для создания DDEсвязи
необходимо, чтобы выполнялись как приложениеисточник, так и приложениеприемник.
Для создания связи с определенным документом приложенияисточника нужно
загрузить и этот документ.
Свойства DDE
Создание связи с
другими программами в Visual Basic осуществляется путем задания значений
определенным свойствам, управляющим DDE связями. Следует отметить, что не все
элементы управления можно использовать для организации DDEсвязей.
Свойство LinkMode
Свойство LinkMode
определяет вид связи, а также способ обновления (актуализации) данных в
приложенииприемнике.
control.LinkMod* = Значение
В табл. 6.2 приведены
константы и их значения, которые можно присваивать свойству LinkMode.
Таблица 6.2. Имена
констант и значения свойства LinkMode Константа |
Значение |
Описание |
vbLinkNone |
0 |
DDEсвязи нет (по умолчанию) |
vbLinkAutomatic |
1 |
Автоматическое изменение
данных приемника при |
|
|
изменении данных источника |
vbLinkManual |
2 |
Данные изменяются только при
вызове метода |
|
|
Li kR |
vbLinkNotify |
3 |
При изменении данных
генерируется событие LinkNotify, |
|
|
но данные приемника
модифицируются только после |
|
|
вызова метода LinkRequest |
Если значение свойства LinkMode равно vbLinkNone,
DDEсвязь не устанавливается. При всех других значениях, присваиваемых свойству
LinkMode, создается связь с источником. Различие состоит только в способе
обновления данных. При создании автоматической связи (vbLinkAutomatic) данные в
приложенииприемнике обновляются сразу же после их изменения в исходном
приложении. При значении свойства LinkMode, равном vbLinkNotify, данные автоматически
не
передаются, а посылается только сообщение об их
изменении. При ручной связи (vbLinkManual) данные обновляются только при явном
вызове приложением приемником метода LAnkRequest.
Свойство LinkTopic
Для создания связи
необходимо указать источник данных. При этом следует соблюдать следующий
синтаксис идентификации источника данных:
Application I Topic!Item
где Application — это имя программы,
являющейся источником данных. Обычно это имя ЕХЕфайла без расширения. Topic —
это некий объект приложения (например, форма в Visual Basic или таблица в
Microsoft Excel). Item — это конкретный элемент объекта Topi'c (элемент
управления, ячейка таблицы и пр.), который может служить источником информации.
Обратите внимание, что Application и Topic разделяются вертикальнрй чертой, a
Item и Topic — восклицательным знаком. При работе с электронной таблицей
Application — это имя программы обработки электронных таблиц (например, Excel),
Topic — имя файла (например, MAP.XLS), содержащего таблицу, a Item — одна или
несколько ячеек (например, R1C1).
Параметры Application и Topic
можно указать и в свойстве LinkTopic: control.LinkTopic "Appiication|Topic"
Textl.LinkTopic "EXCELI[Map.XLS]Table 1"
Для элементаприемника
изменение свойства LinkTopic приводит к разрыву существующей связи и
прекращению DDEобмена. Поэтому перед изменением свойства LinkTopic сначала
следует установить значение свойства LinkMode рав ным 0 (отключение связи),
затем изменить свойство LinkTopic, а после изменения создать связь заново.
Свойство Linkltem
С помощью свойства
Linkltem задается место внутри документа, которое служит источником данных. Оно
указывается в собственном свойстве, так как его можно изменять без прерывания
DDEсвязи.
control.Linkltem
= "name" Textl.Linkltem = "R1C1"
Препятствия
Обратите внимание,
что при создании связи с ячейкой рабочего листа значение свойства Linkltem
задается в ввде "R1C1". Обозначение вида "А1" использовать
нельзя.
Сложность часто
состоит в получении корректных значений параметров Application, Topic и Item.
Многие программы, поддерживающие DDE, имеют элемент Topic с именем
"System", который содержит элемент Item с именем
"Sysltems". Можно обращаться и к другим элементам Item,
предоставляемым программой в качестве возможных источников данных.
В Visual Basic
создаватьТ^Есвязи можно и во время проектирования с помощью команды Edit\Paste
Link. Но следует помнить, что это возможно только тогда, когда данные в
буфер обмена скопированы из приложения, которое поддерживает DDE и может
служить источником данных. В этом случае свойства LinkTopic и Linkltem
принимают значения, используемые
исходным приложением. Их нужно только считать в окне свойств.
Связи, создаваемые во
время проектирования, не всегда действуют во время выполнения. Это зависит от
того, может ли исходное приложение восстанавливать эти связи при запуске
программы. Связь должна всегда создаваться посредством программного кода, что
обеспечивает ее корректность.
Для создания DDEсвязи
с приложением Visual Basic необходимо выполнить минимум четыре шага:
.
• присвоить свойству LinkMode значение vbLinkNone;
.
• задать в свойстве LinkTopic приложениеисточник (с указанием
конкретногофайла);
.
• с помощью свойства Linkltem указать точную позицию данных;
.
• создать связь, установив требуемое значение свойства LinkMode.Создание
связи с Word для Windows может выглядеть следующим образом:
Textl.LinkMode =
vbLinkNone Textl.LinkTopic = "winwordI new.doc" Textl.Linklteni =
"\doc" Textl.LinkMode = vbLinkAutomatic
В Word для Windows присвоение item значения
"\doc" указывает, что при организации связи используется все
содержимое файла, в данном случае NEW.DOC
Для создания DDEсвязи
во время выполнения приложения опять "вступает в игру" буфер обмена.
Например, в процедуре реализации команды меню создания связи вашего приложения
следует считать информацию исходного приложения из буфера обмена.
Private
Sub mnuInsertLink_Click()
sLinkInfo = Clipboard.GetText(vbCFLink)
iPos = InStr(sLinkInfo, "!")
Textl.LinkMode = vbLinkNode
Textl.LinkTopic = Left(sLinkInfo, iPos 1)
Textl.Linkltem = Mid(sLinkInfo, iPos + 1)
Textl.LinkMode =
vbLinkAutomatic End Sub
В этом примере
считывается информация из буфера обмена. Затем в ней разыскивается позиция
восклицательного знака, разделяющего LinkTopic и Linkltem, и соответствующая
часть информации о связи присваивается свойствам.
Свойство
LinkTimeout
С помощью свойства LinkTimeout задается
промежуток времени (в десятых долях секунды), в течение которого элемент
управления ожидает ответ на запрос DDEданных. Некоторые приложения требуют
больше времени для ответа на запросы DDE. Поэтому если при создании связи
исходное приложение не ответит вовремя, значение этого свойства следует
увеличить (но не более чем до пяти секунд).
Методы
DDE
Метод
LinkRequest
Метод LinkRequest
запрашивает у приложенияисточника данные, необходимые для обновления
содержимого элемента управления. При автоматическом обновлении данных метод
LinkRequest не нужен. Если же при создании DDEсвязи свойству LinkMode было
присвоено значение vbLinkNotify, приложениеисточник посылает приемнику
сообщение об изменении данных. В случае ручной связи приемник не уведомляется
об изменении в источнике, и обновление связи выполняется только по запросу.
Private Sub Form_Load
() Textl.LinkMode = vbLinkNone Textl.LinkTopic = "Excel I system"
Textl.Linkltem =E "sysitems"
Textl.LinkMode vbLinkManual
Textl.LinkRequest End
Sub
При установке связи с
элементом Topic по имени "System" задание значения vbLinkAutomatic
(автоматическая связь) недопустимо, поэтому данные должны запрашиваться явно.
При ручной связи или связи с уведомлением позаботиться об актуализации данных
следует самостоятельно с помощью метода LinkRequest.
Метод
LinkPoke
Через DDEсвязь данные обычно передаются в
одном направлении — от источника к приемнику. Однако с помощью метода LinkPoke
можно передавать данные и от приемника к источнику, благодаря чему
обеспечивается обмен данными в двух направлениях.
Но независимо от
направления связи, сторона, создающая связь, всегда называется приемником.
Private Sub Form_Load
() Textl.LinkMode = vbLinkNone Textl.LinkTopic = "Excel
I[mapl.xls]Лист!" Textl.Linkltem = "R1C1" Textl.LinkMode °
vbLinkManual End Sub
Private Sub
Textl_Change () If Textl.LinkMode > vbLinkNone Then Textl.LinkPoke End Sub
В данном примере в процедуре обработки события
Form_Load создается связь текстового поля с ячейкой рабочего листа Excel, и при
изменении содержимого текстового поля Textl его содержимое передается
источнику. Для того чтобы делать ввод при отсутствии связи DDE, проверяется
значение LinkMode, и только при активной связи выполняется LinkPoke.
При использовании DDEсвязи, в особенности при
использовании метода LinkPoke, нужно следить, чтобы не создавались бесконечные
циклы. Если бы в вышеприведенном примере использовалась автоматическая связь,
то при каждом изменении в TextBox новое содержимое сразу же передавалось бы
источнику посредством
LinkPoke. Но в
результате изменялись бы данные у источника, которые автоматически возвращались
бы приемнику, в котором изменялось бы содержимое TextBox, в результате чего
вызывалось бы событие change и данные опять посылались бы обратно и т.д.
Метод LinkExecute
С помощью метода
LinkExecute приложениюисточнику посылаются не данные, как это происходит при
вызове метода LinkPoke, а команды управления. Чаще всего передаются команды
макроязыка данного приложения.
control.LinkExecute ~
"[command]"
Обратите внимание,
что квадратные скобки в этом случае входят в синтаксис оператора, а не
обозначают, что опцию можно пропустить.
В связи с этим
представляет особый интерес элемент Topic с именем "System" многих
приложений. Благодаря этому элементу можно создавать DDEсвязь без указания
параметра Linkltem. Например, с помощью команд в исходном приложении можно
открыть файл с последующим созданием связи.
Textl.Text =
"с:\kunden\moser.xls" 'Ввод имени файла Textl.LinkMode ~
vbLinkNone Textl.LinkTopic ~ "Excel I system" Textl.LinkMode vbLinkManual an Chr(34) ' Определяет кавычки
Textl.LinkExecute "[open(" & an & Textl.Text & an &
")]"
В этом примере в
Excel открывается файл, имя которого указано в поле TextBox. Синтаксис команд,
которые передаются с помощью LinkExecute, можно найти в документации к
определенному приложению.
События DDE
Из событий DDE для
приложенияприемника следует отметить только событие LinkNotify.
Событие LinkNotify
Событие LinkNotify
происходит, как только в исходном приложении изменяются связанные данные.
Сообщение источника об изменении данных поступает в Visual Basic и
анализируется в соответствующей процедуре:
Private Sub Form_Load ()
Textl.LinkMode =
vbLinkNone
Textl.LinkTopic =
"Excel I[mapl] Лист!"
Textl.Linkltem "R1C1"
Textl.LinkMode
= vbLinkNotify End Sub
Private Sub Textl_LinkNotify()
iReply =
MsgBox("Обновить?", vbYesNo)
If
iReply = vbYes Then Textl.LinkRequest
End
If End Sub
В процедуре Form_Load
создается DDEсвязь между приложением Excel и элементом управления Textl. Если в
исходном приложении данные изменяются, появляется окно сообщений (МеззадеВох),
в котором пользователь может указать, следует ли обновлять данные. Событие
LinkNotify вызывается только при наличии связи с уведомлением (vbLinkNotify)
для соответствующего элемента управления, а не автоматической связи или связи
по запросу.
Событие
LinkError
Событие LinkError наступает при возникновении
ошибки в DDE связи, наприч мер если закрылся источник, в то время как связь
существует, или при попытке создать более 128 связей в приложении. Другие
ошибки, иногда возникающие при создании связи, рассматриваются как обычные
ошибки времени выполнения.
•
Private Sub
Form_Load () On Error Goto appstart
Textl.LinkMode vbLinkNone Textl.LinkTopic "=
appname S "I" & topic
Textl.Linkltem item
Textl.LinkMode = vbLinkAutomatic Exit Sub
appstart:
If Err.Number = 282 Then
ret» = Shell(appname
& ".exe" & " /" & topic, 6) Resume Else
MsqBox Err.Description Stop End If End Sub
В этом примере
предпринимается попытка установить связь с приложением Visual Basic. Если
возникает определенная ошибка выполнения (приложение не запущено), то
запускается требуемое приложение с нужным открытым документом.
DDE
в сети
С помощью папки
обмена (CLIPBRD.EXE) возможна организация DDEсвязей между компьютерами,
объединенными в сеть.
NetDDE
Сначала рассмотрим, как вручную создается
DDEсвязь в сети. Для создания связи в сети, кроме шагов копирования и вставки
данных, следует дополнительно выполнить еще два действия. Если данные источника
находятся в буфере обмена, их можно скопировать в локальную папку исходного
компьютера. Там их необходимо сделать доступными для совместного использования.
В компьютере, на котором выполняется приложениеприемник, создается Связь
локальной папки обмена с общей папкой удаленного компьютера. Оттуда данные
копируются в буфер обмена целевого компьютера, и затем их можно вставлять в
целевое приложение.
Такая связь NetDDE
может создаваться и из Visual Basic. Для этого нужно несколько изменить
синтаксис команды создания связи:
\\server\NDD$|$share.DDE!item
Параметр server
содержит имя компьютераисточника, Share — это имя, под которым данные в папке
обмена на удаленном компьютере открыты для совместного , доступа в сети.
Элемент Item указывается, как в обычной DDE связи.
Textl .LinkMode = vbLinkNone
Textl.LinkTopic = "\\phedon\NDDE$alexandra"
Textl.Linkltem = "\doc"
Textl.LinkMode == vbLinkAutomatic
В этом примере устанавливается связь с
ресурсом по имени alexandra, доступ ным для совместного использования на
компьютере phedon. В качестве Item указывается весь документ Word для Windows,
находящийся в буфере обмена.
В принципе, в NetDDE
можно обойтись и без папки обмена. Но чтобы защитить данные, рекомендуется
предоставлять для совместного доступа только те данные, которые действительно
необходимы другим пользователям.
Внимание
При возникновении проблем, связанных с
NetDDE, в качестве инструмента для проверки можно привлечь приложение WINCHAT.EXE,
которое также использует NetDDE для создания связей. С его помощью можно
проверить, функционирует ли NetDDE или нет.
Visual Basic как
источник
Обычно Visual Basic
выступает в качестве приемника, но может выступать и как приложениеисточник. В
этом случае могут использоваться как свойства формы, так и ее элементы
управления, поддерживающие DDE.
Свойства DDE
LinkMode
Чтобы при организации
DDEсвязи программа Visual Basic могла выступать в качестве источника,
необходимо еще на стадии проектирования присвоить свойству LinkMode формы
значение vbLinkSource. Если при запуске программы свойство LinkMode равно
vbLinkNone, то во время выполнения изменить его значение невозможно. Кроме
того, чтобы форма могла функционировать как источник, при загрузке она должна
зарезервировать дополнительную память, что невозможно выполнить в период
выполнения.
При использовании
формы в качестве источника DDEсвязи также следует соблюдать стандартный
синтаксис, чтобы конечное приложение могло обратиться к требуембму объекту в
исходном приложении Visual Basic.
Application I Topic!Item
Application
обозначает имя ЕХЕфайла без расширения, которое можно задать с помощью свойства
EXEName объекта Арр. Элемент Topic содержит имя, которое указано в свойстве
LinkTopic требуемой формы приложенияисточника, a item — имя соответствующего
элемента управления.
При формировании
строки для создания DDEсвязи недопустимо использовать вместо параметра Topic
строку вида Form. PropertyName. Следует сохранить значение нужного вам свойства
в строковой переменной, а затем объединить ее со значениями элементов
Application и Item.
Имея эту информацию,
можно сформировать строку, необходимую для создания DDEсвязи, а затем просто
скопировать ее в буфер обмена. При необходимости этой информацией могут
воспользоваться другие приложения для создания DDEсвязи с вашим приложением.
S\ib mnuEditCopyO
Clipboard.Clear
Clipboard.SetText
Screen.ActiveControl.Text, vbCFText
Clipboard.SetText
Арр.EXEName & "I" & _ Screen.ActiveForm.LinkTopic &
"!" & _ Screen.ActiveControl.Name , vbCFLink End Sub
В примере в буфер
обмена копируется текстовое содержимое активного элемента управления, а также
строка, необходимая для создания DDEсвязи с этим элементом управления.
Если DDEсвязь
создается между вашим приложением и приложениями, которым известны допустимые
значения элементов Application, Topic и Item, то использовать буфер обмена не
обязательно. Это требуется только в том случае, если вы хотите предоставить
возможность организации DDEсвязи приложению, не имеющему такой информации.
Если значение
свойства LinkTopic формы изменяется во время выполнения, все связи с ней
прерываются и должны создаваться заново,
Методы DDE
Метод LinkSend
Если приложение,
созданное с помощью Visual Basic, выступает в качестве источника DDE,
представляет интерес метод LinkSend, с помощью которого данные передаются
приложениюприемнику. Применение этого метода имеет особое значение для элемента
управления PictureBox, для которого даже при создании автоматической связи
данные автоматически не обновляются. Это сделано с целью предотвращения
передачи больших объемов графической информации посредством DDEсвязи. С помощью
метода LinkSend данные могут отсылаться в пункт назначения в удобное время
(например, после того как графическое изображение будет полностью
сформировано).
События DDE
Если Visual Basic
выступает как источник, большое значение имеют события DDE, рассматриваемые
ниже.
Событие LinkOpen
Событие LinkOpen
наступает, как только с приложением создается DDE связь. Процедуре обработки
этого события передается аргумент Cancel. Если задать значение этого аргумента,
отличное от нуля, процесс создания связи прерывается.
Событие LinkClose
Если DDEсвязь
закрывается (источником или приемником), то происходит событие LinkClose.
Событие LinkExecute
Событие LinkExecute
наступает в приложенииисточнике, если приложение приемник выполняет метод
LinkExecute. Благодаря этому источник может реагировать на полученные команды.
Form_LinkExecute (CmdStr As String, Cancel As
Integer)
Переменная CmdStr содержит
строку команды, переданную методом LinkExecute приемника. С помощью
переменной Cancel можно сообщить приложениюприемнику, что команда
выполнена (Cancel = False) или нет (Cancel = True).
Технология DDE
представляет очень удобную возможность обмена данными между приложениями. Но не
следует забывать, что при этом расходуется как оперативная память, так и
ресурсы процессора.
Заключение
Windows предоставляет
различные средства для организации простого обмена данными между приложениями.
Чаще всего используется буфер обмена Windows. Осуществить доступ к буферу
обмена из приложения Visual Basic можно с помощью методов объекта Clipboard.
Благодаря
динамическому обмену данными, процесс обмена данными между приложениями Windows
можно автоматизировать. Данные не нужно копировать заново для обновления. Они
автоматически передаются через DDE связь, как только происходят изменения в
исходных данных. Приложения Visual Basic при такой связи могут выступать и как
источники, и как приемники.
Следующий уровень развития
обмена данными представляет OLE технология (Object Linking and Embedding —
связывание и внедрение объектов) или ее усовершенствование — технология
ActiveX. Они подробно описываются в главе 8. Некоторые новые приложения больше
не поддерживают технологию DDE в чистом виде, а используют ее только для
внутреннего взаимодействия между OLEобъектами.