Глава 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объектами.

 

Hosted by uCoz