Visual Basic 6. Руководство разработчика

         

Активирование клиента с помощью


VBScript

Web является средой типа клиент/сервер. Нагрузка сбалансирована между сервером, хранящим информацию, и клиентом, ее обрабатывающим. До недавнего времени процедура обработки заключалась в воспроизведении Web-страницы (включая графику) на компьютере клиента. При помощи VBSript можно добавлять маленькие программы на страницы, которые выполняются на сервере. С появ­лением DHTML, языков написания сценариев (VBScript и JavaScript), элементов управления ActiveX для Web большая часть обработки переносится с сервера на компьютер-клиент.

По определению Web-страницы являются интерактивными: при щелчке на гиперссылке пользователю предоставляется другая страница. Этот вид взаимодействия не привычен для пользователей Windows. Кроме того, на каждом шаге он требует обращения к серверу. Web-страница не реагирует на каждое событие, например, нажатие кнопки мыши, поскольку HTML не язык программирования. Он даже не отображает дату и не выполняет простых вычислений.

Последняя тенденция в оформлении Web-страниц — это их активизирование. Активной является страница, которая работает как приложение. Она имеет свой интерфейс пользователя, состоящий из элементов Windows (командных кнопок, полей ввода и элементов управления ActiveX, реализованных для Web), и взаимо­действует с пользователем как обычное Windows приложение. Активной странице не требуется обращение к серверу, чтобы отобразить дату или выполнить вычисления.

Встроенное приложение называется сценарием.

Сценарии - это простые программы, встроенные в HTML-страницу в виде ASCII-текста. Когда загружается страница, вместе с ней загружается сценарий и запускается на выполнение броузером на компьютере клиента. Идея, лежащая в основе активизирования страниц — это использование вычислительной мощности компьютера-клиента. Задача компьюте­ра-клиента - это воспроизведение HTML-документов на экране. Но большинство клиентов имеют мощные PC, способные на большее, чем просто отображать Web-страницы на экране. Активные страницы используют доступную вычисли­тельную мощность для передачи процесса обработки от сервера клиенту.


Далее мы опишем отличия Visual Basic от VBScript. VBScript является упрощенной версией Visual Basic, но прежде, чем начать разработку сценариев, необходимо понять философию оформления VBScript. Среда разработчика также заметно отличается. VBScript не имеет встроенного редактора. Чтобы вставить сценарий на страницу, нужно отредактировать HTML-файл и вставить соответствующий код. После изучения структуры сценария и его взаимодействия с остальным документом мы создадим сценарий конкретной Web-страницы. Также можно оформлять DHTML-документы, при этом VBScript выполняет функции управления элементами в реальном времени.

Исторически (на протяжении трех лет развития VBScript) первым использованием VBScript было программирование элементов Web-страницы для сбора данных, введенных пользователем. Многие страницы в WWW собирают данные, введенные клиентом, с помощью некоторых базовых элементов управления - текстовых полей, переключателей и т.п. Они примитивны по сравнению с элегантными элементами управления Windows, но свою роль выполняют успешно. Чтобы пояснить, как VBScript используется в Web-страницах, рассмотрим эти элементы управления с точки зрения программиста VB и их программирование на VBScript.


Активные и неактивные серверы


Модуль класса является сервером или, другими словами, приложением, которое предоставляет сервис для приложений-клиентов. Когда создается объектная пере­менная для доступа к свойствам и методам класса, фактически происходит запуск исполняемого файла (DLL или ЕХЕ), который выполняется в фоновом режиме и ожидает связи. Каждый раз, когда происходит установка или чтение значения свойства или вызов метода, это приложение активируется, выполняет некоторые действия и, возможно, возвращает в приложение некоторые результаты.

Серверы могут быть реализованы как компоненты ActiveX EXE или ActiveX DLL. Эти две реализации отличаются тем. как созданный сервер работает. Компонент ActiveX DLL - это активный (in-process) сервер. DLL загружается в то же адресное пространство, что и исполняемый файл, вызвавший сервер, и работает "в одной упряжке" с клиентом. Однако в каждый момент времени работает либо приложение-клиент, либо DLL. Достоинством DLL является то, что они работают достаточно бы­стро, так как, в действительности, являются частью приложения, которое их ис­пользует. Компонент ActiveX EXE - это неактивный (out-of-process) сервер, который выполняется как отдельный процесс. Когда приложение-клиент впервые создает объект, предоставляемый ЕХЕ-сервером, сервер начинает выполняться как отдельный процесс. Если другое приложение-клиент создает аналогичный объект, новый объект предоставляется уже работающим экземпляром ЕХЕ-сервера. Другими словами, один ЕХЕ-сервер может обслуживать несколько клиентов. Неактивные серверы являются более эффективными в распределении ресурсов, но обмен информацией между сер­верами — медленный процесс. Скорость работы активных серверов выше.

Примером неактивного сервера является Excel. Можно запустить на выполнение два или более приложения, которые требуют услуг Excel (как показано в последней главе), и все они будут обслуживаться одним экземпляром Excel. Для приложений размера Excel нет смысла в вызове его нового экземпляра каждый раз, когда приложению Visual Basic необходимо вычислить выражение методом Evaluate. Если приложениям VB необходимо иметь доступ к различным рабочим листам, они могут быть открыты с помощью того же экземпляра Excel.



Автоматизация


OLE

OLE Automation (Автоматизация OLE) — это еще один шаг вперед по сравнению со связыванием При выполнении связывания объектов выполняется заимствование функциональных возможностей другого приложения. Используя автоматизацию OLE можно управлять исходным документом непосредственно из вашего приложения. Приложения, которые поддерживают автоматизацию OLE, предоставляют свои объекты другим приложениям. Например, объектом, который предоставляет Word, может быть и предложение, и абзац, и весь документ. Объектом, который может предоставить Excel, может быть макрос, блок ячеек или весь рабочий лист.

Управлять предоставленными объектами из приложения Visual Basic можно с помощью свойств и методов, предоставленных приложением-источником. Важной особенностью Visual Basic является то, что он позволяет обращаться как к объектам приложения сервера OLE, так и к его функциональным возможностям для работы с этими объектами. Преимуществом автоматизации OLE является то, что можно, работая в единой среде, использовать любые OLE-средства, доступные в других приложениях.



Когда компания Microsoft начала разрабатывать автоматизацию OLE, основная идея была проста: создать общий язык и среду программирования, позволяющую использовать средства и возможности ряда основных приложений. В результате был разработан язык Visual Basic for Applications (VBA).

Используя только VBA нельзя разработать требуемое вам приложение, незави­симо от его типа VBA предоставляет в распоряжение разработчика только основные управляющие структуры, математические и строковые функции, а также возмож­ности манипулирования переменными. Реальная эффективность VBA определяется приложениями, поддерживающими его.

С появлением VBA версии 5.0 фирма Microsoft начала продавать лицензии на него тем компаниям разработчикам программного обеспечения, которые хотели добавить к своим продуктам дополнительные средства программирования. Например язык программирования, использовавшийся в пакете AutoCAD компании AutoDesk, был уникален и не мог использоваться другими приложениями. Многие другие изготовители включали в свои программные продукты языки, позволяющие разрабатывать сценарии и прочие средства автоматизации но потребность в некоем глобальном языке который мог бы помочь объединить отдельные части различных приложении была очевидна. В конце концов, фирма Microsoft разработала VBA (версии 5), который соответствовал потребностям других разработчиков. Теперь VBA идет своей дорогой, становясь универсальным языком, позволяющим создавать универсальные приложения для Windows.


Большинство потребителей покупают сегодня готовое программное обеспечение и должны после этого настраивать его. Более половины корпорации в США ис пользуют программы фирмы Microsoft. Многие из них используют VBA, чтобы настроить эти приложения в соответствии с собственными потребностями. Это достаточно устойчивая тенденция. Кроме того, имеется потребность не только в настройке приложении, но и в придании приложениям возможности связываться между собой VBA позволяет выполнять и то и другое. В результате потребность в программистах умеющих использовать VBA, в течение последующих лет увеличится.

Сегодняшние приложения стали настолько мощными и насыщенными разно образными функциями, что больше не имеет смысл разрабатывать приложения на заказ Даже приложения из пакета Office 97 выполняют большинство рутинных компьютерных операций, необходимых для работы типичной корпорации. Важность поддержки VBA можно понять познакомившись с продуктами сторонних производителей в них также предусмотрена поддержка VBA. Давайте начнем знакомство с автоматизацией OLE рассмотрев несколько примеров.


Базовые объекты


Для облегчения разработки Web-приложений активный сервер предоставляет следующие объекты для обеспечения функциональных возможностей, широко используемых в Web-разработках.

Database.

Обеспечивает подключение к базам данных, поддерживающим протокол ODBC или OLE DB, созданный на основе объекта ADO, что позволяет Web-разработчикам без проблем осуществлять подключение баз данных к активной Web-странице.

File Access. Предназначен для доступа к текстовым файлам на сервере. Серверные сценарии, как и клиентские, должны быть безопасными. Объект File Access полностью отвечает этим требованиям, поскольку с его помощью можно получить доступ только к файлам в определенных папках на сервере.

Content Linking.

Предназначен для работы со списком URL, что позволяет обращаться со страницами Web-узла, как со страницами обычной книги. После создания страницы объект Content Linking генерирует таблицу содержимого и навигационных связей с предыдущей и последующей страницами. Используя методы и свойства этого объекта, можно добавлять, удалять и упорядочивать отдельные HTML-файлы.

Browser Capabilities.

Позволяет ASP-файлу распознавать тип и отличительные особенности броузера, приславшего запрос, и динамически настраивать параметры узла. Если возможность распознать тип броузера во время сеанса связи отсутствует, то вам понадобится иметь копии каждой страницы для броузера каждого типа либо оповещать пользователя о том, что он может открыть данную страницу, используя броузер конкретного типа.

Advertisement Rotator.

Позволяет отображать рекламные объявления в соответ­ствии с преопределенными критериями, когда запрашивается ASP-файл. По мере того как все больше людей осознают значение Web, как средства бизнес-медиа, и все больше узлов становятся коммерческими, возрастает потребность в средствах работы с объявлениями в Web. Поэтому Web-менеджерам требуются средства для автоматической замены рекламных объявлений в их страницах в соответствии с запросами пользователей. Для упрощения этого процесса в ASP включен объект Advertisement Rotator.

В этой главе рассмотрены некоторые встроенные и базовые компоненты ASP, позволяющие использовать навыки программирования на Visual Basic в Web-разработках.



Базы данных и системы управления базами данных


Почти все деловые приложения хранят большие объемы данных, организованные в формате, упрощающем их поиск. Системы управления базами данных (СУБД) являются механизмом управления табличными данными с помощью команд высокого уровня. Система управления базами данных скрывает подробности низкоуровневого управления (например, сохранения данных в базе), позволяя программисту концентрироваться на управлении информацией, а не на управлении файлами или поддержании связей между ними.

Visual Basic предоставляет большой набор инструментальных средств для создания и доступа к базам данных как на индивидуальных машинах, так и на сетевых Но два основных из них — это:

•  элемент управления Data и

•   объект Data Access (или DAO — Data Access object).

Элемент управления Data предоставляет доступ к базам данных без какого-либо программирования. Можно установить несколько свойств этого элемента управления и использовать такие средства, как текстовые поля, чтобы отобразить значения полей базы данных. Это бескодовый подход к программированию баз данных, который в полной мере реализован в Visual Basic. Как можно догадаться, этот подход не позволяет добиться большего. Рано или поздно, но наступит необходи­мость писать программу.

Объект Data Access — это структура объектов, предназначенная для доступа к базам данных из кода программы. Все функциональные возможности элемента управления Data доступны программе посредством DAO.

Что такое база данных (database)? В простом понимании, это — сгруппированная, связанная информация, организованная специальным образом для облегчения обработки и поиска (рис. 17.1). Фактически, данные в базе хранятся в таблицах (table), подобных файлам с произвольным доступом. Данные в таблице состоят из столбцов

и строк. Строки содержат однотипную по структуре информацию и напоминают записи файлов с произвольным доступом. Запись — это множество (коллекция) значений, называемых полями.

Рис. 17.1. Графическое представление базы данных и структуры таблиц



Целостность ссылок


База данных NWIND, поставляемая с Visual Basic, предусматривает целостность некоторых отношений. Чтобы увидеть, как это работает, выполните следующие действия.

1. Используя Visual Data Manager, откройте базу данных NWIND и дважды щелкните на таблице Orders (Заказы), содержащей все счета.

2. Выберите счет и запомните ID заказчика, которому выдан счет.

3. Закройте таблицу и дважды щелкните на ее имени таблицы, чтобы открыть ее в режиме ввода данных.

4. Выберите заказчика, ID которого появлялся в счете, и нажмите Delete Механизм JET отобразит сообщение об ошибке (рис. 17.12).

Рис. 17.12. Механизм JET отслеживает целостность отношении

Сообщение об ошибке показывает, что запись, которую пытаются удалить, связана с записями в другой таблице и не может быть удалена.

Если целостность отношений (ссылок) для базы данных важно, то укажите механизму JET следить за его сохранностью. Поддержка целостности ссылок — одна из наиболее важных возможностей системы управления базами данных. Иначе программист следил бы за этим сам, а это — задача не простая.

Хотя можно защитить некоторые ссылки из кода программы, все-таки лучший способ — включить целостность ссылок непосредственно в базу данных. Visual Data Manager для этого не подходит, но можно использовать более совершенные инструменты разработки баз данных, например Microsoft Access, чтобы определить, какие отношения должны быть защищены системой. Эта информация будет сохранена в базе данных

VB6 в действии: проект Data Entry

Построим реальное приложение для ввода данных с возможностями добавления и удаления записей (рис. 17.13). Когда пользователь щелкает на кнопке Add Record, приложение вызывает метод AddNew и обе кнопки одновременно "прячутся". На их месте отображаются обычные кнопки ОК. и Cancel. Можно сохранить новую запись в базе данных, щелкнув на кнопке ОК, или отказаться от сохранения, щелкнув на кнопке Cancel. В любом случае, кнопки ОК и Cancel скроются и снова отобразятся кнопки Add Record (Добавить запись) и Delete Record (Удалить запись).




Рис. 17.13. Приложение Data Entry: ввод данных с помощью элемента Data

Форма приложения Data Entry содержит элемент Data, объект RecordSet которого задает таблицу Titles базы данных BIBLIO. Все элементы управления Textbox связаны с элементом управления Data и отображают поля таблицы Title, ISBN, Description, Subject и Comments.

Каждая запись в таблице Titles имеет ключ, связывающий название книги с фамилией издателя. Вместо использования текстового поля, в котором пользователь мог бы ввести ID издателя, будем использовать элемент управления ComboBox с именами всех издателей. Пользователь может выбрать одного издателя по имени. Этот элемент не является обычным элементом управления ComboBox. Это связанный с данными элемент управления ComboBox, который будет рассмотрен в параграфе "Усовершенствованные элементы управления, связанные с данными" далее в этой главе.

Для построения данного приложения выполните следующие действия.

1. Поместите элемент управления Data на форму и установите в его свойстве DatabaseName (Имя базы данных) путь к базе данных BIBLIO, а в свойстве RecordSource (Источник записей) - таблицу Titles.

2. Разместите на форме пять элементов TextBox (см. рис. 17.13) и свяжите их с элементом Data, имя которого Datal (установлено по умолчанию). Установите в свойстве DataField (Поле) каждого элемента TextBox имя соответствующего поля таблицы.

3. Создайте четыре кнопки Command и установите в их свойствах Name (Имя) и Caption (Надпись) значения, приведенные в табл. 17.9.

Таблица 17.9. Свойства Name и Caption кнопок Command

Caption

Name

Add Record

Delete Record

OK

Cancel

AddBttn (Кнопка добавления)

DelBttn (Кнопка удаления)

OKBttn (Кнопка подтверждения)

Cancel Bttn (Кнопка отмены)

4. Разместите кнопки на форме так, чтобы кнопка ОК совпала с кнопкой Add Record, а кнопка Cancel — с кнопкой Delete.

Теперь можно написать код приложения.

Программа 17.6. Событие Click кнопки Add Record

Private Sub AddBttn_Click()

HideButtons



Data1.Recordset.AddNew

End Sub

Подпрограмма HideButtons прячет кнопки Add Record и Delete Record и отобра­жает две другие. Кнопка Add Record добавляет новую пустую запись в конец набора записей RecordSet и устанавливает элемент управления Data на эту запись. Поль­зователь может ввести новые данные в элементы управления TextBox и, щелкнув на кнопке ОК, записать изменения в базу данных.

Программа 17.7. Событие Click кнопки ОК

Private Sub OKBttn_Click()

On Error GoTo CancelUpdate

Data1.Recordset.Update

ShowButtons

Exit Sub

Cancel-Update:

MsgBox Err.Description

Data1.Recordset.Cancel-Update

ShowButtons

End Sub

Метод Update помещает временную запись в базу данных. Затем подпрограмма ShowButtons скрывает кнопки ОК. и Cancel и отображает две другие.

Предупреждение

Если при изменении базы данных возникает ошибка (вызванная, скорее всего, механизмом JET), то операция должна быть отменена. Поскольку метод Update уже был вызван, то метод Refresh вызывать поздно. Вместо него вызывается метод CancelUpdate (Отменить запись).

Кнопка Cancel удаляет временную запись (отображенную), вызывая метод Refresh, а затем скрывает кнопки ОК и Cancel.

Программа 17.8. Событие Click кнопки Cancel

Private Sub CancelBttn_Click()

Data1.Refresh

Datal.Recordset.FindFirst "Isbn = ' " & prevISBN & " ' "

ShowButtons

End Sub

Если операция добавления отменяется, то происходит возвращение к первой записи таблицы (как при обновлении объекта RecordSet). Чтобы вернуться к по­следней отображенной записи, программа сохраняет значение поля ISBN записи в переменной prevISBN. Это происходит и при нажатии кнопки Add Record. Если пользователь отменяет операцию, то программа находит запись с тем же значением ISBN и снова отображает ее.

Программа 17.9. Событие Click кнопки Delete

Private Sub DelBttn Click()

On Error Resume Next

Datal.Recordset.Delete

If Not Data1.Recordset.EOF Then

Data1.Recordset.MoveNext

Elself Not Data1.Recordset.BOF Then



Data1.Recordset.MovePrevious

Else

MsgBox " This was the last record in the table"

' (Эта запись в таблице была последней)

End If

End Sub

Метод Delete удаляет текущую запись. После операции удаления объект RecordSet не перемещается на другую запись автоматически. Вместо этого он остается на удаленной записи, пока не будет нажата одна из кнопок перемещения. Программа перемещается на следующую запись, если удаленная запись не была последней. В противном случае - перемещается на предыдущую запись. Если уда­ленная запись была единственной в таблице, то программа отобразит сообщение и останется на текущей записи.

Подпрограммы ShowButtons (Показать кнопки) и HideButtons (Спрятать кнопки) манипулируют свойством Visible кнопок. Кроме этого, они отображают и прячут, соответственно, элемент Data, чтобы пользователь мог завершить операцию ввода данных, пользуясь только кнопками ОК или Cancel.

Программа 17.10. Подпрограмма ShowButtons

Sub ShowButtons()

AddBttn Visible = True

DelBttn.Visible =  True

OKBttn.Visible = False

CancelBttn.Visible = False

Data1.Visible = True

End Sub

Если открыть приложение Data Entry, то найдется несколько более интересных подпрограмм. Например, при возникновении события Error элемента управления Data программа отменяет операцию модификации и отображает сообщение об ошибке. Это происходит в том случае, если пользователь, редактируя текущую запись, вводит недопустимую информацию в одно из ее полей.

Программа 17.11. Событие Error элемента Data

Private Sub Datal_Error(DataErr As Integer, Response As Integer)

MsgBox Err Description

Response =  0

Data1.Recordset CancelUpdate

End Sub

При обработке события Validate элемента Data программа выясняет, был ли изменен какой-либо из связанных с данными элементов управления. Если это так, то она запрашивает пользователя, нужно ли сохранить изменения в таблице.

Программа 17.12. Событие Validate

Private Sub Datal_Validate(Action As Integer, Save As Integer)

Dim reply

If txtTitle.DataChanged Or txtISBN.DataChanged Or _

txtDescription.DataChanged Or txtSubject DataChanged _

Or txtComments.DataChanged Then

   reply = MsgBox ("Record has been changed Save?", vbYesNo )

' (Запись была изменена Сохранить? ...)

   If reply = vbNo Then

  Save = False

   End If

End If

End Sub

При обработке события Validate программа, обычно, учитывает значение параметра Action и реагирует согласно действию, вызвавшему ошибку.


Чтение имен процедур


Метод

AddCode элемента управления Script позволяет добавлять к нему несколько процедур. Иногда ему необходим список имен всех процедур. Свойство Procedures является семейством, содержащим все процедуры, добавленные в элемент управления Script. Оно имеет свойство Count,

которое возвращает количество процедур, и свойство /tern, возвращающее, собственно, процедуру. Приведенный ниже цикл сканирует все процедуры в списке.

For i=1 To ScriptControll.Procedures.Count

{обработка элемента ScriptControll.Procedures (i)}

Next

Каждый элемент в семействе Procedures имеет свойство Name, которое соответствует имени процедуры, и свойство HasReturn Value, которое возвращает значение True, если процедура возвращает результат (т.е. является функцией). Кнопка List Procedures на форме SEdit выводит список имен и типов всех процедур в нижний элемент управления TextBox.

Программа 20.10. Список процедур

Private Sub Coinmand2 Click ()

On Error GoTo CodeError

ScriptControll.AddCode Text1.Text

For i=1 To ScriptControll.Procedures.Count

If ScriptControll.Procedures(i).HasReturnValue Then

Text2.Text = Text2.Text & vbCrLf & "Function " _

& ScriptControll.Procedures(i).Name

Else

Text2.Text = Text2.Text & vbCrLf S "Subroutine " _

& ScriptControll.Procedures(i).Name

End If

Next

Exit Sub

CodeError:

MsgBox Err.Description

End Sub

Обратите внимание, как код различает процедуры и функции с помощью свойства

HasReturn Value.

Совет

Хотелось бы, чтобы существовало какое-нибудь свойство, называемое, например, Code, возвращающее текст процедуры. К сожалению, такого свойства не существует. Нет простого способа получить код отдельной процедуры. Более того, отсутствует метод удаления отдельной процедуры. Необходимо удалить все процедуры методом Reset элемента управления Script, а затем добавить их по одной, исключив ненужную. При этом придется сохранить список процедур в отдельном элементе (например, в TextBox). В проекте SEdit для извлечения отдельной процедуры выполняется просмотр содержимого верхнего элемента управления TextBox.



Что такое


OLE?

В прошлом инструментальные средства разработки программного обеспечения были практически одинаковы, и отличались, в основном, способностью обмена информацией с другими инструментальными средствами. Системы программиро­вания можно было рассматривать как острова, изолированные друг от друга. При создании приложений использовались методы структурного программирования.

С появлением OLE в разработке программного обеспечения был осуществлен переход от процедурного к объектно-ориентированному программированию. Это позволило создавать самодостаточные модули или объекты, что значительно упростило программирование, в частности, при разработке крупных приложений. В предыдущих главах рассматривалось использование объектов, встроенных в Visual Basic, для построения приложений. С помощью OLE можно совместно использовать объекты Visual Basic и объекты, принадлежащие другим прикладным программам. Теперь ваши программы — не "острова" в море функциональных возможностей, а органичная часть операционной системы и других прикладных программ.



Что такое активные серверные страницы?


Компания Microsoft разработала несколько методов для создания серверных сценариев разной степени сложности (наиболее простыми являются Database Connector и SQL Web Assistant). Было время, когда многие компании тратили массу денег и сил на разработку средств создания серверных сценариев, и все они при этом не могли служить надежным подспорьем для VB-програмистов или даже Web-разработчиков.

В 1996 г ситуация коренным образом изменилась. Появились активные серверные страницы — элегантное средство, решившее большую часть упомянутых проблем. На самом деле, ASP — это выполняемые на сервере HTML-страницы со встроенным кодом VBScript. Именно поэтому их называют серверными сценариями. Результаты выполнения операторов VBScript (если таковые имеются) передаются на компьютер клиента. HTML-код передается, как он есть. Как следствие, чтобы преобразовать разработанную HTML-страницу в ASP, достаточно изменить расширение ее файла с НТМ на ASP. Немедленных преимуществ это не предоставляет, но теперь можно "оживлять" эти страницы, включая в них сценарии.

Серверные сценарии передают текст и HTML-теги на компьютер клиента, где они воспроизводятся на экране. Из всей выходной информации серверных сценариев только HTML-документы воспроизводятся на экране клиента. Поскольку VBScript обращается к любым объектам, установленным на сервере, при создании сценариев можно использовать элементы ActiveX для реализации любых форм обработки данных, доступа к базам данных и т.п. Сервер, который поддерживает ASP, называется активным сервером (Active Server). В настоящее время существует два сервера, поддерживающих ASP — Internet Information Server и Personal Web Server.

Активный сервер предоставляет несколько встроенных объектов (параграф "Объекты активного сервера"

далее в этой главе). Использование этих объектов упрощает разработку сценариев, так как эти объекты считывают параметры, переданные клиентом, обращаются к базам данных и т.п. Помимо встроенных, можете использовать в сценарии любые другие объекты (с помощью функции Create0bject()). Начнем с разработки нескольких активных серверных страниц, а затем рассмотрим объекты активного сервера.



Цикл жизни элемента управления


Давайте поэкспериментируем немного с событиями кнопок элемента управ­ления. Сделайте следующее.

1. Переключатель в окно UserControl и выполните на нем двойной щелчок, чтобы открыть окно Code.

2. Найдите события Initialize, InitProperties и Terminate в раскрывающемся списке справа. В каждое из них введите оператор Debug. Print с последующим именем события, как показано ниже.

Private Sub UserControl_Initialize()

Debug.Print "initializing control"

End Sub

Private Sub UserControl InitProperties()

Debug.Print "initializing properties"

End Sub

Private Sub UserControl_Terminate()

Debug.Print "terminating control"

End Sub

3. Закройте окно UserControl и возвратитесь к тестовой форме. Поместите экземпляр нового элемента управления на форму, и наблюдайте за окном проверки. Будут отображены следующие сообщения:

initializing control

initializing properties

При помещении элемента управления на форму сначала инициализируется сам элемент, а затем инициализируются его свойства.

Примечание

Операторы Print исполняются при переключении UserControl на тестовую форму. Даже тогда, когда приложение не запускается, код выполняется! Чтобы понять такое поведение, необходимо стать на место конструктора элемента управления ActiveX. Когда на форме размещается обычный элемент управления ActiveX, типа элемента TextBox, то выполняется некоторый код. Это то, что мы только что видели. Элементы управления ActiveX запускаются всегда, независимо от того, принадлежат ли они форме, которая выполняется, или нет. Как же еще проверить изменился ли у элемента управления шрифт или цвет фона, задаваемые разработчиком?

4. Теперь установите свойство Title и выполните тестовое приложение. Два новых сообщения появляются в окне проверки (сначала необходимо очистить текущее содержание окна проверки):

terminating control

initializing control

Элемент управления, который находился на форме в режиме конструирования, был удален, а новый — инициализирован. Все его свойства были инициализированы значениями по умолчанию, а значением по умолчанию для свойства


Title была пустая строка. Именно поэтому он исчез.

Если еще раз остановить приложение, в окне Debug появится следующее сообщение:

initializing control

На сей раз был удален экземпляр элемента управления режима выполнения, а экземпляр режима конструирования - инициализирован. Каждый раз, когда происходит переключение из режима конструирования в режим выполнения, один экземпляр элемента управления удаляется, а новый создается.

В любом случае, при переходе из одного режима в другой свойства элемента должны быть сохранены. Чтобы это сделать, выполните следующее.

1. Переключитесь обратно в окно Code и введите оператор Print в событиях Read Properties и Write Properties.

2. Переключитесь обратно на тестовый проект, установите свойство Title, снова выполните приложение — и вы увидите следующую последовательность сооб­щений:

writing properties

terminating control

initializing control

reading properties

Visual Basic сохраняет значения свойств в окне Properties и удаляет экземпляр элемента режима конструирования. Затем он инициализирует экземпляр режима выполнения и считывает те же самые свойства. Таков цикл жизни элемента управления ActiveX.

Примечание

Если Visual Basic знает, какие значения необходимо сохранить, почему он не может запомнить их, пока создается новый экземпляр элемента управления? Почему Visual Basic сохраняет значения свойств и затем считывает их снова? Казалось бы, сделать это так просто, но обратите внимание на событие Terminate между записью и чтением значений свойств. Между исчезновением одного и появлением другого экземпляра элемент управления просто не существует! При всей кажущейся нелепости ситуации именно так ведут себя элементы управления.

Подведем итоги событий, характеризующих цикл жизни элемента управления. Чтобы выполнить коды этих событий, поместите их в соответствующие обра­ботчики событий

События кнопок в цикле жизни элемента управления

При размещении элемента управления на форме происходят следующие события.

Initialize.



Инициализирует экземпляр элемента управления режима конструи­рования.

InitProperties.

Присваивает начальные значения свойствам.

При переключении из режима конструирования в режим выполнения происходят следующие события.

WriteProperties.

Сохраняет свойства, перечисленные в окне Properties.

Terminate. Удаляет экземпляр элемента управления режима конструирования.

Initialize.

Инициализирует новый экземпляр (режима выполнения) элемента управления.

ReadProperties.

Считывает сохраненные свойства.

При переключении из режима выполнения в режим конструирования происходят следующие события.

Initialize.

Инициализирует экземпляр элемента режима конструирования.

ReadProperties.

Считывает значения из окна Properties и присваивает их соот­ветствующим свойствам.

Совет

При переключении из режима выполнения в режим конструирования ни одно событие WriteProperties не происходит. Как и ожидалось, Visual Basic не сохраняет свойства, которые изменяются во время выполнения, и переустанавливает элемент управления ActiveX в значения набора свойств из окна Properties режима конструирования. Другими словами, изменения свойств элемента управления, произошедшие в режиме конструирования, продолжают действовать в режиме выполнения. Обратное утверждение неверно. Изменения, сделанные во время выполнения, при переключении обратно в режим конструирования сбрасываются.

Для поддержки значений свойств при переключении элемента управления из режима конструирования в режим выполнения необходимо добавить несколько строк кода в события ReadProperties и WriteProperties. Мы уже знаем, как значения свойства записываются и считываются из объекта Property Bag. Поэтому код для свойства Title не вызывает вопросов:

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

Debug.Print "writing properties"

PropBag.WriteProperty "Title", m_Title, "Control Title"

End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

Debug.Print "reading properties"

Title = PropBag.ReadProperty ("Title", "Control Title")

End Sub


Динамические


HTML

Мы знаем, как использовать VBScript для программирования встроенных и пользовательских элементов управления ActiveX на Web-странице. Другое приме­нение VBScript в Web (возможно, более популярное) — это создание DHTML-страниц. Как уже упоминалось, DHTML-документы — это статические HTML-страницы с программируемыми элементами. Например, можно запрограммировать заголовок, чтобы он менял цвет, когда указатель мыши попадает на него, скрывать и отображать текст в зависимости от действий пользователя и т.п. Чтобы сделать элементы HTML программируемыми, необходимо рассмотреть несколько особен­ностей. Об этом и о том, как запрограммировать их с помощью VBScript, расска­зано в следующем параграфе.



Динамический


HTML (DHTML)

Динамический HTML несколько отличается от HTML: он не вводит новых тегов, но делает существующие теги программируемыми. Это позволяет динамически соединять теги со структурой VBScript и управлять видом документов на экране. Например, он поддерживает наслоение, которое позволяет размещать элементы на странице в соответствии с действиями пользователя. Можно помешать изображения друг на друга, оговорив при этом, что изображение под указателем переносится на передний план. Если переместить указатель на другое изображение, то оно, в свою очередь, перенесется на передний план. Можно изменить цвет текстовых элементов (заголовков, ячеек таблицы), если поместить на них указатель.

DHTML может обогатить страницу элементами мультимедиа, такими как спрайты (перемещаемые графические элементы), плавное изменение цвета текста, эффекты модуляции и т. д., без вовлечения сервера. DHTML содержит элементы управления анимацией и мультимедиа. Это используется для создания визуальных эффектов при выборе элементов на странице или целой страницы. Эти элементы управления предлагают фильтры, анимацию и модуляцию — возможности для создания страниц с некоторыми эффектами, используемыми на телевидении. Возможности мультимедиа не являются обязательными, но они вносят в HTML изюминку. Об элементах управления мультимедиа, которые можно использовать в HTML-страницах, в этой главе не рассказано. Дополнительную информацию можно найти по следующему ниже адресу.

http://www.microsоft.com/workshop/с-frame.htm#/workshop/author/

default.asp

Другая особенность DHTML, делающая его подходящим для бизнес-прило­жений — это возможность установления связи с данными. Каждая такая страница содержит невидимый элемент управления ActiveX, связанный с источником данных. Это позволяет создавать формы, содержащие встроенный элемент управления ActiveX, связанный с полями записи. Данные, вводимые пользователем в элемент управления, сохраняются в элементе управления Data Source, который передает данные на сервер под управлением программы.



Динамический список


Чтобы создать список, как в SBXDHTML.HTM, необходимо начать с простого документа HTML. Например, HTML для списка с отобранными названиями Sybex (документ SBXHTML.HTM) приведен ниже.

Программа 19.3. Простой список HTML

<HTML>

<head>

<TITLE>Site Map</TITLE>

</HEAD>

<BODY>

<FONT FACE= "Verdana" SIZE=2>

<CENTER>

<H1>

Popular Titles from SYBEX

</H1>

</CENTER>

<FONT SIZE=3>

<B>DEVELOPERS HANDBOOKS</B><BR>

<FONT SIZE=2>

<UL>

<LI>The NetWare 3.12 Administrator's Handbook (2nd Ed)

<LI>Access and SQL Server Developer's Handbook

<LI>Microsoft Access 2 Developer's Handbook

</UL>

</FONT>

<P>

<FONT SIZE=3>

<B>FAST TRACK</B><BR>

<UL>

<LI>Fast Track to Visual Basic 4

<LI>The ABCs of JavaScript

</UL>

</FONT>

<P>

<FONT SIZE=3>

<B>MASTERING</B><BR>

<UL>

<LI>Mastering Web Design

<LI> Mastering the Internet (2nd Ed)

<LI> Mastering Windows NT Server 4

<LI> Mastering Java

<LI> Mastering Windows 95

</UL>

</FONT>

<P>

<FONT SIZE=3>

<B>NETWORK PRESS</B><BR>

<UL>

<LI>The Encyclopedia of Networking (2nd Ed)

<LI> Introduction to Local Area Networks

<LI> Networking The Small Office

</UL>

</FONT>

</BODY>

</HTML>

Этот пример не содержит весь текст, который можно увидеть в окне броузера, а отображает только структуру списка. Также отсутствуют теги <А>, которые преобразуют каждый заголовок в гиперссылку, указывающую соответствующую книгу на Web-сервере Sybex. Чтобы просмотреть полный список, откройте документ SBXHTML.HTM в текстовом редакторе. Здесь тегом, который соответствует элементу Mastering Web Design (первый заголовок в серии Mastering) является:

<LI TYPE = DISC><A HREF="http://www.sybex.com/cgi-bin/


categor.pl?1911back.html">Mastering Web Design</A>

Как видно из примера, каждая серия состоит из списка элементов. Чтобы отобразить данный список средствами HTML, нужно заключить его в пару тегов <UL> (UL — это аббревиатура для Unsorted List — неупорядоченный список) и перед каждым новым элементом списка вставить тег <LI>. Атрибут TYPE==DISC вызывает появление маленького кружка перед каждым элементом (его можно опустить, если такой вид списка вас не устраивает).

Динамическая версия этого списка (документ SBXDHTML.HTM на компакт-диске) более сложна, но в нем используется та же структура. Каждому активному элементу списка нужно присвоить имя, чтобы на него можно было сослаться в коде. Приведем описание серии Mastering.

<DIV ID= 'Head3'>

<FONT SIZE=3>

<B>MASTERING</B>

<BR>

<FONT SIZE=2>

The books to choose for comprehensive, soup-to-nuts coverage of

virtually any popular program. Mastering titles demonstrate basic

to advanced skills through real-world examples. Included are

some of the best-selling computer books on the market.

</DIV>

Теги <DIV> отмечают начало и конец элемента. Заголовок "Mastering" и следующее определение формируют элемент, поскольку они заключены в пару тегов <DIV>. Атрибут ID тега <DIV> является именем элемента.

Вслед за заголовком "Mastering" (который будет преобразован в активный элемент) следует список названий книг из серии Mastering. Этот список является элементом другого типа. Необходимо обеспечить возможность разворачивания и сжатия этого списка. Определение списка Mastering — это HTML-код, описанный ранее, но заключенный в пару тегов <DIV>. Код списка "Mastering" приведен ниже.

<DIV ID= " " STYLE= "display: none">

<FONT SIZE=2>

<UL>

<LI>Mastering Web Design

<LI>Mastering the Internet (2nd Ed)

<LI>Mastering Windows NT 4

<LI>Mastering Windows 95



</UL>

</FONT>

</DIV>

В этом примере пропущено определение гиперссылок с целью облегчения читабельности. Обратите внимание: этот элемент называется ТОСЗ            и имеет свой стиль. Атрибут

STYLE= "display:none"

предписывает Internet Explorer не отображать элемент. Весь документ будет загружен на компьютер клиента, но не будет отображен из-за установки атрибута STYLE.

Как вы догадались, необходимо добавить код для скрытия и отображения списка, когда пользователь щелкает на активном элементе

Mastering. Раздел Mastering называется Head3. Таким образом, необходимо создать обработчик события, который реагирует на событие onClick объекта Head3.

Sub Head3_onClick()

If ТОСЗ.style.display = " " Then

ТОСЗ.style.display = "none"

Else

ТОСЗ.style.display = " "

End If

End Sub

Этот обработчик события вызывается в случаях, когда пользователь щелкает на активном элементе Mastering. Он анализирует значение атрибута DISPLAY элемента ТОСЗ. Если элемент ТОСЗ видим (значением его атрибута DISPLAY является пустая строка), то код скрывает его, устанавливая значение DISPLAY в "none". Иначе, он отобразит элемент, установив значение его атрибута DISPLAY в пустую строку.

Кроме реагирования на событие щелчка мыши, активные элементы реагируют на ее перемещение. Когда указатель попадает на название серии, то само название и ее описание становятся красными. Когда указатель перемещается на другую серию, выделенная прежде серия становится черной. Каждая серия является отдельным объектом, поэтому все, что необходимо делать — это изменять цвет объекта.

Двумя подпрограммами, которые определяют, когда указатель перемещается в область Head3 и покидает ее, являются функции

Head3_onMouseOver() и Head3_onMouseOut(). Используем эти функции для изменения цвета элемента Head3. Ниже приведен код обработчиков событий.

Sub Head3_noMouseOver()

Head3.style.color = "#FF3300"

End Sub

Sub Head3_noMouseOut()

Head3.style.color = "#000000"



End Sub

DHTML представляет собой не что иное, как программируемый HTML. При создании Web-страницы с помощью DHTML фактически строится HTML-документ, а затем для обеспечения реакции на действия пользователя каждый активный радел заключается в пару тегов <DIV>. Все, что находится между ними, является отдельным элементом, а его атрибутами можно управлять при помощи операторов VBScript.

Чтобы программно управлять элементом, создайте обработчик события для каждого внешнего воздействия, на которое документ должен реагировать. Название обработчика события составляется из имени элемента, который необходимо запрограммировать (значение атрибута ID тега <DIV>) и события, которое он будет обрабатывать.

На этом заканчивается краткое введение в Web и VBScript. Надеемся, теперь вы знаете, как работают HTML и VBScript, и понимаете их роль в Web-разработках. Visual Basic поддерживает новый тип проектов - D HTML-проекты, но без хоро­шего понимания тега <DIV> и использования VBScript для программирования элементов на странице невозможно эффективно использовать визуальные инстру­менты для разработки DHTML-документов.

Быть может, информация, приведенная в этой главе, показалась вам слишком общей, не имеющей практического применения. Это потому, что вы еще не видели по-настоящему хороших VBScript-программ. Вы научились только азам, а приме­нение полученных знаний - еще впереди. В следующей главе вы узнаете, как использовать VBScript для написания сценариев собственных приложений и созда­вать на нем bat-файлы (групповые файлы) для Windows 98 (VBScript является языком написания сценариев для операционных систем). В последней главе речь пойдет об использовании VBScript для разработки приложений сервера, взаимо­действующих с клиентом.

Глава 20. Объекты, используемые в сценариях

• Объект FileSystemObject

• Доступ к папкам и файлам

• Элемент управления Script

• Написание сценариев для Windows

• Объект Shell

В предыдущей главе VBScript использовался для описания Web-страниц, в том числе сценариев, использующих вычислительную мощность компьютера клиента. Сценарии - это простые программы, которые загружаются в текстовом формате и выполняются на компьютере клиента. Сам по себе, VBScript является ядром языка программирования. Самостоятельно он выполняет очень мало. Подлинные возможности сценариев заключаются в том, что VBScript обеспечивает доступ к объектам, предоставляемым броузером. Если проигнорировать объекты, которыми можно управлять с помощью VBScript (такими как <DIV>-тэги или встроенные элементы управления ActiveX), то что останется? Язык, который может создавать переменные, задавать их значения, выполнять основные операции над переменными, вычислять логические выражения и повторять некоторые циклические структуры. Если имеется механизм выполнения этих операций, то можно построить специ­альный язык программирования.



Чтобы создать такой язык и встроить его в приложение, необходим механизм, который интерпретирует и выполняет код VBScript. Добавьте немного объектов со свойствами и методами, и получится новый язык. DHTML и Internet Explorer предоставляют объекты, которые могут использоваться VBScript. Далее в главе показано, как встраивать VBScript в приложения и позволять пользователям программировать приложение.

А как же Visual Basic for Applications? VBA - это мощный язык для программи­рования офисных (и других) приложений, но не язык сценариев. Во-первых, встраивание VBA в приложение не является задачей для среднего VB-программиста. Во-вторых, кроме чисто технических сложностей, VBA — дорогой продукт. Только крупные компании могут позволить себе иметь лицензию на VBA, поэтому отно­сительно небольшое число не Microsoft-приложений используют VBA (например, AutoCAD фирмы Autodesk). С другой стороны, внедрение VBScript в приложение не вызывает особых затруднений, и VBScript свободно распространяется.

Эта технология используется при работе с другими программными продуктами, включая Windows. Например, можно автоматизировать операции Windows 98 с помощью сценариев, которые являются эквивалентами пакетных файлов DOS. Windows 98 содержит Windows Scripting Host (WSH) - систему, которая интерпретирует и выполняет код VBScript, а также предоставляет несколько объектов, необходимых для написания сценария в операционной системе. Одним из объектов WSH является объект Environment (среда), который предоставляет доступ к переменным среды операционной системы. Другой объект WSH - Network (сеть) - открывает доступ к сетевым ресурсам. Эти объекты описаны далее в этой главе. Пока же запомните: язык написания сценариев для Windows 98 - VBScript, а полученные знания применимы и в другой области написания сценариев.

В следующем параграфе рассмотрен очень полезный объект, введенный в VBScript - FileSystemObject. Он обеспечивает доступ к файловой системе хост-компьютера и в Visual Basic отсутствует. Позже мы исследуем элемент управления Script, который позволяет добавлять возможности сценария к VB-приложениям. Да, оказывается можно добавить сценарий к своему собственному приложению с использованием VBScript, и сделать его более гибким. В последнем параграфе этой главы мы узнаем, как использовать VBScript для написания сценариев для Windows.


Динамическое изменение элементов меню


В процессе работы программы можно изменить элементы меню. Эти возмож­ности показаны на примере программы MenuMod (созданной на основе программы MenuBMP).

VB6 в действии: проект MenuMod

Приложение MenuMod позволяет организовать переключение отображения элементов меню либо в виде растрового изображения, либо в виде текста. Меню приложения MenuMod соответствует меню приложения MenuBMP, но, кроме того, добавлен третий пункт Display Graphics (вывести изображение, если элемент меню содержит текст) или Display Text (вывести текст, если элемент меню содержит графику). Обработчик события Click этого пункта меню вызывает функцию DisplayTextMenu()

или DisplayBitmap Мепи(), что позволяет переключаться из одного режима в другой. В процедуре ModifyMenu() для организации замены графики на текст в элементе меню следует использовать флаг MF_STRING, а для обратной замены — флаг MF_BITMAP.

Программа 13.6. Приложение MenuMod

Option Explicit

Private Declare Function GetMenu Lib "user32" _

(ByVal hwnd As Long) As Long

Private    Declare Function GetSubMenu Lib "user32" _

           (ByVal hMenu As Long, ByVal nPos As Long) As Long

Private    Declare Function GetMenuItemID Lib "user32" _

(ByVal hMenu As Long, ByVal nPos As Long) As Long

Private Declare Function ModifyMenu Lib "user32" _

Alias "ModifyMenuA" (ByVal hMenu As Long,

ByVal nPosition As Long, ByVal wFlags As Long, _

ByVal wIDNewItem As Long, ByVal IpString As Any) As Long

Private Declare Function CreateCompatibleDC Lib "gdi32" _

(ByVal hdc As Long) As Long

Private Declare Function CreateCompatibleBitmap Lib "gdi32"_

(ByVal hdc As Long, ByVal nWidth As Long,_

ByVal nHeight As Long) As Long

Private Declare Function Select0b]ect Lib "gdi32"_

(ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function BitBIt Lib "gdi32" _

(ByVal hDestDC As Long, ByVal x As Long, ByVal у As Long, _

ByVal nWidth As Long, ByVal nHeight As Long, _


ByVal hSrcDC As Long, ByVal x Src As Long, _

ByVal уSrc As Long, ByVal dwRop As Long) As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

Const MF_STRING = &HO&

Const SRCCOPY = &HCC0020

Const MF_BYPOSITION - &H400&

Const MFJ3ITMAP - &H4&

Private Sub Exit_Click()

Unload Me

End Sub

Private Sub Form Load()

Call DisplayBitmapMenu

End Sub

Private Sub Graphics_Click()

‘ Отображение текста

If Graphics Checked Then

Graphics Checked  = False

Call DisplayTextMenu

Else

Graphics.Checked = True

Call DisplayBitmapMenu

End If

End Sub

Private Sub MyMenu_Click(Index As Integer)

Me CIs

Me Font Name - MyMenu(Index) Caption

Me CurrentX - (Me ScaleWidth - __

Me.TextWidth(MyMenu(Index).Caption))/2

Me CurrentY = (Me.ScaleHeight   _

Me TextHeight(MyMenu(Index) Caption))/2

Me.Print MyMenu(Index).Caption

End Sub

Private Sub DisplayTextMenu()

Dim hMenuID As Long, menuID As Long

Dim menuPos As Integer

Dim retValue As Long

‘ Получение дескриптора меню

hMenuID = GetSubMenu(GetMenu(Me.hwnd),0)

menuPos = 0

menuID - GetMenuItemID(hMenuID, menuPos)

retValue = ModifyMenu(hMenuID, menuPos, _

MF_BYPOSITION Or MF_STRING, menuID, "Verdana")

menuPos = 1

menuID = GetMenuItemID(hMenuID, menuPos)

retValue - ModifyMenu(hMenuID, menuPos,

  MF_BYPOSITION Or MF_STRING, menuID, "Serif")

menuPos - 2

menuID - GetMenuIteitiID (hMenuID, menuPos)

retValue = ModifyMenu(hMenuID, menuPos, _

MF_BYPOSITION Or MF_STRING, menuID, "Comic Sans")

End Sub

Private Sub DisplayBitmapMenu()

Dim Width As Integer, Height As Integer

Dim hTmpDC As Long, hMenuID As Long

Dim hBitmap As Long

Dim retValue As Long

Dim tmpID As Long

Dim fileName As String

Dim menuPos As Integer, menuID As Long

‘ Установка позиции меню и имени файла

menuPos - О

fileName - Арр Path & "\verdana.bmp"

Picturel Picture - LoadPicture(fileName)



Width   64

Height =16

‘ Получение дескриптора меню

hMenuID=GetSubMenu(GetMenu(Me.hwnd), menuPos)

‘ Создание контекста устройства, предназначенного для хранения

‘ растрового изображения

hTmpDC = CreateCompatibleDC(Picturel hdc)

‘ Создание растрового изображения

hBitmap = CreateCompatibleBitmap(Picturel hdc. Width, Height)

‘ Выбор растрового изображения во временный контекст

tmpID - Select0b;ect(hTmpDC, hBitmap)

‘ Копирование содержимого из элемента управления в контекст

‘ устройства

retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _

Picturel.hdc, О, О, SRCCOPY)

‘ Отмена выбора

tmpID = SelectObject(hTmpDC, tmpID)

‘ Модификация меню

menuID = GetMenuItemID(hMenuID, menuPos)

retValue = ModifyMenu(hMenuID, menuPos, _

    MF_BYPOSITION Or MF_BITMAP, menuID, hBitmap)

‘ Второй пункт меню

menuPos = 1

fileName = App.Path & "\serif.bmp"

Picturel.Picture = LoadPicture(fileName)

‘ Создание растрового изображения для элемента меню

hBitmap = CreateCompatibleBitmap(Picturel.hdc. Width, Height)

‘ Выбор растрового изображения во временный контекст устройства tmpID = SelectObject(hTmpDC, hBitmap)

retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _

Picturel.hdc, 0, 0, SRCCOPY)

tmpID = Select0b;ect(hTmpDC, tmpID)

menuID = GetMenuItemID(hMenuID, menuPos)

retValue = ModifyMenu(hMenuID, menuPos,

MFJ3YPOSITION Or MF_BITMAP, menuID, hBitmap)

‘ Третий пункт меню

menuPos = 2

fileName = App.Path & "\comic.bmp"

Picturel.Picture = LoadPicture(fileName)

‘ Создание растрового изображения для элемента меню

hBitmap = CreateCompatibleBitmap(Picturel.hdc. Width, Height)

‘ Выбор растрового изображения во временный контекст устройства tmpID = SelectObject(hTmpDC, hBitmap)

retValue = BitBIt(hTmpDC, 0, 0, Width, Height, _

Picturel.hdc, 0, 0, SRCCOPY)

tmpID = SelectObject(hTmpDC, tmpID)

menuID = GetMenuItemID(hMenuID, menuPos)

retValue = ModifyMenu(hMenuID, menuPos,

MF_BYPOSITION Or MF_BITMAP, menuID, hBitmap)

‘ Очистка

retValue = DeleteDC(hTmpDC)

End Sub


Добавление свойства


Давайте добавим свойство к нашему прототипу элемента управления. Назовем его Title и сохраним его значение в закрытом свойстве m_Title. Выберите UserControll в окне Project и вставьте следующее объявление в окно Code:

Private m_Title As String

и следующие процедуры

Public Property Get Title () As String

Title = m_Title

End Property

Public Property Let Title(ByVal vNewValue As String)

m_Title = vNewValue

End Property

Закройте окна конструирования UserControl и Code, переключитесь на тестовую форму, выберите новый элемент управления и найдите новое свойство в окне Properties Наличие процедур Let и Get - это все, что необходимо Visual Basic для добавления свойства в элемент управления. Введите новое значение в поле свойства Title (например. Control Title). Как и ожидалось, заголовок не появился на элементе управления.

Чтобы отобразить заголовок, необходимо добавить несколько строк кода. Переключитесь обратно в окно UserControl, выполните на нем двойной щелчок, чтобы открыть окно Code, и в событии Paint введите процедуру.

Private Sub UserControl_Paint()

UserControl.CurrentX = 0

UserControl.CurrentY = 0

UserControl.Print m_Title

End Sub

Совет

Первые два оператора не нужны, если что-либо необходимо отобразить в верхнем левом углу элемента управления, но этим переменным необходимо присвоить соот­ветствующие значения, если что-либо требуется отобразить в другом месте элемента управления.

Переключитесь обратно на тестовую форму. Если, следуя предыдущим указаниям в процессе экспериментов с формой, вы добавили какие-либо элементы управления, удалите их.

Добавьте экземпляр специального элемента управления (если имя объекта User-Control не было изменено, то он будет автоматически назван UserControll), и присвойте значение его свойству Title. Например, My Generic Control. Заголовок не появится в момент ввода, потому что событие Paint не вызывается, когда у свойства изменяется значение. Необходимо изменить размеры элемента управления, чтобы заставить событие Paint отобразить заголовок. Если вас не устраивает шрифт, измените свойство Font (наш элемент управления не имеет свойства Font).


Каждый раз для установки нового свойства вызывается процедура Property Let. Следовательно, для того чтобы заголовок отображался после ввода, необходимо вызы­вать метод Paint из процедуры Property Let. Переключитесь обратно в UserControl и добавьте следующую строку к процедуре Title Property Let.

UserControl_Paint

Окно VB должно иметь вид, как показано на рис. 16.14



Рис. 16.14. Окно VB во время первых шагов конструирования базового прототипа элемента управления

Теперь присвойте значение свойству Title и проследите, чтобы строка появилась на элементе управления. Затем нажмите клавишу F5, чтобы запустить приложение на выполнение. Заголовок не появится на элементе управления. Он был там во время конструирования, но исчез во время выполнения. Можно остановить приложение и поискать значение свойства Title, чтобы удостовериться, что оно все еще содержит установленное значение. Но здесь нас подстерегает неожиданность. Оказывается, что значением свойства Title является пустая строка. Это не является следствием допущенной ошибки. Любой набор свойств режима конструирования теряет свои значения во время выполнения. Это странно, но так работают элементы управления.

Опыт работы с Visual Basic свидетельствует, что любые свойства, установленные в режиме конструирования, сохраняют свои значения во время выполнения. Чтобы это произошло, необходимо сначала сохранить значения свойств в PropertyBag, до чего не так-то просто додуматься. Давайте исследуем цикл жизни элемента управления.


Дополнение


HTML стилями и классами

Основой DHTML являются так называемые стили.

Многие теги HTML распо­знают атрибуты, позволяющие Web-разработчику модифицировать некоторые свойства элементов. Однако их внешний вид, предлагаемый тегами HTML, нельзя модифицировать. Тег <Н1> отображает заголовки первого уровня, но их внешний вид изменить нельзя.

При помощи DHTML можно переопределить почти каждый тег HTML. Например, следующий код является определением стиля, который выделит все заголовки первого уровня голубым цветом, а все заголовки второго уровня — красным.

<STYLE>

H1{color:red}

H2{color:blue}

</STYLE>

Если вставить этот оператор в начало HTML-документа, как правило, в раздел HEAD, то он будет применен ко всем последующим тегам <Н1> и <Н2>.

Одновременно с измененными заголовкам <Н1> и <Н2> можно использовать исходные теги <Н1> и <Н2>. Или два типа заголовков <Н1>, один - красный, а другой - черный. Это становится возможным, если задать классы, чтобы различать пользовательские теги. Класс является новой категорией тегов, определенных автором. Предположим, нужно определить два тега <Н1>, один — для названий, а другой — для резюме. Ниже приведены два определения пользовательских тегов <Н1>.

HI.title {font-weight: bold; background: white; color: black)

HI.summary {font-weight: bold; color: blue)

Чтобы использовать второй заголовок <Н1>, необходимо вставить следующий тег.

<Н1 CLASS =

summary>This is a summary section </H1>

Класс является практически новым тегом, но поскольку он является производным от уже существующего класса, то вместо определения абсолютно нового тега опре­деляются атрибуты существующих тегов. Тег <Н1

class=title> содержит все атрибуты тега <Н1>, кроме заданных в определении класса: ширина шрифта, цвет фона и текста.

Можно использовать классы для приспособления существующих тегов HTML к собственным потребностям. После того как тег вставлен в документ, он уже не может быть изменен. Пока наша страница является статической. Как мы увидим позже, DHTML позволяет переопределить стили, после воспроизведения страницы в окне броузера. Например, можно указать, что цвет свойства тега <Н1> изменится, когда указатель мыши будет находиться на нем или пользователь выполнит другое действие. Броузер распознает действия пользователя и генерирует события для каждого из них. Если предоставить соответствующий обработчик событий, то документ будет реагировать на эти события.



Доработанный элемент управления


TextBox

Элемент управления CTextBox представляет собой специальный элемент управ­ления ActiveX, который расширяет возможности стандартного элемента управления TextBox. Это простой элемент (он наследует все функциональные возможности элемента управления TextBox), однако он оказывается очень полезным при конструировании приложений для ввода данных. Как будет показано далее, доработки совершенно просты и, на самом деле, тривиальны в реализации.

Большинство разработчиков занималось созданием экранов ввода данных, в которых некоторые поля являются обязательными, и, возможно, разрабатывали формы с элементами управления TextBox, окрашенными в тот или иной цвет в зависимости от того, является ли соответствующее поле обязательным, или нет. Или, возможно, использовали событие LostFocus обязательного поля, чтобы задержать фокус в этом поле до тех пор, пока пользователь не введет значение

А как насчет доработанного элемента управления TextBox, который изменяет цвет после того, как значение введено? На рис. 16.18 показана форма ввода данных, использующая такой доработанный элемент управления TextBox. Поля Name (Имя), Last Name (Фамилия) и E-mail (электронный адрес) являются обязательными, а соответствующие элементы управления TextBox первона чально окрашены в красный цвет. Если пользователь перемещает фокус и не вводит значения в эти поля, то они остаются красными. Если же значение в поле введено, то его цвет изменяется на белый. Другая возможность доработанного элемента управления TextBox состоит в том, что он изменяет цвет, когда получает фокус, и, таким образом, пользователь может быстро найти активный элемент управления на форме. Как можно, вероятно, догадаться, используется идея, примененная в формах ввода данных на Web страницах, где для указания обяза тельных полей используется звездочка.

Рис. 16 18 Элемент управления CTextBox расширяет стандартный элемент управления TextBox, добавляя к нему несколько специальных свойств

VB6 в действии: проект CTextBox

Откройте проект CTextBox на компакт диске и запустите его. При первом открытии проекта появляется сообщение об ошибке, указывающее, что элемент управления CTextBox не может быть загружен. Продолжите загрузку проекта, а затем откройте его тестовую форму. Все экземпляры элемента управления CTextBox заменены элементами PictureBox. Удалите элементы управления PictureBox с формы и создайте массив из семи элементов управления CTextBox. Поместите их на форму, как показано на рис. 16.18, выравнивая с соответствующими заголовками и друг с другом. Затем запустите проект, нажав клавишу F5, и проверьте функциональные возможности нового элемента управления.


Спецификация элемента управления CTextBox

Конструирование элемента управления CTextBox довольно просто. Ведь он идентичен стандартному элементу управления TextBox и обеспечивает несколько дополнительных свойств, рассмотренных ниже.

EnterFocusColor.

Когда элемент управления получает фокус, цвет фона устанавли­вается равным этому значению. Если не нужно, чтобы активный в текущий момент элемент управления изменял цвет, установите EnterFocusColor равным белому цвету.

LeaveFocusColor.

Когда элемент управления теряет фокус, цвет фона устанав­ливается равным этому значению (это свойство обычно равно белому цвету для необязательных полей и имеет то же значение, что и MandatoryColor для обяза­тельных полей).

Mandatory. Это свойство указывает, является ли элемент управления обязательным полем, если Mandatory = 1, или необязательным полем, если Mandatory = 0.

MandatoryColor. Это свойство задает цвет фона элемента управления, если его свойство Mandatory = 1 (обязательное поле). MandatoryColor заменяет значение установки LeaveFocusColor. Точнее, если пользователь пропускает обязательное поле, то соответствующий элемент управления окрашивается в MandatoryColor, a не в LeaveFocusColor. Следует обратить внимание на то, что обязательные поля (Mandatory = 1) ведут себя так же, как и необязательные поля после того, как в них было введено значение.

Для изучения использования этих свойства при конструировании формы ввода данных нужно открыть проект CTextBox и поэкспериментировать со значениями специальных свойств, чтобы понять их воздействие на работу элемента. В связи с тем, что элемент управления CTextBox не является стандартным элементом интерфейса Windows, пользователи могут не сразу понять, что означает изменение цвета. Но ни у кого не займет много времени, чтобы приобрести навыки и начать эффективно использовать эту возможность.

Конструирование элемента управления CTextBox

Конструирование элемента управления CTextBox достаточно просто. Чтобы разработать заказной элемент управления, имеющий все компоненты стандартного элемента управления TextBox (кроме свойств, относящихся к установлению связи с данными), используется мастер интерфейса элемента управления ActiveX. Мастер автоматически создаст исходный текст, после чего нужно добавить несколько операторов, которые изменяют цвет фона элемента управления в зависимости от значений свойств и его содержимого.



Создайте новый проект элемента управления ActiveX и, как обычно, добавьте тестовый проект. Назовите компоненты проекта следующим образом.

1. Выберите проект и измените название на ColorTextBox.

2. Выберите объект UserControl и замените имя на CTextBox.

3. Выберите тестовый проект и измените имя на TestProject.

4. Выберите тестовую форму и замените имя на TestForm.

Так как специальный элемент управления есть не что иное, как элемент управления TextBox, следует поместить экземпляр элемента управления TextBox на него. Элемент управления TextBox должен накрыть весь объект UserControl, поэтому нужно ввести следующий ниже код в обработчик события Resize объекта UserControl.

Private Sub UserControl_Resize()

Textl.Move 0, 0, UserControl.Width, UserControl.Height

End Sub

Остальная часть кода пользователя должна использовать свойство Mandatory, поэтому этот код сейчас добавить нельзя. На этом этапе можно запустить мастер интерфейса элемента управления ActiveX, чтобы сгенерировать большую часть кода. Наша цель состоит в том, чтобь! включить все функциональные возможности элемента управления TextBox в наш специальный элемент управления.

В окне Select Interface Members следует переместить следующие компоненты и списка Available Names (Доступные Имена) в список Selected Names (Выбранньи Имена).

Appearance

KeyDown

MouseUp

OLEGiveFeedback

Backcolor

KeyPress

MultiLine

OLESetData

Click

KeyUp

OLECompleteDrag

OLEStartDrag

Change

Max Length

OLEDrag

PasswordChar

DblClick

MouseDown

OLEDragDrop

Refresh

Enabled

Mouselcon

OLEDragMode

Text

Font

MouseMove

OLEDragOver

ToolTip

ForeColor

MousePointer

OLEDropMode

Это базовые части элемента управления TextBox, за исключением свойств, предназначенных для установки связи с данными (DataSource, DataMember и т.д.). При дублировании функциональных возможностей существующего элемента управ­ления в специальном элементе управления нужно удостовериться, что все компонен­ты, которые разработчик ожидает найти в специальном элементе управления, там появились. Свойства для установления связи с данными пропущены потому, что сейчас не планируется использование элементов управления при работе с базами данных (Тема создания элементов управления, связанных с данными, довольно сложна и не раскрывается в этой книге)



После нажатия на кнопку Next отобразится следующее окно Create Custom Interface Members (Создание специальных частей интерфейса). Здесь нужно добавить следующие специальные компоненты.

EnterFocusColor.

Цвет фона элемента управления, когда он получает фокус.

LeaveFocusColor.

Цвет фона элемента управления, когда он теряет фокус.

Mandatory. Если это свойство имеет значение True, цвет фона элемента управления равен значению свойства MandatoryColor, чтобы показать, что элемент управления используется для требуемого поля.

MandatoryColor.

Цвет фона элемента управления, у которого свойство Mandatory равно True.

В следующем окне мастера отображаются все компоненты, за исключением специальных, соответствующих свойствам элемента управления

TextBoxl. Ни один из компонентов элемента управления CTextBox не отображается на объект UserControl просто потому, что TextBox полностью включает в себя весь объект UserControl.

В следующем окне Set Attributes задайте значения специальных свойств. Введите атрибуты, показанные в табл. 16.4, в соответствующие поля окна Set Attributes мастера.

Таблица 16.4. Значения специальных свойств

Свойство

Тип данных

Значение по умолчанию

В режиме выполнения

В режиме конструирования

EnterFocusColor LeaveFocusColor Mandatory MandatoryColor

OLECOLOR OLECOLOR Boolean OLECOLOR

&HOOFFFF &HFFFFFF False &HFFOOOO

Чтение/Запись Чтение/Запись Чтение/Запись Чтение/Запись

Чтение/Запись Чтение/Запись Чтение/Запись Чтение/Запись

В том же окне можно также ввести описание каждого свойства, которое появ­ляется в окне Properties, когда выбрано соответствующее свойство. После щелчка мышью на кнопке Next, а затем на кнопке Finish будет сгенерирован код элемента управления.

Теперь можно открыть окно Code объекта UserControl и просмотреть код, сгенерированный мастером. Следующие переменные и начальные значения распо­ложены в верхней части окна Code:

' Значения свойств, устанавливаемые по умолчанию:

Const m_def_Mandatory =



False

Const m_def_EnterFocusColor = &HFFOOFF

Const m_def_MandatoryColor = &HFF

Const m_def_LeaveFocusColor = &HFFFFFF

' Переменные свойств:

Dim m_Mandatory As Boolean

Dim m_EnterFocusColor As Variant

Dim m_MandatoryColor As OLE_COLOR

Dim m_LeaveFocusColor As OLE_COLOR

Эти объявления переменных и констант соответствуют свойствам, которые были заданы в окнах мастера. Все стандартные элементы уже реализованы, и их не нужно изменять, кроме процедур свойства Appearance. Мастер реализует это свойство как Integer, но использование перечислимого типа более предпочтительно для свойств, имеющих ограниченное число значений. Поэтому добавьте следующее объявление типа:

Enum Flat3D

Flat

[3D]

End Enum

и затем измените процедуры свойства следующим образом.

Программа 16.17. Модифицированные процедуры свойства Appearance

Public Property Get Appearance() As Flat3D

Appearance = Text1.Appearance

End Property

Public Property Let Appearance(ByVal New Appearance As Flat3D)

Text1.Appearance() = New Appearance

PropertyChanged "Appearance"

End Property

Нужно также изменить код процедуры Property Let для свойства MandatoryColor. Это свойство может быть установлено только в случае, если свойство Mandatory элемента управления равно True. Если оно равно False, то пользователь должен сначала изменить его, а затем задать свойство MandatoryColor.

Программа 16.18. Модифицированные процедуры свойства MandatoryColor

Public Property Let MandatoryColor(ByVal New_MandatoryColor As _

OLE_COLOR)

m_MandatoryColor = New_MandatoryColor

If m_Mandatory Then Text1.Backcolor = New_MandatoryColor

PropertyChanged "MandatoryColor"

End Property

Свойство Mandatory имеет тип Integer. Можно ввести любые целочисленные значения в его поле в окне Property. Определим следующий перечислимый тип:

Enum ReqOpt

[Optional]

Required

End Enum

Следует обратить внимание, что значение Optional должно быть заключено в квадратные скобки, так как оно является ключевым словом Visual Basic. Измените процедуры свойства Mandatory следующим образом.



Программа 16.19. Модифицированные процедуры свойства Mandatory

Public Property Get Mandatory() As ReqOpt

Mandatory = m_Mandatory

End Property

Public Property Let Mandatory(ByVal New_Mandatory As ReqOpt)

m_Mandatory = New Mandatory

If m Mandatory = Required Then

Text1.Backcolor = m_MandatoryColor

Else

Text1.Backcolor = m_def_LeaveFocusColor

End If

PropertyChanged "Mandatory"

End Property

Когда свойство Mandatory установлено в True, элемент управления автоматически устанавливает свойство цвета фона равным значению свойства MandatoryValue.

Тем самым обеспечивается тривиальный код, необходимый для правильного функционирования элемента управления. Теперь можно добавить специальный код, чтобы расширить возможности элемента управления

TextBox. Код, расширяющий возможности элемента управления TextBox, расположен в событии LostFocus объекта UserControl. Когда пользователь убирает фокус с элемента управления CTextBox, код проверяет содержимое элемента управления и свойство Mandatory. Если элемент управления пуст и свойство Mandatory равно True, то цвет фона элемента управления TextBox устанавливается равным значению свойства MandatoryColor.

Программа 16.20. Обработчик события LostFocus объекта UserControl

Private Sub Textl_LostFocus ()

If Len(Trim(Textl.Text)) = 0 And m_Mandatory = Required Then

Text1.BackColor = m_MandatoryColor

Else

           Text1.BackColor = LeaveFocusColor

End  If

End Sub

Примечание

Обратите внимание, что код не инициирует событие

LostFocus. Хотя поведение элемента управления, когда он теряет фокус, определяется кодом, все же можно еще написать обработчик события LostFocus. Можно

использовать событие LostFocus, потому что это событие не может быть вызвано непосредственно самим элементом управления. Оно вызывается контейнером элемента управления (т.е. формой), и нельзя инициировать это событие из кода элемента управления. Таким образом, если даже в коде элемента управления отсутствует оператор RaiseEvent LostFocus (), обработчик события LostFocus все же можно запрограммировать. То же верно и для события GotFocus, которое также вызывается контейнером, а не элементом управления.



Элемент управления CTextBox имеет иную возможность: когда его активизи­руют, он изменяет цвет фона на значение свойства EnterFocusColor.

Private Sub Textl_GotFocus()

Text1.Backcolor = EnterFocusColor

End Sub

Если такое поведение вас не устраивает, то просто нужно присвоить свойству EnterFocusColor значение цвета фона элемента управления.

При конструировании элементов управления ActiveX используются как прие­мы разработки стандартных VB-приложений, так и приемы разработки компонентов ActiveX. Их свойства, методы и события обрабатываются точно так же, как и их дубликаты в компонентах ActiveX, а именно:

• свойства — это закрытые переменные, которые можно считывать или устанав­ливать через процедуры property;

• методы — это общедоступные подпрограммы;

•  события могут быть инициированы из любого места в коде элемента управления ActiveX с помощью метода RaiseEvent.

Видимый интерфейс элемента управления отображается на объекте UserControl, который подобен форме. Он поддерживает почти все свойства и методы формы, включая методы рисования. Отсутствуют какие-либо средства для загрузки и выгрузки UserControls, какие есть для форм, однако можно сделать элемент управ­ления видимым или невидимым на этапе выполнения с помощью команд про­граммного кода.

Код элемента управления сосредоточен в его ключевых событиях, таких как события Paint и Resize, и нет никакого отличия от кода, используемого при конст­руировании обычных приложений с подобными функциональными возможностями.

Ответственность за интеграцию элемента управления ActiveX в среду разработки лежит на Visual Basic. Свойства, добавляемые к элементу управления, автоматически отображаются в окне Properties, а синтаксис методов отображается по мере ввода кода (они включены в средство AutoList Members из Visual Basic). Процесс конструирования элемента управления ActiveX поразительно похож на процесс разработки стандарт­ного приложения VB. Но в результате появляется "новое существо, которое может жить" в различных средах, включая Web-страницы, что будет показано в последней части этой книги.



Часть V. Программирование баз данных на Visual Basic

Глава 17. Программирование баз данных на Visual Basic

Глава 18. Элементы управления Active Data Object

Глава 17. Программирование баз данных на Visual Basic

• Базы данных и системы управления базами данных

• Концепция реляционных связей

• Использование Visual Data Manager

• Структура базы данных BIBLIO

• Проверка корректности данных

• Ввод данных

• Доступ к полям в наборах записей (RecordSet)

• Введение в SQL

• Использование усовершенствованных элементов управления, связанных с данными

• Отображение баз данных

Тема, которая слишком велика, чтобы поместиться в одной главе — это программирование баз данных. Эта глава озаглавлена именно так, но на самом деле является лишь введением в основные понятия программирования баз данных на Visual Basic. Она предназначена для тех, кто намерен создавать небольшие базы данных и уже знаком с другими системами управления базами данных, например, с системой dBase. Тем, кто знаком с программированием баз данных в других средах, информация, приведенная в этой главе, поможет освоиться в программи­ровании баз данных на Visual Basic.

Примечание

В приложениях этой главы используются примеры баз данных BIBLIO и NWIND, которые входят в версию Professional Edition of Visual Basic. Имена баз данных жестко заданы во многих примерах. В частности, поиск баз данных осуществляется в заданной по умолчанию папке, создаваемой во время установки. Если Visual Basic установлен в другой папке, то необходимо изменить путь к базе данных, чтобы он соответствовал расположению базы в системе. Для этого необходимо изменить свойство DatabaseName в элементе управления Data (если приложение использует Data) или путь к базе данных в методе OpenDatabaseQ в исходном тексте программы (если приложение открывает базу данных непосредственно). Так как нельзя изменить эти установки в программах на CD, сначала скопируйте примеры приложений в папку на жестком диске, после чего их можно будет запускать и/или изменять.


Доработка существующих элементов управления


Имеется возможность разрабатывать пользовательские элементы управления ActiveX, которые расширяют возможности существующих элементов управления. Вряд ли найдется хоть один пользователь, который не хотел бы добавить "новые" возможности к существующим элементам управления. Многие программисты добавляют новые возможности к стандартным элементам управления ActiveX с помощью соответствующего кода в их приложении. Например, недостатком элемента управления ComboBoxt является то, что любые новые значения, добав­ляемые в поле ввода, не добавляются в список значений. Другими словами, элемент управления ComboBox позволяет ввести новое значение, но это значение автоматически не добавляется к списку значений. Многие программисты пере­хватывают нажатие клавиши ENTER в элементе управления ComboBox и вручную добавляют новые значения в список элемента управления.

Уверен, что каждый программист хотел бы добавить свое собственное небольшое усовершенствование к стандартному элементу управления VB. В этом разделе рассматривается, как доработать существующие элементы управления ActiveX и оформить их в виде заказных (специальных) элементов управления. Очевидно, что нельзя изменить базовые функции существующего элемента управления, поскольку нет никакого доступа к их коду. Но можно сделать очень многое, добавляя некоторый код и оформляя существующий элемент управления вместе с добавленным кодом как новый элемент управления.

В этом разделе будет показано, как можно доработать элемент управления TextBox. Заказной элемент управления CTextBox представляет собой обычный элемент TextBox, который изменяет свое поведение в зависимости от того, принимает ли он обязательное или необязательное поле.

На компакт-диске, в папке этой главы, можно найти проект CLDesign, который демонстрирует, как в режиме конструирования можно добавить к элементу управления дополнительные возможности для режима выполнения. Вы когда-либо пробовали задать значение элемента управления Scrollbar в режиме конструирования, двигая его бегунок? Большинство пробовали это, и результатом было переме­щение всего элемента управления на форме. Значение элемента управления ScrollBar не может быть установлено визуально в режиме конструирования. Интересное расширение элемента управления ScrollBar может обеспечить механизм, который позволит разработчику определять, должен ли элемент управления перемещаться или должен функционировать так, как и во время выполнения, даже в том случае, если он находится в режиме конструирования. Проект CLDesign достаточно прост, и поэтому не будет обсуждаться в этой главе. Все то, что нужно знать для того, чтобы заставить элемент управления вести себя в режиме конструирования так же, как и в режиме выполнения - это свойство EditAtDesignTime объекта UserControl. Если установить это свойство равным True, команда будет добавлена к контекстному меню. Выполните щелчок правой кнопкой на элементе управления тестовой формы и выберите команду Edit. Элемент управления будет вести себя так, как будто он находится в режиме выполнения. Например, если он содержит элемент управления Scrollbar, то можно изменить значение элемента управления с помощью мыши. Элемент управления CLDesign, показанный на форме, изображенной на рис. 16.17, позволяет разработчику выби­рать начальный цвет в режиме конструирования с помощью трех полос прокрутки.

Рис. 16.17. Проект CLDesign в режиме конструирования приложения ведет себя так же, как и в режиме выполнения



Доступ к информации о системе


API-функции, описываемые в этом разделе, позволяют организовать просмотр других выполняющихся программ непосредственно из VB-приложения и получить не только информацию о приложении, но и его родительском окне.



Доступ к папкам и файлам


В предыдущем параграфе рассмотрены методы объекта

FileSystemObject, которые позволяют обращаться к файлам на локальном диске. Объект FileSystemObject поддерживает много других методов для операций с файлами и папками, (позволяющими копировать и удалять файлы и папки), которые более интересны для программиста на VB, чем методы доступа к текстовым файлам. Хотя в Visual Basic имеются операторы и функции для доступа к файловой системе, но объект FileSystemObject предоставляет целостный, иерархический подход к файловой системе, поэтому рекомендуется использовать именно его.

Примечание

Только объект FileSystemObject позволяет обратиться к файловой системе из сценария.

CopyFile. Копирует один или более файлов из одной папки в другую. Он имеет следующий синтаксис.

FSys.CopyFile source, destination, overwrite

Аргумент

source - путь к файлу-источнику. Он может содержать и символы шаблона (для копирования нескольких файлов). Аргумент destination - путь к папке-приемнику, в которую копируются файлы. Он, что естественно, не может содержать символы шаблона. Последний аргумент — overwrite — необязателен и принимает булево значение (True/False) и определяет, будет ли существующий файл переза­писан. Метод CopyFile генерирует ошибку выполнения, если у файла-приемника установлен атрибут "только для чтения" независимо от значения аргумента overwrite. Свойство Attributes рассмотрено в примере обновления файла с установленным атрибутом "только для чтения".

CopyFolder.

Копирует папку, включая подпапки (это называется рекурсивным копированием). Синтаксис метода CopyFolder приведен ниже.

FSys.CopyFolder source, destination, overwrite

Здесь

source - путь к папке-источнику (из которой копируются файлы), может содержать символы шаблона при копировании группы файлов. Destination — путь к папке-приемнику (в которую копируются файлы) — не может содержать символы задания шаблона. Последний аргумент overwrite - необязателен и его значение (True/False) определяет, можно ли существующие файлы в папке переза­писывать. Чтобы защитить уже существующие файлы в папке-приемнике, установите его в False.


Для копирования всех Doc-файлов из папки MyDocuments в папку WorkDocs\Feb-ruary используйте оператор

FSys.CopyFolder "С:\MyDocuments\*.DOC", "С:\WorkDocs\February"

где

FSys - должным образом объявленная переменная FileSystemObject.

Предупреждение

Если встречается ошибка, то метод CopyFolder прерывает свою работу. Это значит, что некоторые файлы будут скопированы, а некоторые — нет.

DeleteFile. Удаляет один или несколько файлов. Имеет следующий синтаксис.

FSys.DeleteFile filespec, force

Здесь

filespec - имя файла (файлов) для удаления, которое может содержать символы шаблона. Аргумент force необязателен. Он определяет, будут ли удаляться (True) файлы с атрибутом "только для чтения", или нет (False). Подобно методу CopyFile, при обнаружении первой ошибки он останавливается.

DeleteFolder.

Удаляет заданную папку и ее содержимое, включая подпапки и их файлы. Его синтаксис идентичен DeleteFile.

FSys.DeleteFolder folderspec, force

Здесь

folderspec — имя папки для удаления. Папка будет удалена и в том случае, даже если она содержит файлы (сравните с командой RMDIR в DOS). Аргумент force имеет то же значение, что и в DeleteFile.

Movefile. Метод перемещает один или несколько файлов из одной папки в другую. Его синтаксис следующий.

FSys.MoveFile source, destination

Здесь

source - путь к перемещаемым файлам, a destination —

путь к папке, в которую будут перемещены файлы. Метод работает аналогично методу Сору, но файлы-источники после копирования удаляются. Аргумент source может содержать символы шаблона для перемещения групп файлов, destination — это имя файла или имя папки (в случае перемещения в определенную папку). Если копируется несколько файлов, то destination -

это путь к папке, в которую перемещаются файлы. Если destination задает уже существующее имя файла или папки, то происходит ошибка.

MoveFolder. Этот метод перемещает папку в другое место. Его синтаксис:

FSys.MoveFolder source, destination

где

source и destination - спецификации папки-источника и папки-приемника.



FileExist, FolderExists.

Эти методы возвращают значение True, если указанный файл или папка существует. Используются для проверки наличия папки или файла перед попыткой их использования в сценарии. Их синтаксис следующий.

FSys.FileExists(fileSpec)

и

FSys.FolderExists(folderSpec)

GetFile, GetFolder.

Эти методы возвращают соответственно объект File и Folder, которые представляют заданный файл или папку.

Примечание

Метод GetFile не возвращает файл или имя файла: он возвращает ссылку, обеспечи­вающую доступ к свойствам файла. Объекты File и Folder рассмотрены далее в этой главе.

Чтобы с помощью метода GetFile создать объектную переменную типа File, необходимо создать объектную переменную типа FileSystemObject, а затем вызвать ее метод GetFile.

Set thisFile = FSys.GetFile ("с:\autoexec.bat")

Переменная

thisFile представляет файл AUTOEXEC.BAT, и можно использовать ее свойства и методы для манипулирования файлом. Например, можно использовать ее свойство Size для определения размера файла, свойство DataCreated для определения даты создания и т.д. Свойства и методы объекта File приведены в параграфе "Объект File".

Метод GetFolder полностью аналогичен GetFile, за исключением того, что он возвращает объект Folder. Аргумент метода GetFolder должен быть абсолютным или относительным путем:

Set thisFolder = FSys.GetFolder("с:\windows\desktop")

Здесь переменная thisFolder

представляет Рабочий стол. Ее свойства и методы можно использовать для управления папками Рабочего стола. Свойство Size можно использовать для определения размера папки (включая подпапки), свой­ство DateCreated — для определения даты создания папки и т.д. Методы и свойства объекта Folder рассмотрены далее в этой главе.

GetFileName. Этот метод возвращает последний компонент заданного пути, который является именем файла с расширением. Для получения имени файла метод обычно вызывается с объектом типа File в качестве аргумента. Без метода GetFileName пришлось бы разрабатывать специальную функцию для выделения имени файла из полной спецификации пути.

Примечание

Метод GetFileName обрабатывает свой аргумент независимо от того, существует ли заданный путь.


Доступ к полям в объектах


RecordSet

Связанные с данными элементы управления могут отображать поля текущей записи в объекте RecordSet элемента управления Data, но необходимо также обра­щаться к значениям полей из кода программ. К полям можно обращаться через объект Field набора записей RecordSet. Следующее выражение задает поля (столбцы) набора записей RecordSet.

recordset.Fields

Переменная recordset представляет собой объект RecordSet (это может быть свойство RecordSet элемента Data, например, Data I. RecordSet или переменная с именем RecordSet).

Обращайтесь к отдельным полям по имени поля или его порядковому номеру в таблице Если элемент управления Data с именем Datal связан с таблицей Titles базы данных BIBLIO, то можно обращаться к полю Title текущей записи с помощью любого из следующих операторов.

bookTitle = Datal.Recordset.Fields(0)

bookTitle = Datal.Recordset.Fields ("Title")

Другие два свойства, представляющие интерес - это свойство RecordCount объекта RecordSet (возвращает число записей в RecordSet) и свойство Count объекта Fields (возвращает число полей в строке RecordSet). Эти два свойства фактически являются размерами объекта RecordSet.. Число записей в RecordSet элемента Datal определяет строка

Datal.RecordSet.RecordCount

а число столбцов в этом же RecordSet — следующая строка:

Datal.RecordSet.Fields.Count

VB6 в действии: просмотр RecordSet

Разработаем небольшое приложение, демонстрирующее, как можно просматривать записи в наборе RecordSet и обрабатывать их поля. Обработка довольно триви­альна: помещение строк объекта RecordSet в элемент управления ListBox. Программа демонстрирует, как просматривать RecordSet и извлекать конкретные поля.

Чтобы создать это приложение, выполните следующие действия.

1. Откройте новый проект и поместите элементы управления ListBox и Data на форму (рис. 17.14).

2. Установите свойство Visible элемента управления Data в False. Нельзя исполь­зовать элемент управления Data для перемещения по RecordSet после того, как все записи отображены в элементе управления ListBox.


3. Установите свойства DatabaseName и RecordSource элемента управления Data на любую таблицу базы данных BIBLIO или NWIND.



Рис. 17.14. Приложение загружает поля RecordSet в элемент управления ListBox

4. Теперь введите следующий код в событие Load формы.

Private Sub Form_Load()

Dim i As Integer

Data1.Refresh

Data1.Recordset.MoveLast

Data1.Recordset.MoveFirst

For i = 1 To Data1.Recordset.RecordCount

List1.AddItem Data1.Recordset.Fields(1)

Data1.Recordset.MoveNext

Next

End Sub

Совет

При запуске этого приложения элемент управления ListBox заполняется значениями из второго поля таблицы. Этот код предназначен для использования в больших приложениях. В параграфе " Усовершенствованные элементы управления, связанные с данными" рассмотрен связанный с данными элемент управления ListBox, заполняю­щийся автоматически. Метод Refresh вызывается перед использованием свойств элемента управления Data и заставляет элемент управления Data читать RecordSet из базы данных. Когда объект RecordSet только создан или обновлен, ему не известно, сколько в нем записей. Несомненным является наличие только одной записи — первой. Если пользователь щелкает на кнопке Next, то RecordSet считает, что содержит две записи, потому другие еще не видны. Чтобы узнать общее количество записей, необходимо перейти на последнюю запись с помощью метода MoveLast. После вызова этого метода для определения числа строк в RecordSet используется свойство RecordCount.

Seek. Можно немедленно найти запись в таблице на основании значения индексного поля с помощью метода Seek объекта RecordSet. Этот метод чрезвычайно быстр, потому что использует индекс таблицы и ищет записи в отсортированном списке. Метод имеет следующий синтаксис.

Seek operator, key

     Параметр

operator- одна из следующих операций сравнения:

•   = (равно)

•   > (больше чем)

•   < (меньше чем)

•   >= (больше или равно)

•   <= (меньше или равно)

Параметр

key (ключ) - значение, сравниваемое с ключевым полем индекса. Если индекс создан на основе одного поля, то key —



одиночное значение, если на основе нескольких полей, то параметр key содержит несколько значений, разделен­ных запятыми.

Например, если таблица Customers проиндексирована по полю State (Штат), то следующий вызов позволяет найти первого заказчика в Калифорнии.

Datal.Recordset.Seek "=" , "СА"

Метод Seek быстрее, чем метод Find, но менее гибкий. Если приходится часто производить поиск записей на основании значения определенного поля, то необхо­димо по этому полю создать индекс и использовать метод Seek. Для выполнения поиска всех типов, включающих несколько полей и оператор LIKE, можно использовать метод Find, но он выполняется не так быстро, как метод Seek.

VB6 в действии: проект ManyTbIs

Приложение ManyTbIs (проект с несколькими таблицами) демонстрирует использование метода Seek для быстрого поиска записей с помощью первичных ключей (рис. 17.15). Это приложение объединяет все таблицы в базе данных BIBLIO, чтобы отобразить названия книг вместе с именами авторов, издателей и сопутст­вующей информацией (комментарии и описания).



Рис. 17.15. Приложение ManyTbIs: названия всех книг, имена авторов и издателей содержатся в различных таблицах базе данных BIBLIO

Примечание

Читатели, которые уже знакомы с SQL, поймут, что это приложение может быть реализовано без использования метода Seek. По сути, можно написать единственную строку кода, содержащую SQL-запрос. Этот пример предназначен только для демонст­рации использования метода Seek. Далее в этой главе приложение ManyTbIs будет модифицировано, и вы увидите, как его реализовать с помощью одного SQL-запроса.

При перемещении по названиям книг (с помощью соответствующих кнопок элемента управления Data таблицы Titles) программа отображает соответствующий заголовок книги в первом текстовом поле формы и поля Comments и Subject в со­ответствующих им текстовых полях. Эти текстовые поля непосредственно связаны с элементом управления Data формы.

Чтобы отображать сведения об издателе, приложение использует поле PubID (ID издателя) таблицы Titles, как ключ к таблице Publishers (Издатели), в которой оно находит (с помощью метода Seek) запись с таким же значением PubID.



Для отображения имени автора приложение использует поле ISBN, чтобы найти соответствующую запись в таблице Title Author (Авторы книги). Когда эта запись найдена, для поиска имени автора программа использует поле AuID как ключ к таблице Authors (Авторы).

Код для выполнения этих действий находится в обработчике события Reposition (перемещение) элемента управления Data, которое вызывается каждый раз, когда пользователь нажимает одну из кнопок перемещения для перехода на другую запись в таблице Titles. Приложение использует все четыре таблицы базы данных, следовательно, ему необходимы и четыре объекта RecordSet — по одному на каждую таблицу. Форма приложения во время проектирования содержит четыре элемента управления Data, но только один из них видим во время выполнения приложения (рис. 17.16).



Рис. 17.16. Приложение ManyTbIs в процессе проектирования

Для разработки приложения ManyTbIs выполните следующие действия.

1. Создайте новый проект и поместите элементы управления Label и TextBox так, как изображено на рис. 17.16.

2. Поместите на форму и четыре элемента управления Data: TITLES, PUBLISHERS, AuthorISBN и Authors. Задайте в их свойствах DatabaseName путь к базе данных BIBLIO.

3. Каждый элемент управления Data должен видеть свою таблицу базы данных, так что обязательно установите свойство RecordSource каждого элемента управ­ления Data, как показано в табл. 17.10.

Таблица 17.10. Значения свойства

RecordSource элементов управления Data на форме ManyTbIs

Имя элемента управления Data

Значение свойства

RecordSource

TITLES

Titles

PUBLISHERS

Publishers

AUTHORISBN

Title Author

AUTHORS

Authors

4. Теперь свяжите текстовые поля с соответствующими полями элементов управ­ления Data.

•  Свяжите текстовое поле, в котором отображается название книги, с полем Title элемента управления Data с именем TITLES.

•  Свяжите текстовое поле, в котором отображается имя издателя, с полем Publisher элемента управления Data с именем PUBLISHERS.



•  Свяжите текстовое поле, в котором отображается имя автора, с полем Author элемента управления Data с именем AUTHORS.

Свяжите остальные текстовые поля с соответствующими полями элемента управления Data. Можно открыть приложение ManyTbIs в среде разработки Visual Basic и посмотреть, как различные элементы управления, связанные с данными, подключены к элементам управления Data. На этом этапе можно объединять любое название книги с любым автором и любым издателем, потому что все три элемента управления Data не соединены и могут быть размещены как угодно в соответствующих таблицах.

Для соединения элементов управления применим метод

Seek элемента управления Data, поэтому необходимо использовать первичные индексы таблиц. Выполняться это должно при загрузке формы.

5. Введите следующий код в обработчик события Load формы.

Private Sub Form Load ()

PUBLISHERS.Refresh

AUTHORISBN.Refresh

AUTHORS.Refresh

PUBLISHERS.Recordset.Index = "PrimaryKey"

AUTHORISBN.Recordset.Index = "ISBN"

AUTHORS.Recordset.Index = "PrimaryKey"

End Sub

Чтобы открыть индексный файл для таблицы объекта

RecordSet типа Table, необходимо назначить имя индекса свойству Index объекта RecordSet. Когда свойству Index назначено значение, то все вызовы Seek по отношению к RecordSet используют этот индекс

6. Введите следующий код в обработчик события Reposition элемента управления Data с именем TITLES

Private Sub TITLES_Reposition()

PUBLISHERS.Recordset.Seek "=",

TITLES.Recordset.Fields ("PubID")

If PUBLISHERS.Recordset.NoMatch Then

lblPublisher.Caption = "***"

AUTHORISBN.Recordset.Seek "=", _

TITLES.Recordset.Fields ("ISBN")

If AUTHORISBN.Recordset.NoMatch Then

lblAuthor.Caption = "***"

Exit Sub

End If

AUTHORS.Recordset.Seek " ", _

AUTHORISBN.Recordset.Fields ("Au_ID")

End Sub

Каждый раз, когда пользователь изменяет позицию элемента управления Data в объекте RecordSet, программа выполняет следующее.



1. Использует метод Seek для PUBLISHERS RecordSet, чтобы найти запись, у которой поле PubID соответствует полю PubID отображаемого названия книги.

2. Если такой записи нет, то она печатает звездочки в текстовом поле, в котором могло бы быть имя издателя. Если соответствующая запись найдена, программа ничего не выполняет. Метод Seek помещает элемент управления PUBLISHERS Data на строку таблицы Publishers с именем издателя, соответствующим названию книги. Соответствующее текстовое поле, связанное с данными, обновляется автоматически.

3. Затем программа находит запись таблицы Title Author, у которой поле ISBN равно ISBN текущей книги. Если подобная запись не существует - печатаются звездочки и происходит выход из подпрограммы. Если запись найдена, то ее поле AuID становится ключом для последней операции установки, нахо­дящей запись в таблице AUTHORS, у которой поле AuID соответствует полю AuID в таблице Title Authors.

Метод Seek быстр поля на форме обновляются немедленно. Даже с большими файлами этот подход работает хорошо и не приводит к значительным задержкам. Обратите внимание можно искать записи в RecordSet на основании более чем одного индекса. Каждый вызов Seek выполняется с определенным индексом, но можно изменять текущий индекс, устанавливая другое значение свойства Index объекта RecordSet.


Формат SQL-операторов


Существуют SQL-операторы для всех типов операций, которые можно выпол­нять с базой данных. SQL-операторы используются для создания новой базы данных и добавления в нее таблиц и индексов. Можно использовать SQL-операторы для обновления базы данных. SQL - функционально полный язык для управления базами данных, но наиболее часто он используется для выборки данных из базы. Выборка данных из базы называется запросом к базе данных, а SQL-операторы для осуществления запросов к базе данных называются командами выбора (Select-statements), потому что они содержат глагол SELECT (Выбирать).

Общий формат команд выбора следующий. SELECT (список полей) FROM (список таблиц) WHERE (выражение).

Примечание

Ключевые слова SQL в книге печатаются прописными буквами, но SQL не чувствителен к регистру. Использование верхнего регистра — вопрос стиля. Это помогает читателям, которые не знакомы с SQL, находить ключевые слова и лучше понимать его сложные элементы.

(список полей)

Эта часть команды SQL — список полей, разделенных запятыми, которые будут включены в запрос. Если имя элемента (поля или таблицы) содержит пробел, необходимо заключить его в квадратные скобки ([ ]) Например, чтобы включить в запрос поле Customer Name (Имя заказчика), нужно ввести [Customer Name].

Полное имя каждого поля предваряется именем таблицы, которой оно принад­лежит Эта запись обеспечивает уникальность имен полей, даже если несколько таблиц имеют поля с одинаковыми именами. Например, полное имя поля Total (Итог) в таблице Customer Orders (Счета заказчика) — [Customer Orders] Total. Если имя поля Total не появляется ни в какой другой таблице, то имя таблицы можно опустить и обратиться к этому полю как Total.

Результат выполнения запроса Select содержит записи таблицы, соответствующие критериям, и строку заголовков. Заголовки — это имена полей, задаваемые при проектировании базы данных. При отображении результатов запроса с помощью связанного с данными элемента управления Grid (Сетка) в качестве заголовков отображаются имена полей. Чтобы изменить заголовки, используйте ключевое слово AS после имени поля. Это удобно, когда для имени поля таблицы возникает неоднозначность в контексте запроса, содержащего несколько таблиц с совпадаю­щими именами в различных таблицах. Например, если имеется поле Total в таблице Customer Orders, то можно отобразить заголовок Order Total этого поля следующим образом.


[Customer Orders].[Total] AS [Order Total]

Чтобы выбрать все поля в таблице, используйте звездочку (*) вместо пере­ числения имен всех полей. Например, следующая команда выбирает все поля в таблице Orders: SELECT * FROM Orders

(список таблиц)

Эта часть команды — список всех таблиц, на которых основан запрос. Чтобы выбрать поля из нескольких таблиц, разделите имена полей запятыми. Если SQL-запрос основан более чем на одной таблице, было бы неплохо перед именами полей добавить имена таблиц, которым поля принадлежат.

При выборе полей из нескольких таблиц необходимо указать, как связать таблицы. Если вы укажете только имена таблиц, то результат запроса будет содержать все возможные комбинации полей в каждой таблице. Чтобы связать поля в нескольких таблицах, создайте, так называемое, объединение (join), являющееся фундаментальным понятием в командах выбора SQL.

(выражение)

Эта часть команды — логическое выражение, использующееся для отбора данных и возвращающее объект RecordSet. Для формирования этого выражения можно использовать большинство встроенных функции и операторов Visual Basic, а также следующие SQL-операторы.

field_name BETWEEN value1 AND value2

- возвращаются только строки, в которых поле field_name имеет значение в диапазоне от valuel до value2 (пример см в параграфе "#date#")

field_name IN (valuel, value2, ...) - возвращаются только те строки, в которых поле field_name совпадает с одним из значений в круглых скобках. Внутри скобок задается любое число элементов. Следующая команда возвращает записи для заказчиков из определенных городов.

SELECT Customers.CompanyName, Customers.ContactTitle,

Customers.City, Customers.Country FROM Customers WHERE

UCase(customers.city) IN ("BERLIN", "LONDON", "BERN", "PARIS")

ORDER BY Customers.Country

#date# Этот оператор определяет даты внутри выражения по американской системе месяц/день/год. Например, следующая SQL-команда возвращает из базы данных NWIND все заказы, произведенные в 1994 году.



SELECT Orders.ShipName, Orders.OrderDate, Orders.CustomerID

FROM Orders WHERE OrderDate BETWEEN #1/1/94# AND #12/31/94#



LIKE Этот оператор - один из наиболее мощных и сложных в SQL. Он предна­значен для выбора строк по шаблону. Для формирования выражения используются специальные символы, перечисленные в табл. 17.11.

Таблица 17.11. Специальные символы, используемые в операторе LIKE

Символ

Пояснение

Пример

*

Любая группа символов

Joh* определяет John, Johnson и John's

?

Любая одиночная буква

?t определяет at и it

#

Любая одиночная цифра

1234#67 определяет 1234167, 1234267, 1234367, 1234467 и т.д.

[]

Один символ из заключенных в скобки

[ai]t определяет at и it, но не bt

[!]

Любой символ не из скобок

[!a]t определяет it, но не at

[-]

Любой символ из диапазона

[i-k]t определяет it, jt, и kt, но не at или st

ORDER BY (field list). Этот оператор упорядочивает строки RecordSet по значениям указанных полей. Следующий SQL-оператор создает RecordSet с именами всех заказчиков из таблицы Customers базы данных NWIND, отсортированными по стране. Имена заказчиков из одной страны сортируются по названиям их городов.

SELECT Customers.CompanyName, Customers.ContactName,

Customers.Country, Customers.City FROM Customers

ORDER BY Customers.Country, Customers.City

(В этой команде можно не указывать имя таблицы перед именами полей.) Результаты работы команды показаны ниже.




Формы и элементы управления


HTML-страницы содержат элементы управления, которые позволяют пользователю вводить информацию. Это обычные элементы управления

Windows:

текстовые поля ввода, переключатели и т.п. Области HTML-страницы, в которых появляются эти элементы управления, называются формами, а сами элементы управления - встроенными (intrinsic) элементами управления. HTML предлагает специальные теги для размещения встроенных элементов управления на форме.

Примечание

Кроме встроенных элементов управления, на формах можно разместить элементы управления ActiveX. Так как элементы управления ActiveX загружаются на компьютер клиента, а большинство пользователей не желает их инсталлировать на своей системе, эта тема подробно не рассматривается.

Прежде чем разместить элементы управления на странице, создайте форму тегом <FORM>. Синтаксис его таков:

<FORM NAME=name ACTION=action METHOD=method>

</FORM>

Все элементы управления помещаются между двумя тегами. Атрибут NAME (не обязательный) — имя формы. Он используется, если страница содержит несколько форм Атрибут ACTION — имя приложения на сервере, вызванного для обработки информации. Атрибут METHOD определяет, как значения элементов управления передаются на сервер. Информация, необходимая броузеру для установления контакта с приложением на сервере, содержится в теге <FORM>.

Перечислим элементы управления, поддерживаемые HTML. На рис. 19.7 показана Web-страница с формой, содержащей большинство встроенных элементов управления HTML. HTML-код для этой страницы приведен в параграфе "Web-страница FORM.HTW

Элемент управления TEXT

Элемент управления Text - это поле, в которое пользователь вводит текстовую строку (название, адрес и т.п.). Чтобы вставить элемент управления Text на форму, используется следующий тег.

<INPUT TYPE = TEXT NAME = "Publisher" VALUE = "Sybex">

Атрибут VALUE задает начальное значение. После ввода значения пользователем VALUE будет содержать новую строку. Для редактирования содержимого элемента управления Text используются общие клавиши редактирования (Home, Del, Insert и т д.), но отформатировать текст нельзя.


Для управления размерами элемента и объемом его содержимого используются атрибуты SIZE и MAXLENGTH. Атрибут SIZE устанавливает размер элемента управ­ления на форме как количество символов, атрибут MAXLENGTH - максимальное количество символов, которое пользователь может вводить в элемент управления. Разновидностью элемента управления Text является идентичный ему элемент управ­ления Password, но он не отображает введенные символы в том виде, как они вводятся с клавиатуры. Он отображает звездочки и используется для введения паролей.



Рис. 19.7. Форма, содержащая все встроенные элементы управления HTML

Элемент управления TextArea

Элемент управления TextArea аналогичен элементу управления Text, но позволяет вводить несколько текстовых строк. С элементом управления TextArea работают все обычные клавиши редактирования. Для размещения элемента управления TextArea на форме используется тег <TEXTAREA>.

<TEXTAREA NAME = "Comments" ROWS = 10 COLS = 30>

The best editor I've ever used!

</TEXTAREA>

Поскольку элемент управления TextArea позволяет задать несколько строк исходного текста, он вставляется не обычным тегом <INPUT>, а парой тегов <TEXTAREA>. Атрибуты ROWS и COLS задают размерность элемента управления на странице, указывая количество символов. Следует заметить: символ прерывания строки между двумя тегами <TEXTAREA> сохраняется и при отображении текста в элементе управления. Если включить теги HTML в исходный текст, то они появятся в виде текста в элементе управления.

Элемент управления CheckBox

Элемент управления CheckBox — флажок работающий как кнопка. Каждый раз когда пользователь на нем щелкает его состояние изменяется. Этот элемент управления используется для задания списка опций из которого пользователь выбирает один или больше элементов. Для добавления на форму элемента управления CheckBox используется следующий тег <INPUT>.

<INPUT TYPE = CHECKBOX NAME = "Checkl">

Чтобы начать проверку элемента управления CheckBox, необходимо задать атрибут CHECKED тега <INPUT>. Элемент управления принимает значение 0 или 1 в зависимости от того установлен ли флажок.



Элемент управления RadioButton

Элемент управления RadioButton  переключатель — используется для задания списка опции подобно элементу управления CheckBox, но при этом может быть выбран только один из элементов списка. Каждый раз когда посетитель выбирает новую опцию, предыдущая отменяется. Чтобы поместить этот элемент управления на форму используется следующее выражение.

<INPUT TYPE = RADIO NAME = "Radio1">

Если каждый элемент управления CheckBox имеет уникальное имя, то группа элементов RadioButton должна иметь общее имя. Это позволяет броузеру определить, сколько элементов управления RadioButton входит в одну группу, и какой элемент установлен. Чтобы определить какой из элементов группы будет устанавливаться первым (по умолчанию) используется атрибут CHECKED. Следующие строки помещают на форму группу из четырех элементов управления RadioButton.

<INPUT TYPE = RADIO NAME = "Level">Beginner<BR>

<INPUT TYPE = RADIO NAME = "Level">Intermediate<BR>

<INPUT TYPE = RADIO NAME = "Level" CHECKED>Advanced<BR>

<INPUT TYPE = RADIO NAME = "Level">Expert<BR>

Элемент управления Multiple Selection

Элемент управления Multiple Selection является списком из нескольких пунктов. Пользователь может ничего не выбрать или выбрать один или несколько пунктов из списка. Список ограничен парой тегов <SELECT>. Каждый элемент списка вставляется отдельным тегом <ОРTIOМ>. Для размещения на форме списка Multiple Selection введите следующие строки.

<SELECT NAME = "MemoryOptions" SIZE = 3 MULTIPLE = multiple>

<OPTIONAL VALUE = 16> 16 MB </OPTION>

<OPTIONAL VALUE = 32> 32 MB </OPTION>

<OPTIONAL VALUE = 64> 64 MB </OPTION>

<OPTIONAL VALUE = 128> 128 MB </OPTION>

<OPTIONAL VALUE = 256> 256 MB </OPTION>

</SELECT>

Атрибут SIZE задает количество видимых строк. Если его пропустить, то список будет представлен одной строкой а посетителю придется использовать клавиши управления курсором, чтобы просмотреть доступные пункты. Если список содержит больше одной строки то вертикальная панель прокрутки автоматически предоставляет помощь посетителю в выборе искомого элемента. Атрибут MULTIPLE указывает, может ли пользователь выбрать несколько пунктов списка, удерживая нажатой клавишу Shift или Ctrl и одновременно щелкая на названиях нужных пунктов. Если пропустить этот атрибут, то при выборе нового элемента предыдущий выбор отменяется.



У тега <OPTION> есть атрибут VALUE, который задает значение выбранного элемента. Если в предыдущем списке пользователь выбирает пункт 64 MB, то значение 64 передается на сервер. Наконец, для начального выбора одной или более опций задается атрибут SELECTED.

<OPTION SELECTED VALUE=128> 128 MB</OPTION>

Элемент управления Command Button

Щелчок на этом элементе управления инициирует определенные действия. Без VBScript кнопки Command выполняют только два действия.

•  Передают данные, введенные в элементах управления, на сервер.

• Сбрасывают значения элементов управления формы в исходное состояние.

Используя VBScript, кнопки Command выполняют любые действия, програм­мируемые на страницах. На форме можно разместить кнопки трех типов" Submit (Передача), Reset (Сброс) и General (Общая).

Наиболее важной кнопкой является Submit. Она пересылает содержимое всех элементов управления формы на сервер (значения обрабатываются приложением, URL которого задается атрибутом ACTION тега <FORM>). Кнопка Reset сбрасывает значения элементов управления формы в исходные. Она не передает никаких значений на сервер. Большинство форм содержит кнопки Submit

и Reset, которые вставляются следующим образом.

<INPUT TYPE =

SUBMIT VALUE = "Send data">

<INPUT TYPE = RESET VALUE = "Reset Values">

Атрибут VALUE задает надпись, которая появится на кнопке. Кнопка Submit считывает имя приложения на сервере, с которым необходимо установить связь (атрибут ACTION тега <FORM>), применяет значения элементов управления к этому URL и выполняет передачу на сервер.

Третья кнопка — общего типа, ее тип — просто BUTTON, а функции такие же, как и у других кнопок интерфейса Windows. Нажатие этой кнопки инициирует событие, использующееся для выполнения некоторого VBScript-кода. Чтобы помес­тить этот элемент управления на форму, используется тег <INPUT>.

<INPUT TYPE = BUTTON NAME = "ShowDate">

После каждого нажатия этой кнопки на выполнение запускается обработчик события ShowDate_onClick. Его код приведен ниже.



Sub ShowDate_on Click()

MsgBox "The date is "& Date ()

End Sub

Совет

He следует использовать кнопку Submit для проверки допустимости данных на компьютере клиента, потому что при ее нажатии данные просто передаются на сервер. Вместо этого для запуска подпрограммы проверки допустимости данных используется элемент управления Button. Затем с помощью метода Submit они передаются на сервер.

Обычно кнопка Command проверяет допустимость введенных пользователем данных, а потом передает содержимое формы в ASP-приложение на сервер. Это кнопка общего типа, она создается и размещается на форме следующим образом.

<INPUT TYPE = BUTTON NAME = SendData VALUE = "Register Now">

Программа 19.1. Обработчик события Click кнопки SendData

<SCRIPT LANGUAGE = VBScript>

Sub SendData_onClick()

If Instr("@", Email.Value)=0 Then

MsgBox "Invalid e-mail address. "& chr(13)& _

  "Please enter a string like_

yourname@yourserver.com"

Else If RealName.Value = " " Then

MsgBox "You can't register without a name"

Else

RegistrationForm.Submit

End If

End Sub

</SCRIPT>

Этот сценарий запускается при нажатии кнопки

SendData. Сначала он проверяет содержимое элемента управления EMail. Если адрес задан не в форме name@server.com, то пользователю предлагается ввести правильный e-mail адрес. Затем проверяется значение элемента управления RealName.

Если пользователь не ввел имя, выдается приглашение на ввод. Если обе проверки в структуре If завершаются неудачно, то сценарий пересылает данные других элементов управления (форма содержит другие элементы управления) с помощью метода Submit. Метод Submit формы эквивалентен кнопке Submit. В обоих случаях броузер устанавливает связь с приложением заданным атрибутом ACTION тега <FORM> и передает ему значения элементов управления как параметры. Например, такую строку:

http://www.servername.com/Register.asp?EMail=EP@SYBEX.COM&Name=Evangelos+P

EMail и Name — это имена параметров, ожидаемых приложением Register.asp на сервере (далее показано, как написать приложение, которое извлекает данные, переданные клиентом, и обрабатывает их на сервере). Значения этих параметров могут быть любыми. Обратите внимание: строка не заключается в кавычки, а пробелы заменены знаком "+".


Формы и окна


В этом параграфе описываются 32-х разрядные API-функции Windows, расши­ряющие возможности Visual Basic при создании форм, окон и меню Используя эти функции, можно создавать элементы меню, содержащие растровые изображения и динамически изменять объекты меню. Вы узнаете, как отслеживать перемещение мыши и манипулировать окнами других активных приложении, размещенных на рабочем столе.



Функции доступа к системной базе данных


Registry

Registry Windows 95/98 - это иерархическая база данных (часто называемая реестром),

содержащая информацию об установках Windows. В нее входит инфор­мация о пользователях, о конфигурации аппаратных средств системы и прикладных программах. Registry заменила INI-файлы (использовавшиеся в предыдущих версиях Windows), которые предназначались для хранения информации в перерывах между сеансами работы.

Для доступа к Registry воспользуйтесь программой Regedit. Для ее запуска выполните следующие действия.

1. Выберите команду Run в меню Start (команда Выполнить в меню Пуск).

2. В окне Run (Пуск) наберите regedit и нажмите клавишу Enter, чтобы открыть окно Registry Editor, показанное на рис. 13.9.

Если выполнить двойной щелчок на одном из объектов в главном окне Regedit, то данные, записанные в Registry, появятся на экране в виде древовидной структуры. Объект самого верхнего уровня обычно называют Registry key

(раздел базы данных), а находящиеся в нем объекты нижнего уровня - подразделами Registry включает следующие разделы.

• HKEY_CLASSES_ROOT хранит информацию о зарегистрированных расшире­ниях и файловых ассоциациях, данные OLE.

• HKEY_CURRENT_USER относится к текущему пользователю Если он един­ственный, то содержание этого раздела полностью совпадает с подразделом HKEY_USERS.

• HKEY_LOCAL_MACHINE хранит информацию о конфигурации аппаратных средств, установленных на компьютере Подразделы HKEY_LOCAL_MACHINE.

• HKEY_USERS содержит информацию о конфигурации рабочего стола, параметры сети и другие сведения об отдельных пользователях, которые могут регистрироваться на данном компьютере

• HKEY_CURRENT_CONFIG содержит информацию об установленных шрифтах и принтерах.

• HKEY_DYN_DATA хранит сведения о производительности компьютера. После старта системы они загружаются в оперативную память и могут там динамически изменяться.

Рис. 13.9. Главное окно Registry Editor

Предупреждение

Следует предельно аккуратно обращаться с информацией, расположенной в реестре. Повреждение нескольких объектов, находящихся в нем, может привести к прекращению работы системы вплоть до невозможности загрузки. Прежде чем выполнять какие-либо действия с содержимым реестра, пользуясь средствами Visual Basic, убедитесь, что сделаны резервные копии файлов SYSTEM.DAT и USER.DAT. С их помощью всегда можно восстановить исходное состояние базы данных Registry. Прежде чем выполнять с ним какие-либо действия, следует обратиться к Windows по вопросам процедур резервного копирования и восстановления. Лучше всего начинать с использования функций, встроенных в Visual Basic, которые являются вполне "безопасными" (они описаны в Приложении А на компакт-диске), а затем переходить к использованию API-функции.


Можно воспользоваться Regedit, чтобы выяснить, какого типа информация требуется определенным приложениям. Относительно безопасно использовать Registry для хранения информации о приложении. Например, можно сохранить информацию об инициализации приложения, чтобы при следующем запуске можно было просмотреть информацию об установках предыдущего сеанса работы. Список недавно открывавшихся файлов, которые можно найти почти в каждом приложении Windows, хранится в Registry. Манипулируя содержимым реестра, следует внимательно следить за тем, чтобы не изменить информацию о других приложениях. Изменяйте информацию, имеющую отношение только к вашим собственным приложениям.

Работа с реестром заслуживает того, чтобы надолго на ней остановиться. В этом параграфе будет рассмотрена процедура создания новой ветви в базе данных Registry для сохранения информации, которую приложение считывает. Это несложная процедура, полезная для всех, кто работает с Registry.

VB6 в действии: проект Registry

Приложение Registry позволяет продемонстрировать процесс создания разделов в реестре Windows (Registry), записи соответствующих значений и получения данных из него. В приложении создаются три подраздела HKEY_LOCAL_ MACHINE, в которых хранятся размеры формы, запущенной при предыдущем сеансе работы:

•  \Sybex\Mastering VB 6.0

• Window Width (Ширина Окна)

• Window Height (Высота Окна)

В программе (рис. 13.10) используются подразделы

Window Width (Ширина Окна) и Window Height (Высота Окна) для хранения ширины и высоты окна (данные записываются приложением Registry).



Рис. 13.10. Программа Registry запоминает размеры формы, установленные во время предыдущего сеанса работы

Когда программа запускается, она пытается получить значения, хранящиеся в подразделах Window Width и Window Height с помощью функции RegQueryValue Ex(). Если эти подразделы содержат значения, то программа просто получает их и устанавливает, соответственно, ширину и высоту окна. Если эти подразделы не содержат значений, значит, в Registry нет соответствующих элементов. Затем программа устанавливает высоту и ширину текущего окна и сохраняет эту инфор­мацию в реестре с помощью функции RegSet Value Ех(). Функция RegCreateKeyO позволяет создать определенный элемент реестра. Если такой элемент существует, то функция открывает к нему доступ.



Если размеры окна изменяются пользователем, программа сохраняет новые значения высоты и ширины окна в реестре с помощью метода

QueryUnload. При последующем запуске программы окно будет иметь именно эти размеры. Таким образом, можно организовать сохранение установок инициализации программы в реестре, а затем получать их при запуске приложения. Чтобы проверить проект Registry, закройте форму щелчком на кнопке Close. Если работа приложения завершена с помощью команды End меню Run (команда Закончить в меню Выполнить) в IDE-среде Visual Basic, то событие QueryUnload не вызывается.

Ниже приводится текст программы Registry.

Программа 13.11. Программа Registry

Option Explicit

Private Declare Function RegCreateKey Lib "advapi32.dll" _

Alias "RegCreateKeyA" (ByVal hKey As Long, _

ByVal IpSubKey As String, phkResult As Long) As Long

Private Declare Function RegDeleteKey Lib "advapi32.dll"

Alias "RegDeleteKeyA" (ByVal hKey As Long,

ByVal IpSubKey As String) As Long

Private Declare Function RegDeleteValue Lib "advapi32.dll" _

Alias "RegDeleteValueA" (ByVal hKey As Long, _

ByVal IpValueName As String) As Long

Private Declare Function RegQueryValueEx Lib "advapi32.dll" _

Alias "RegQueryValueExA" (ByVal hKey As Long,

ByVal IpValueName As String, ByVal IpReserved As Long, _

IpType As Long, IpData As Any, IpcbData As Long) As Long

Private Declare Function RegSetValueEx Lib "advapi32.dll" _

Alias "RegSetValueExA" (ByVal hKey As Long, _

ByVal IpValueName As String, ByVal Reserved As Long,

_

ByVal dwType As Long, IpData As Any, _

ByVal cbData As Long) As Long

Const ERROR_SUCCESS = 0&

Const ERROR_BADDB = 1009&

Const ERROR_BADKEY = 1010&

Const ERROR_CANTOPEN = 1011&

Const ERROR_CANTREAD = 1012&

Const ERROR_CANTWRITE = 1013&

Const ERROR_REGISTRY_RECOVERED = 1014 &

Const ERROR_REGISTRY_CORRUPT = 1015&

Const ERROR_REGISTRY_IO_FAILED = 1016&



Const HKEY CLASSES ROOT = &H80000000

Const HKEY_CURRENT_USER = &H80000001

Const HKEY_LOCAL_MACHINE = &H80000002

Const REG_SZ = 1

‘ Dim regKey As String

Const regKey = "\Sybex\Mastering VB 6.0"

Private Sub ForraLoad()

Dim retValue As Long, result As Long

Dim keyID As Long, keyValue As String

Dim subKey As String

Dim bufSize As Long

Label 6.Caption = regKey

‘ Создание раздела

retValue = RegCreateKey(HKEY_LOCAL_MACHINE, regKey, keyID)

If retValue = 0 Then

‘ Сохранение значения ширины

subKey = "Window Width"

retValue = RegQueryValueEx(keyID, subKey, 0&, _

REG_SZ, OS, bufSize)

‘ Если значение не задано, установить его

If bufSize < 2 Then

   keyValue = Me.Width

   retValue = RegSetValueEx(keyID, subKey, 0&, _

REG_SZ, ByVal keyValue, Len(keyValue) + 1)

Else

   keyValue = String(bufSize + 1, " ")

   retValue = RegQueryValueEx(keyID, subKey, _

           0&, REG_SZ, ByVal keyValue, bufSize)

   keyValue = Left$(keyValue, bufSize - 1)

   Me.Width = keyValue

End If

‘ Установка значений для формы

Label4.Caption = subKey

Label5.Caption = Me.Width

‘ Запись значения высоты

subKey = "Window Height"

retValue = RegQueryValueEx(keyID, subKey, 0&,

_

REG_SZ, 0&, bufSize)

If bufSize < 2 Then

   keyValue = Me.Height

   retValue = RegSetValueEx(keyID, subKey, 0&, _

REG_SZ, ByVal keyValue, Len(keyValue) + 1)

Else

   keyValue = String(bufSize + 1, " ")

   retValue = RegQueryValueEx(keyID, subKey, 0&, REG_SZ, _

ByVal keyValue, bufSize)

   keyValue = Left$(keyValue, bufSize - 1)

   Me.Height = keyValue

End If

‘ Установка значений для формы

Label8.Caption = subKey

Label7.Caption = Me.Height

   End If

End Sub

Private Sub Form_QueryUnload(Cancel As Integer, _

UnloadMode As Integer)

Dim keyValue As String

Dim retValue As Long, keyID As Long

   retValue = RegCreateKey(HKEY_LOCAL_MACHINE, regKey,     keyID)

   keyValue = Me.Width

   retValue = RegSetValueEx(keyID, "Window Width", 0&,

   REG_SZ, ByVal keyValue, Len(keyValue) + 1)

   keyValue = Me.Height

   retValue = RegSetValueEx(keyID, "Window Height", 0&, _

   REG_SZ, ByVal keyValue, Len(keyValue) + 1)

End Sub

Приложение Registry успешно работает в Windows 95/98 (но не в Windows NT 4).


Функции рисования


Visual Basic предоставляет несколько методов для рисования на формах элементов управления PictureBox (см. гл. 6). Этих методов немного, но разнообразие их параметров делает эти методы достаточно гибкими. Однако они работают не так быстро, как их "двойники" из набора API-функций. Система Windows содержит много графических объектов и достаточное количество API-функций для рисования

и заливки изображений. В этом параграфе рассмотрены некоторые API-функции, которые помогут повысить быстродействие приложений, создаваемых в Visual Basic (рассмотрение всех API-функций для работы с графикой выходит за пределы этой книги). В последнем параграфе главы рассмотрены основные положения графиче­ских API-функций Windows, контекстов устройств и растровых структур. Эти методы помогут написать быстродействующие программы, позволяющие орга­низовать вывод графических изображений и манипулировать отдельными пиксе­лями.

Примечание

Обратите внимание: значительная часть данной главы посвящена графическим функциям и методам вывода растровых изображений. Графические операции являются самыми медленными в Windows, поэтому Visual Basic с благодарность примет от вас любую помощь. Примеры, приведенные в данном параграфе, помогут вам ускорить выполнение графических операций.

Вывод линий и окружностей

Двумя основными API-функциями являются функции LineTo() и Ellipse(), позволяющие выводить прямые линии и эллипсы (окружности). Объявление функции LineTo() приведено ниже.

Public Declare Function LineTo Lib "gdi32" Alias ''LineTo" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long) As Long

Функция LineTo() позволяет нарисовать отрезок прямой, соединяющий текущую точку и точку с координатами (X, Y) в указанном контексте устройства. Чтобы определить текущую точку, воспользуйтесь функцией MoveToEx():

Private Declare Function MoveToEx Lib "gdi32" Alias "MoveToEx" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long,

IpPoint As POINTAPI) As Long


Параметры х и у функции MoveToEx() являются координатами новой текущей точки. Последний параметр - структура POINTAPI - содержит координаты текущей точки перед их изменением данной функцией. Структура POINTAPI рассматрива­лась ранее в параграфе "Объявление 32-х разрядных функций и структур" этой главы.

Координаты точек в обеих функциях (как и во всех графических API-функциях) задаются в пикселях. Если возникает необходимость в совместном использовании графических методов Visual Basic и API-функций, то необходимо установить значение соответствующего свойства элемента управления равным 3 (пиксели). Чтобы в окне формы Form1 нарисовать отрезок прямой линии от точки с координатами (10,10) до точки (85,130), используется следующий набор операторов.

Dim point As POINTAPI

MoveToEx Forml.hDC, 10, 10, point

LineTo Forml.hDC, 85, 130

Функция Ellipse(), объявленная ниже, предназначена для вывода эллипсов и кругов.

Public Declare Function Ellipse Lib "gdi32" Alias "Ellipse" _

(ByVal hdc As Long, ByVal XI As Long, ByVal Yl As Long, _

ByVal X2 As Long, ByVal Y2 As Long) As Long

Эта функция позволяет нарисовать эллипс в контексте устройства, определенном дескриптором hdc.

Эллипс вписан в прямоугольник, определенный координатами противоположных вершин (XI, Y1) и (X2,Y2). Чтобы нарисовать квадрат, нужно задать прямоугольник с одинаковыми сторонами.

Если эти команды используются для создания изображений на формах или элементах управления PictureBox, то цвет линии определяется значением свойства ForeColor формы или PictureBox, а ширина - значением их свойства DrawWidth. Можно изменить значения свойств либо воспользоваться API-функцией CreatePen().

Public Declare Function CreatePen Lib "gdi32" Alias "CreatePen" _

(ByVal nPenStyle As Long, ByVal nWidth As Long, _

ByVal crColor As Long) As Long

Параметр

nPenStyle — целое число, которое может принимать любое из значений, приведенных в табл. 13.8. Указанные значения соответствуют значениям свойства DrawMode.



Таблица 13.8. Значения параметра nPenStyle функции CreatePenQ

Константа

Значение

PS_SOLID

0

PS_DASH

1

PS_DOT

2

PS_DASHDOT

3

PS_NULL

5

PS_DASHDOTDOT

4

PS_JNSIDEFRAME

6

Для создания сплошного пера красного цвета шириной два пикселя необходимо вызвать функцию CreatePen() со следующими параметрами:

myPen = CreatePen (0, 2, RGB (255, 0, 0))

Создание объекта Pen не означает, что данный объект будет автоматически использоваться в последующих операциях вывода графики. Чтобы использовать новое перо в дальнейшем, "свяжите" объект Pen с контекстом устройства, в котором он применяется. Вызовите для этого функцию Select0bject().

Public Declare Function Select0bject Lib "gdi32" Alias _

"SelectObject" (ByVal hdc As Long, ByVal h0bject As _

Long) As Long

Первый параметр — дескриптор контекста устройства, в котором будет выпол­няться процедура рисования, а второй параметр — дескриптор объекта Pen. Чтобы указать, что объект myPen будет использоваться в последующих операциях, вызовите такую функцию:

Select0bject Forml.hDC, myPen

После того как этот оператор выполнится, функции

Line() и Ellipse() смогут использовать перо myPen при выводе изображений в контекст устройства. Анало­гичным объекту Pen является объект Brush, который используется для заливки областей (эта процедура будет рассмотрена позже). Воспользуемся функцией CreateSolidBrush()

для создания объекта Brush.

Public Declare Function CreateSolidBrush Lib "gdi32" Alias _

"CreateSolidBrush" (ByVal crColor As Long) As Long

Цвет кисти задается функцией RGB() или свойством Color в диалоговом окне Color. Чтобы использовать объект Brush в дальнейших операциях, выберите его в контексте устройства с помощью функции SelectObject().

VB6 в действии: проект APIDraw

В проекте APIDraw показана работа графических API-функций, рассмотренных в предыдущем параграфе. APIDraw - достаточно простое приложение, которое рисует круг, эллипс и описанные вокруг них (ограничивающие) прямоугольники (рис. 13.11). В следующем параграфе рассмотрена процедура заливки созданных изображений.





Рис. 13.11. Приложение APIDraw: круг и эллипс, созданные с помощью API-функции Ellipse()

В начале программы объявляются API-функции.

Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long,

ByVal x As Long, ByVal у As Long) As Long

Private Declare Function Ellipse Lib "gdi32" (ByVal hdc As Long,

ByVal XI As Long, ByVal Yl As Long, ByVal X2 As Long, _

ByVal Y2 As Long) As Long

Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, _

ByVal x As Long, ByVal у As Long, IpPoint As POINTAPI) _

As Long

Private Declare Function CreateSolidBrush Lib "gdi32" _

(ByVal crColor As Long) As Long

Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc _

As Long, ByVal x As Long, ByVal у As Long, ByVal crColor _

As Long, ByVal wFillType As Long) As Long

Private    Declare Function SelectObject Lib "gdi32" _

     (ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function DeleteObject Lib "gdi32" _

(ByVal hObject As Long) As Long

Фрагмент программы, обрабатывающий щелчок на клавише Draw Now (см. рис. 13.11) содержит функции MoveToEx() и LmeTo(), позволяющие нарисо­вать ограничивающие прямоугольники, и функцию Ellipse() для вывода эллипса. Первый эллипс ограничен прямоугольником, противоположные вершины которого расположены в точках с координатами (10, 10) и (500, 300), а второй - ограничен прямоугольником, который простирается из точки (10, 10) в точку (300, 300). Так как второй прямоугольник является квадратом, второй эллипс является окруж­ностью. Фрагмент программы, обрабатывающий нажатие кнопки Draw Now, приведен ниже

Программа 13.12. Вывод эллипсов

Private Sub Commandl Click()

Dim point As POINTAPI

Forml.CIs

Forml.ForeColor = RGB(255, О, О)

MoveToEx Forml.hdc, 10, 10, point

LineTo Forml.hdc, 500, 10

LineTo Forml.hdc, 500, 300

LineTo Forml.hdc, 10, 300

LineTo Forml.hdc, 10, 10

Ellipse Forml.hdc, 10, 10, 500, 300

Forml.ForeColor = RGB(0, 0, 255)



MoveToEx Forml.hdc, 10, 10, point

LineTo Forml.hdc, 300, 10

LineTo Forml.hdc, 300, 300

LineTo Forml.hdc, 10, 300

LineTo Forml.hdc, 10, 10

Ellipse Forml.hdc, 10, 10, 300, 300

End Sub

Заливка замкнутых фигур

Очень полезным режимом (отсутствующим в Visual Basic) является режим заливки замкнутых фигур (областей). Можно легко нарисовать окружность и прямоугольник, залитые определенным цветом, но как быть с фигурами, контуры которых определяются пересечением базовых фигур (см. рис. 13.11)? Для заливки фигур неправильной формы необходимо использовать API-функцию ExtFloodFill().

Public Declare Function ExtFloodFill Lib "gdi32" _

Alias "ExtFloodFill" (ByVal hdc As Long, ByVal x As Long, _

ByVal у As Long, ByVal crColor As Long, ByVal _

wFillType As Long) As Long

Эта функция позволяет залить сплошную область, начинающуюся в точке с координатами (x, у) цветом, определенным параметром crColor.

Последний параметр (wFillType)

определяет тип заливки и может принимать одно из следующих значений.

•   FLOODFILLBORDER (0) - функция выполняет заливку области цветом crColor. Точка (х, у) должна находиться в пределах закрашиваемой области.

•   FLOODFILLSURFACE (1) - параметр cIColor определяет только цвет обрамления.

Поскольку область заливается с помощью кисти, сначала необходимо создать объект Brush, затем выбрать его в контекст устройства и вызвать функцию ExtFloodFill(). Фигуры, появляющиеся на экране после щелчка на кнопке Draw Now (приложения Ellipse), содержат весьма причудливые области, для заливки которых применяется функция ExtFloodFill(). К этой программе добавлен небольшой фрагмент, позволяющий заливать замкнутые области цветом, выбранным пользо­вателем в диалоговом окне Color. Чтобы заполнить область, щелкните на кнопке Fill Color (в общем диалоговом окне Color) и выберите цвет заливки, а затем щелкните на точке, расположенной в пределах области, которую вы хотите залить. Заливка выполняется в обработчике события MouseUp, текст которого приведен ниже.

Программа 13.13. Заливка замкнутой области

Private Sub Form MouseUp(Button As Integer, Shift As Integer, _

x As Single, у As Single)

brush = CreateSolidBrushe(CommonDialogI.Color)

SelectObject Me.hdc, brush

ExtFloodFill Me.hdc,

x,
y, Me.point(x, y), FLOODFILLSURFACE

DeleteObject brush

End Sub

Программа извлекает информацию о выбранном цвете из элемента управления CommonDialogI и использует ее для создания сплошной кисти. Затем кисть выбирается в контекст устройства формы и вызывается функция ExtFloodFill(), с помощью которой выполняется заливка требуемой области.


Функции вывода пикселей


В большинстве случаев можно не беспокоиться о быстродействии приложений, в которых выводится всего несколько линий (даже если этот процесс занимает пару миллисекунд), за исключением, быть может, отдельных случаев, связанных с выводом сложных с математической точки зрения кривых. Но даже тогда, вероятно, нет смысла возиться с использованием API-функций. Если вспомнить о приложении Image (см. гл. 7), в котором в процессе обработки изображения необходимо было устанавливать значения цвета примерно для миллиона пикселей, то там все выглядит иначе: каждая лишняя миллисекунда, затраченная на обработку одного пикселя, будет приводить к значительной задержке всего цикла в целом. В гл. 12 рассматри­вались функции GetPixelV() и SetPixelV(), которые работают значительно быстрее, чем их аналоги в Visual Basic (методы Point и PSet соответственно) для чтения и установки значения пикселя.

Функция GetPixelV() возвращает значения пикселя в координатах (х, у) в контексте устройства, определенном параметром hdc, следующим образом.

Public Declare Function GetPixel Lib "gdi32" Alias "GetPixel" _

(ByVal hdc As Long, ByVal x As Long, ByVal y As Long) _

As Long

Значение пикселя возвращается как тип Long так же, как это сделал бы метод Point. Первый параметр функции GetPixel() - значение свойства hDC формы, элемента управления PictureBox или любого другого элемента управления, в который можно осуществить вывод графики.

Объявим функцию SetPixel().

Public Declare Function SetPixel Lib "gdi32" Alias "SetPixel" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long, _

ByVal crColor As Long) As Long

Здесь

hdc - дескриптор контекста устройства управления, x и у - координаты пикселя, а crColor — его цвет.

На рис 13.12 приведено окно приложения CopyPix, которое выполняет копиро­вание пикселей из левого PictureBox в правый с помощью программы, исполь­зующей операторы Visual Basic (кнопка Сору VB), или API-функции GetPixelV() и SetPixelV() (кнопка Сору API). Запустите приложение, чтобы увидеть, насколько быстрее работают API-функции по сравнению с их эквивалентами в Visual Basic. При этом можно не засекать время, требуемое для выполнения этих операций — разница будет заметна даже "на глаз". Не забудьте, что значение свойства AutoRedraw второго элемента PictureBox должно иметь значение False, чтобы можно было заметить разницу в скорости выполнения операций копирования.


Проект CopyPix необходимо запускать на системе, способной отображать более 256 цветов. Если система поддерживает только 256 цветов, необходимо удостове­риться, что цвет, выбранный для заливки области, является цветом из палитры, а не псевдоцветом. Если цвет является псевдоцветом, то область будет заполнена с помощью шаблона, состоящего из точек разного цвета. Если снова попытаться залить эту же область, то программа выполнит заливку только одного пикселя, поскольку функция ExtFloodFill() позволяет выполнить заливку области, имеющей сплошной цвет, а не псевдоцвет.



Рис. 13.12. В проекте CopyPix демонстрируется различие в быстродействии между методами Visual Basic и эквивалентными API-функциями

Текст программы настолько прост, что здесь приводится только фрагмент, обслуживающий кнопку Copy API. В программе выполняется просмотр каждого пикселя исходного (левого) изображения (с помощью двойного цикла), считывается

значение цвета пикселя, а затем это значение присваивается пикселю с теми же координатами в правом PictureBox. Фрагмент программы приведен ниже.

Программа 13.14.

Копирование пикселей с помощью API-функций

Private Sub Conmiand2_Click ()

Dim i As Integer, 3 As Integer

Dim cIrValue As Long

For i = 0 To Picturel.ScaleWidth - 1

For j = 0 To Picturel.ScaleHeight - 1

   SetPixel Picture2.hdc, i, ~j, GetPixel(Picturel.hdc, i, j)

Next

' DoEvents

Next

End Sub

Чтобы копировать изображение из окна одного элемента управления в другое, можно использовать либо метод PaintPicture, либо API-функцию BitBlt(). Они работают одинаково быстро. Если же возникает необходимость обработать отдельные пиксели, то использование двух API-функций, рассмотренных ранее, позволит значительно ускорить процесс обработки. В гл. 12 рассматривалось использование соответствующих функций для оптимизации быстродействия приложения Image, в котором большая часть времени уходила на чтение и установку значений пикселей.


Функция


BitBlt()

Функция

BitBlt() используется для выполнения операции копирования отдельных битов из области-источника изображения в область-получатель. Функция позволяет передавать прямоугольную область из контекста устройства-источника в контекст устройства-получателя. Ранее в этой главе (приложение MenuBMP) приводился пример использования функции BitBlt(). Рассмотрим эту функцию более подробно и сравним ее с методом PaintPicture, встроенным в Visual Basic.

Функция BitBlt() объявляется следующим образом.

Declare Function BitBIt Lib "gdi32" Alias "BitBIt" (ByVal _

hDestDC As Long, ByVal x As Long, ByVal у As Long, _

ByVal nWidth As Long, ByVal nHeight As Long, ByVal _

hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _

ByVal dwRop As Long) As Long

В отличие от метода PaintPicture, для вызова функции BitBlt() требуется указать все параметры. Необходимо указать начальные координаты Х и Y получателя, высоту и ширину передаваемого изображения, а также начальные координаты источника.

Прежде чем вызвать функцию BitBlt(), необходимо создать контекст устройства для объекта-источника и объекта-получателя с помощью функций CreateCompatibleDC() и CompatibleBitmapO. Если планируется использовать функцию BitBlt() для копи­рования содержимого элемента управления PictureBox, то контекстом устройства элемента управления является значение его свойства hWnd. Функцию BitBlt() можно использовать с любым контекстом устройства, даже с контекстом устройства растрового изображения, загруженного в память.

За исключением дескрипторов hDestDC

и hSrcDC, параметры функции BitBlt() такие, как и у метода PaintPicture. Они определяют координаты области-источника, содержимое которой будет скопировано (параметры источника), и координаты и размеры области-получателя, куда должны быть скопированы пиксели, образующие изображение (параметры получателя). Размеры областей источника и получателя должны быть одинаковыми. В табл. 13.7. приведены значения кодов растровых операций для параметра dwRop. Эти коды определяют, каким образом пиксели из области-источника объединяются с пикселями в области-получателе.


StretchBlt()

Для обработки растровых изображений можно воспользоваться функцией StretchBlt(). С помощью этой функции можно выполнять масштабирование (сжимать или растягивать) растровых изображений в процессе копирования. Функция StretchBlt() объявляется следующим образом.

Declare Function StretchBIt Lib "gdi32" Alias "StretchBIt" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long, _

ByVal nWidth As Long, ByVal nHeight As Long, ByVal _

hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _

ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, _

ByVal dwRop As Long) As Long

Функция StretchBlt() имеет те же параметры, что и функция BitBlt(), плюс два дополнительных параметра, которые определяют размер области-источника. С помощью функции Stretch Bit() изображение можно сжимать, растягивать и даже выворачивать наизнанку, задавая параметры с разными знаками. Коды растро­вых операций, содержащиеся в табл. 13.7, определяют способ объединения цветов пикселей области-источника и области-получателя.

Эти коды рассматривались в гл. 7. Можно запустить приложение PaintPic, рассмотренное там же, чтобы поэкспериментировать с различными кодами растровых операции. В приложении PaintPic используется метод PaintPicture, но растровые операции выполняют аналогичные преобразования.

Таблица 13.7. Коды растровых операций функций BitBlt() и StretchBlt()

Значение

Описание

BLACKNESS

Заполняет область-получатель черным цветом

DSTINVERT

Инвертирует область-получатель

MERGECOPY

Изображение определяется результатом выполнения операции побитового И над копируемым изображением и шаблоном

MERGEPAINT

Результирующее изображение определяется результатом выполнения операции побитового ИЛИ над инвертированным копируемым и областью-получателем

NOTSRCCOPY

Изображение определяется инвертированным исходным изображением

NOTSRCERASE

Результирующее изображение определяется результатом выполнения операции побитового ИЛИ над областью-источником и областью-получаталем с последующим инвертированием цвета

PATCOPY

Шаблон копируется в область получатель

PATINVERT

Изображение определяется результатом выполнения операции побитового исключающего ИЛИ над шаблоном и областью-получателем

PATPAINT

Изображение определяется результатом выполнения операции побитового ИЛИ над областью-источником и шаблоном с последующим объединением операцией ИЛИ с областью-получателем

SRCAND

Изображение определяется результатом выполнения операции побитового И над областью-источником и областью-получателем

SRCCOPY

Область-источник копируется в область-получатель без изменений

SRCERASE

Изображение определяется результатом выполнения операции побитового И над областью-источником и инвертированной областью-получателем

SRCINVERT

Изображение определяется результатом выполнения операции побитового исключающего ИЛИ над областью-источником и областью-получателем

SRCPAINT

Изображение определяется результатом выполнения операции побитового ИЛИ над областью-источником и областью-получателем

WHITNESS

Область-получатель заливается белым цветом



Гиперссылки


Тег, "оживляющий" страницы HTML — это тег <А>. Он предназначен для вставки в документ гиперссылки. Гиперссылка — это строка, по цвету отличаю­щаяся от остального текста. Когда указатель мыши находится на гиперссылке, он принимает форму руки (некоторые броузеры отображают другие указатели, но ясно, что текст под указателем является гиперссылкой). После щелчка кнопкой мыши на гиперссылке броузер запрашивает и выводит на дисплей другой документ (который находится на этом или другом сервере).

Теги <А> и </А> задают границы текста, который будет выделен как гипер-ссылка. Дополнительно необходимо задать URL документа-источника гиперссылки. Например, URL начальной страницы Sybex.

http://www.sybex.corn

URL, на который выполняется переход, задается атрибутом HREF тега <А>. Чтобы показать на экране строку "Visit the SYBEX home page" (Посещение SYBEX домашней страницы), слово SYBEX используется как гиперссылка и в документ вводится следующее.

Visit the <A HREF="http://www.sybex.com">SYBEX</A> home page

Эта строка вставляет гиперссылку в документ. Когда пользователь щелкнет на гиперссылке SYBEX, броузер покажет главную страницу заданного URL.

Примечание

Не нужно задавать имя документа в гиперссылке. Сервер предлагает страницу по умолчанию, так называемую домашнюю (home) страницу. Домашняя страница, как правило, является входом для заданного узла и содержиг гиперссылки на другие страницы, входящие в узел.

Чтобы сразу перейти на страницу, заданную на Web узле используют гипер­ссылки, подобные следующей.

View a document on<A HREF = "http://www.sybex.com/HTMLTutorial.htm">

HTML programming</A> on the Sybex site.

Большинство гиперссылок обычно указывает на другие документы, находящиеся на том же сервере. Эти гиперссылки содержат относительные

ссылки на документы. Для определения гиперссылки на документ Images htm, находящийся в одной папке с текущей страницей, используется следующий тег

Click <A HREF=".\Images.htm">here</A> to view the images.

Если файл Images.htm находится в подпапке Bitmaps текущей папки, используется следующая команда.

Click <A HREF "..\Bitmaps\ Images.htm">here</A> to view the images



HTML-страницы


Простейшим компонентом Web является HTML. Это простой язык формати­рования документов, отображаемых в Web-броузере. Важнейшая задача, выполняемая броузером — это воспроизведение документов в соответствии с HTML-тегами и отображение документов на экране.

Используя редакторы HTML и инструменты WYSIWYG (What You See Is What You Get — что видите, то и получите), можно печатать информацию в форме, пригодной для просмотра в броузере. Компания может печатать свои внутренние документы в HTML-формате и делать их доступными только в локальной сети. Преимуществ у такого подхода много, кстати. Office 97 поддерживает печать в HTML-формате. Любой документ, создаваемый в приложении Office 97, можно преобразо­вать в HTML-формат и передать на Web-сервер, в Internet или корпоративную Intranet. Можно определить место нахождения информации, осуществляя поиск по соответствующим гиперссылкам. Кроме того, информация обновляется настолько часто, насколько часто ее изменяют.

HTML состоит из тегов, форматирующих текст, которые располагаются в парах угловых скобок Теги, как правило, тоже используются парами. Первый тег подключает признак форматирования, а комплементарный ему — отключает. Например, чтобы выделить нескольких слов полужирным шрифтом, их заключают в теги <В> и </В> следующим образом.

Some<B>words</B>in the sentence are formatted in <B>bold</B>.

Конечно, не все теги столь просты. Тег <TABLE>, например, который используется для форматирования таблиц, нуждается в дополнительных тегах, таких как тег <TR>, который задает границы новой строки в таблице, и тег <TD>, который задает границы новой ячейки в строке. Теги также сопровождаются атрибутами - ключевыми словами с определенными значениями в пределах специфического тега. Тег <А> используется для выделения гиперссылки в документе, он распознает атрибут HREF Гиперссылка с домашней Web-страницей Microsoft задается так.

This <A HREF="http: //www.microsoft.com">link</A> will take you to

Microsoft's home page.

Текст между тегами <А> и </А> отмечен как гиперссылка (отображается на дисплее другим цветом и подчеркиванием). Атрибут HREF в теге <А> задает URL или адрес, на который следует переключиться при вызове этой гиперссылки.

Далее в главе приведено краткое введение в HTML (параграф "Учебник по HTML (для начинающих)").

В нем рассказывается об элементах языка, используемого в примерах следующих глав. Эта информация предназначена для программистов на VB Для полной справки по HTML, включая все теги, распознаваемые Internet Explorer, и их атрибуты, посетите следующий сайт:

http://www.microsоft.com/workshop/author/newhtml



Индексы


Индексы — это структуры, которые определяют порядок записей в таблице. Обычно данные в таблице не упорядочены. На практике, тем не менее, возникает необходимость обращаться к ним в определенном порядке. Когда печатается список имен заказчиков, необходимо печатать их в алфавитном порядке. Если печатаются почтовые этикетки, то, вероятно, необходимо печатать их в порядке почтового индекса. Тип обработки, выполняемой над базой, определяет порядок, в

котором должны быть расположены строки таблицы. Это главное для таблицы, которая будет по-разному использоваться в различных операциях.

Если запрос обуславливает различный порядок строк в таблице, то их придется реорганизовать. Но для этого требуется слишком много времени. Решение проблемы состоит в том, чтобы поддерживать маленькие таблицы, называемые индексами, которые определяют последовательность чтения записей из таблицы. Индексный файл не содержит информацию, которая появлялась бы в таблице непосредственно: только числа, определяющие порядок записей.

Предположим, пятая запись в таблице должна появиться первой, когда строки таблицы запрошены в алфавитном порядке. Первый элемент индексного файла содержит значение 5. Значит, когда из базы данных будут извлекаться строки заданной таблицы, сначала будет извлечен пятый элемент.

Примечание

В гл. 5 рассматривалось приложение, в котором использовалось свойство ItemData списка для поддержания отсортированных данных с помощью элемента управления ListBox. Индексные файлы подобны элементам свойства ItemData.

Таблица может иметь более одного индекса. Индексы всех таблиц в базе данных поддерживаются механизмом JET. Единственное, что нужно выполнить — это задать поля, на которых будет основан индекс.

В каких случаях индексация не нужна?

Когда запись модифицируется, индексы также должны модифицироваться. Это заметно увеличивает время модифицирования записи. Индексы также увеличивают занимаемый объем памяти и, следовательно, время и ресурсы, необходимые для обычного резервирования.

Поддержание множественных индексов для каждой таблицы на всякий случай — хорошая идея, однако за индексные файлы нужно платить. Вводить дополни­тельные индексы надо только в том случае, если они необходимы для соответст­вующей операции над базой данных. Слишком много индексов, особенно для очень больших таблиц, которые часто изменяются, замедлят их обработку.



Инициализация элемента управления и его свойств


Для этих целей можно использовать два события -

Initialize и InitProperties. Событие InitProperties предназначено для задания свойствам начальных значений.

До сих пор за нас это делал мастер интерфейса пользователя ActiveX. Событие Initialize может использоваться для выполнения кода инициализации, который не использует свойства. Если попытаться задать значение свойства или выполнить какое-либо действие на элементе управления (например, вывести Title на элементе управления оператором UserControl. Print "Control"), то будет выдано следующее сообщение об ошибке:

Object Required

Объект UserControl еще не существует. Именно поэтому оператор:

UserControl.Print "Control"

работает только тогда, когда находится внутри других событий, но не внутри события Initialize.

Что же можно сделать из кода этого события? Очень немного. Можно присвоить начальные значения закрытым переменным элемента управления, но нельзя обращаться к свойствам элемента управления и даже к объекту Ambient.

Больший интерес представляет событие InitProperties, которое Происходит после того, как создан элемент управления. Следует только помнить, событие Initialize имеет место каждый раз, когда происходит переключение между режимом конструирования и выполнения, но событие InitProperties за ним не следует.

Совет

Событие InitProperties происходит тогда, когда элемент управления создается и по­мещается на контейнер первый раз. После этого роль события InitProperties в цикле жизни элемента управления берет на себя событие ReadProperties. При изменении значения некоторых свойств элемента управления для Visual Basic бессмысленно сбрасывать эти свойства в их начальные значения. Вместо этого, он считывает их из Property Bag при вызове события ReadProperties.

В событии InitProperties можно вставить код инициализации, который управляет внешним видом "новорожденного" элемента управления. Например, можно определить, что случится, если пользователь помещает элемент управления на форму с помощью двойного щелчка на пиктограмме вместо перетягивания элемента управления на форму. Когда Visual Basic помещает экземпляр элемента управления на форму, он уже имеет некоторый размер (который одинаков для всех элементов управления). Если элемент управления содержит длинный заголовок, геометрическую фигуру или любой другой элемент, который должен быть виден полностью, можно откорректировать начальный размер элемента управления с помощью нескольких операторов:


UserControl.Width = 2400

UserControl.Height = 1200

При помещении элемента управления на форму с помощью двойного щелчка на его пиктограмме его начальный размер будет равен 2400 на 1200 твипов.

Объекты Extender и Ambient также доступны из процедуры InitProperties. Заголовок на элементе управления можно отобразить тем же шрифтом, что и у контейнера, следующим образом.

Set Font = Ambient.Font

UserControl.Print "FabControl"

Эти две строки отображают строку

"FabControl" шрифтом контейнера в верхнем левом углу элемента управления. Кроме того, шрифт элемента управления также будет первоначально установлен равным шрифту формы.

Примечание

Заголовок "FabControl" появится на новом экземпляре элемента управления только в том случае, если свойство AutoRedraw установлено в True. Элемент управления создается "за кулисами" и реально отображается только после того, как весь код инициа­лизации будет выполнен. Если свойство AutoRedraw элемента управления равно False, строка будет первоначально напечатана на элементе управления, но когда элемент управления отображается, эта строка не является частью растрового изобра­жения (вспомните гл. 6) и не будет перерисовываться.


Инициирование событий из кода класса


Это достаточно сложная тема и ее можно было бы благополучно пропустить. Инициирование событий из кода класса — не очень распространенная практика. Так как классы не имеют видимого интерфейса пользователя, то не существует внешних событий, реагируя на которые можно вызывать их обработчики. В следующей главе описано, как генерировать ошибки из кода элементов управления ActiveX. Элементы управления ActiveX имеют видимый интерфейс и должны реагировать на многие внешние события, такие как события мыши и клавиатуры. Как станет ясно, инициировать события из элементов управления ActiveX достаточно просто.

Совсем другая ситуация с ActiveX DLL. Классы инициируют события, осно­ванные на внутренних событиях, таких как лимит времени. Модифицируем класс CTimer так, чтобы он вызывал события Minute и Hour каждый раз, когда минута или час прошли. Доработанный проект CTimer вместе с его тестовым проектом находится в папке EVNTimer в папке этой главы на компакт-диске.

Так как класс CTimer не может отслеживать время непрерывно, необходимо ему помочь, воспользовавшись элементом управления Timer. Но модуль класса не имеет формы, и как тогда можно использовать элемент управления Timer? Мы добавим форму к проекту, но отображаться она не будет. Это будет скрытая форма с элементом управления Timer. Модуль класса будет иметь доступ к элементу Timer на форме и перехватывать его событие Timer. Это один из способов исполь­зования элемента управления ActiveX в модуле класса.

1. В окне Project Explorer выберите компонент CTimer и переименуйте его на EventTimer, как показано на рис. 15.3. Затем откройте меню Project, выберите команду Add Form (Добавить форму) и добавьте новую форму в проект модуля класса.

Примечание

Убедитесь, что новая форма появилась под компонентом

EventTimer, а не TestProject. Если форма добавилась к тестовому проекту, удалите ее и повторите процесс.

2. Откроите форму Form1 в режиме конструирования и поместите на нее экземпляр элемента управления Timer. Установите его свойство Enabled в True, а его свой ство Interval в 10000. Это значение соответствует 10 секундам. Не нужно, чтобы TimerClass тратил слишком много компьютерного времени на обработку событий Timer, так что установите большой промежуток времени ожидания.


На рис 15.3 показан проект EventTimer в среде разработки Visual Basic. Обратите внимание на компоненты в окне Project, на Form1 в окне Design и на окно Code класса. Новый класс называется EventTimerClass, а проект называется EventTimer. Открывая этот пример проекта, не забудьте выбрать проект теста и добавить ссылку на EventTimer к нему.

Наша задача - перехватить событие Timer от элемента управления. Timer внутри модуля класса и использовать его для генерирования событий Minute и Hour. Событие Minute первый раз происходит через 60 секунд после запуска таймера и каждые 60 секунд после этого. Аналогично, событие Hour происходит первый раз через 60 минут после начала работы класса и через каждые 60 минут после этого.



Рис. 15.3. Проект EventTimer подобен проекту CTimer, но он использует внутренний таймер для отсчета времени

3. Чтобы обеспечить доступ к элементу управления на другой форме, необходимо создать переменную формы в самом классе. Вставьте следующие объявления в окно программного кода класса.

Dim cFrrn As Formi

Dim WithEvents eTimer As Timer

Ключевое слово WithEvents

сообщает Visual Basic, что элемент управления должен содержать свойства, методы и события (вот почему он назван eTimer). Эти переменные оживут, если им поставить в соответствие объекты. Это должно произойти внутри события инициализации класса.

4. Вставьте следующие строки в событие Class_Initialize:

Private Sub Class_Initialize ()

Set cFrm = New Form1

Load cFrm

Set eTimer = cFrm.Timer1

End Sub

Первый оператор связывает новый экземпляр объекта Formi с переменной cFrm. Затем загружается новая форма. С этого времени реализуется доступ к элементам управления, размещенным на форме. Последняя строка делает переменную eTimer

эквивалентной элементу управления Timer1 на форме Form1. Теперь класс может иметь доступ к элементу управления Timeri на форме Formi с помощью имени eTimer, также как и Form1 имеет доступ к нему с помощью имени Timer1. Два выражения эквивалентны, но нельзя получить доступ к элементу управления Timer как Form1.Timer1 из модуля класса.



Если открыть раскрывающийся список объектов в окне программного кода модуля класса, то можно увидеть объект eTimer. Так как объектная переменная eTimer объявлена с использованием ключевого слова WithEvents,

то есть возмож­ность программировать его события. Вот почему его имя появилось в списке объектов. Выберите объект eTimer

в списке объектов и затем откройте список событий в окне Code. Появится имя события Timer. Выберите его, после чего можете программировать событие eTimer_Timer(), что эквивалентно програм­мированию события Timer1_Timer.

5. Добавьте строки программного кода 15.5 в обработчик события eTimer_Timer.

Программа 15.5. Инициирование событий из кода класса

Private Sub eTimer_Timer()

Static seconds As Long

Static minutes As Long

Static hours As Long

Dim RaiseMinutes As Boolean, RaiseHours As Boolean

If Not Counting Then Exit Sub

RaiseMinutes = False

RaiseHours = False

seconds = seconds + eTimer.Interval / 1000

If seconds = 60 Then

minutes = minutes + 1

seconds = 0

RaiseMinutes = True

If minutes = 60 Then

hours = hours + 1

minutes = 0

RaiseHours = True

End If

End If

If RaiseHours Then

RaiseEvent Hour

Elself RaiseMinutes Then

RaiseEvent Minute

End If

End Sub

Булева переменная Counting

объявлена в секции объявлений формы и служит признаком работы таймера. Если таймер остановлен, то не нужно обрабатывать событие Timer. Эта переменная устанавливается в True внутри метода StartCounting и устанавливается в False внутри метода StopCounting.

Эта подпрограмма вызывается каждые 10 секунд и увеличивает число прошедших секунд,

прибавляя к ним 10. Каждые 60 секунд она увеличивает число минут на 1, и каждые 60 минут она увеличивает число часов на 1. Если переменная minutes равна 0 (это значит, что она достигла значения 60 и сброшена в 0), должно быть инициировано событие Hour. Если это не так, то проверяется значение пере­менной seconds.

Если она равна 0, то должно быть инициировано событие Minute. В результате этого инициируются 59 последовательных событий Minute, затем событие Hour, после чего процесс повторяется. Так как нельзя выдать сразу два события, то событие Minute пропускается, когда инициируется событие Hour. Ясно, что событие Hour означает наличие и события Minute.



6. Для того чтобы надлежащим образом инициировать события, необходимо объя­вить их имена. Добавьте следующие строки в окно кода модуля класса (вне лю­бой процедуры):

Event Minute ()

Event Hour ()

Полный программный код EventTimerClass показан ниже. Обратите внимание на сходство и отличия с простым классом CTimer. Процедура Property Get и метод класса не изменились. Добавлен только код для доступа к элементу управления Timer на невидимой форме и запрограммировано событие Timer элемента Timer для инициирования соответствующих событий.

Программа 15.6. Листинг EventTimerClass

Dim cFrm As Formi

Dim WithEvents eTimer As Timer

Dim totallnterval As Double

Dim Tl As Double

Dim Counting As Boolean

Event Minute()

Event Hour()

Public Sub StartCounting ()

Tl = Time

Counting = True

End Sub

Public Sub StopCounting()

totallnterval = totallnterval + Time - Tl

Counting = False

End Sub

Property Get ElapsedTime() As Double

ElapsedTime = totallnterval

End Property

Public Sub ResetTimer()

totallnterval = 0

End Sub

Private Sub Class_Initialize ()

Set cFrm = New Formi

Load cFrm

Set eTimer = cFrm.Timer1

End Sub

Private Sub eTimer_Timer()

Static seconds As Long

Static minutes As Long

Static hours As Long

Dim RaiseMinutes As Boolean, RaiseHours As Boolean

If Not Counting Then Exit Sub

RaiseMinutes = False

RaiseHours = False

seconds = seconds + eTimer.Interval / 1000

If seconds = 60 Then

minutes = minutes + 1

seconds = 0

RaiseMinutes = True

If minutes = 60 Then

hours = hours + 1

minutes = 0

RaiseHours = True

End If

End If

If RaiseHours Then

RaiseEvent Hour

Elself RaiseMinutes Then

RaiseEvent Minute

End If

End Sub


Internet и Web-протоколы


Internet — это глобальная распределенная компьютерная сеть с общим протоколом связи TCP/IP (Transmission Control Protocol/Internet Protocol). TCP/IP - универсальный протокол, одинаково выполняющийся на всех компьютерах и операционных системах. Глубокие знания о нем для пользователя Internet необязательны.

Каждый компьютер в сети имеет уникальный адрес, например, 193.25.84.100. Каждое число, разделенное точкой — это значение в диапазоне от 0 до 255. Из этого следует, что Internet не может иметь подключенными более 4 миллиардов компью­теров (256*256*256*256). Это количество не так велико, как может показаться, потому что большая часть допустимых значений зарезервирована. Другие — переданы организациям, которые могут использовать или не использовать пре­доставленные адреса по своему усмотрению. Для предоставления большего коли­чества адресов провайдеры Internet-служб используют область адресов (т.к. не все пользователи связываются одновременно, то те же 256 адресов позволяют обслу­живать более 1000 пользователей). К сожалению, невозможно, чтобы все пользо­ватели имели уникальные IP-адреса, подобно адресам E-mail. Каждый раз при связи с провайдером конкретному компьютеру присваиваются различные IP-адреса.

Если TCP/IP предоставляет возможность любым двум компьютерам связываться между собой с помощью Internet, то зачем нужен другой протокол? HTTP является протоколом Web. В то время как TCP/IP позволяет двум компьютерам связываться на аппаратном уровне, HTTP же является языком серверов и клиентов и используется для обмена информацией. HTTP оптимизирован для запрашивания и предоставления документов HTML. Например, при обмене файлами по Internet используется FTP (File Transfer Protocol - протокол передачи файлов). Используемый протокол зависит от типа передаваемой информации. Тем не менее, все эти протоколы произошли от TCP/IP.

В следующем параграфе вы подробнее узнаете о компонентах Web и об эволюции Web-документов.



Исходный текст приложения


Messages

В обработчике события Load (Загрузка) формы создаются две объектные пере менные — OLApp, которая указывает на приложение Outlook, и mNameSpace,

которая указывает на папки Outlook. Эти переменные объявлены в разделе декларации формы:

Dim OLApp As Application

Dim mNameSpace As NameSpace

Затем в программе объявляется переменная AllContacts, которая указывает на элементы (объекты) в папке Contacts.

Dim AllContacts As Items

Программа просматривает все объекты в семействе AllContacts и добавляет имена контактов (свойство FullName) в окно элемента управления Combo 1. Значение свойства Sorted элемента управления Combol устанавливается равным True, и программа удаляет любые повторяющиеся элементы (которые могут появиться в последовательных позициях списка). Ниже приведена программа, которая обраща­ется к Outlook и устанавливает значение объектной переменной AllContacts.

Программа 14.22.

Инициализация проекта Messages

Private Sub Form_Load()

On Error GoTo OutlookNotStarted

Set OLApp - CreateObject ("Outlook Application")

On Error GoTo NoMAPINameSpace

Set mNameSpace = OLApp.GetNamespace("MAPI")

Set AllMessages = _

mNameSpace.GetDefaultFolder(olFolderInbox).Items

Set AllContacts = _

mNameSpace.GetDefaultFolder(olFolderContacts).Items

Combo1.Clear

For Each mcontact In AllContacts

Combo1.Addltem mcontact.FullName

If Combo1.List(Combo1.NewIndex)= _

Combo1.List(Combo1.NewIndex + 1) Then _

Combo1.RemoveItern Combo1.NewIndex

Next

Combo1.ListIndex = 0

Exit Sub

OutlookNotStarted:

MsgBox "Could not start Outlook"

' (He удалось запустить Outlook)

Exit Sub

NoMAPINameSpace:

MsgBox "Could not get MAPI NameSpace"

' (He удалось получить место расположения MAPI)

Exit Sub

End Sub

Фильтрация сообщений

Пользователь может выбирать имя и (или) диапазон дат для сужения области поиска. Если флажки "From this Sender (От данного отправителя)" и "Between this dates (Между этими датами)" сброшены, то щелчок на кнопке Show Selected Messages приведет к выводу в окно элемента управления List Box информации обо всех сообщениях, находящихся в папке InBox. Если установить один или оба флажка, то программа выведет информацию только о тех сообщениях, которые соответствуют указанным критериям.


Чтобы отфильтровать сообщения, следует воспользоваться методами Find и FindNext объектной переменной AllMessages. Переменная AllMessages объявлена как переменная типа Item. Объект Item поддерживает эти два метода для получения выбранных сообщений. Синтаксис метода Find имеет вид:

Items.Find(filterstring)

где filterstring — это выражение, которое задает критерий фильтрации. Метод Find возвращает объект, тип которого зависит от типа семейства Items. Если метод Find применяется к папке InBox, то будет возвращен объект Mailltem, если же этот метод применяется к папке Contacts, то будет возвращен объект Contactltem. После того как найден первый соответствующий критерию объект, оставшиеся могут быть получены вызовом метода FindNext, причем, без указания параметров.

Параметр filterstring — это строковое выражение, в котором объединены имена полей, логические операции и константы. Чтобы получить информацию о сооб­щениях, отправленных из Site Builder Network, необходимо набрать следующую строку:

"[SenderName] = "Site Builder Network"

Чтобы получить список всех сообщений, отправленных в октябре 1998 года, следует набрать следующую строку:

"[SentOn] >= ""10/01/98"" And [SentOn] <=""10/31/98""

(Последовательно набранные двойные кавычки указывают на внедренные двойные кавычки, которые вставлены в строку с помощью выражения Chr(34).)

Количество объединяемых критериев поиска зависит только от запросов поль­зователя. Имена полей для каждого типа объекта могут быть найдены в Object Browser. Выбрав желаемый объект (например, Mailltem или Contactltem), можно просмотреть список его свойств на Панели Members.

В проекте Messages при построении строки-фильтра используются значения различных элементов управления формы. Сначала проверяются значения введенных дат, а затем формируется строка фильтра:

If chkCompany.Value And Combo1.ListIndex >= 0

Then ContactName = Combo1.Text

filterString = "[SenderName] = """ & ContactName S """"



End If

If chkDate.Value Then

If filterString = "" Then

filterString = "[SentOn] >"""&_

DateFrom.Text & """ And [SentOn] <"""&_

DateTo.Text & """"

Else

filterString = filterString & " and _

[SentOn] > """ & DateFrom.Text & """ _

And [SentOn] < """ & DateTo.Text & """"

End If

End If

If filterString = "" Then

filterString = "[SentOn] > ""01/01/1980"""

End If

Обратите внимание на обилие кавычек в выражениях. Два символа двойных кавычек необходимы для вставки символа кавычки в строку. Если значение пере­менной ContactName равно "Sybex" то выражение:

"[SenderName] = """ & ContactName & """"

приведет к появлению следующей строки:

[SenderName] = "Sybex"

Переменная

filterstring

формируется медленно, в соответствии со значениями, введенными пользователем в окне формы. Если пользователь определяет имя, то оно присваивается свойству SenderName. Если пользователь определяет даты, то они присваиваются соответственно свойству SentOn.

Затем переменная filterstring

передается методу Find объекта AllMessages. Программа просматривает в цикле отфильтрованные сообщения, вызывая метод FindNext. После каждой итерации в окне элемента управления ListBox отображается отправитель очередного сообщения и тема. В это же самое время выбранные сообщения присоединяются к семейству Selectee/Messages:

Set thismessage = AllMessages.Find(filterString)

If thismessage Is Nothing Then

MsgBox "No messages sent in the specified interval"

' (В указанном интервале сообщений не было)

Else

List1.Clear

While Not thismessage Is Nothing

List1.AddItem thismessage.SenderName & _

Chr(9) & thismessage.Subject

SelectedMessages.Add thismessage

Set thismessage = AllMessages.FindNext



Wend

End If

Остальная часть программы проста. Если выполнить щелчок на объекте, нахо­дящемся в окне элемента управления ListBox, программа повторно вызывает из семейства SelectedMessages выбранный объект и отображает его основные поля в окне соответствующего элемента управления Label в нижней части экрана и, собственно, текст сообщения - в окне элемента управления TextBox (при этом его свойству Locked должно быть присвоено значение True, чтобы предотвратить редактирование сообщения). Ниже приведен текст программы обработчика собы­тия Click элемента управления ListBox.

Программа 14.23. Просмотр объекта

Message

Private Sub List1_Click()

Dim thismessage As Object

Dim MessageAttachments As Attachments

selectedEntry = Listl.Listlndex + 1

If selectedEntry < 1 Then Exit Sub

Set thismessage = SelectedMessages.Item(selectedEntry)

lblSender.Caption = " " & thismessage.SenderName

lblSent.Caption = " " & thismessage.SentOn

lblRecvd.Caption = " " & thismessage.ReceivedTime

txtBody.Text = " " & thismessage.Body

Set MessageAttachments = thismessage.Attachments

If MessageAttachments.Count = 0 Then

Command4.Enabled = False

Else

Command4.Enabled = True

End If

End Sub

Откройте проект Messages в Visual Basic, чтобы исследовать текст программы и ознакомиться с тем, как программа объединяет объекты папки Contacts и исполь­зует их для получения информации о E-mail-объектах из папки InBox. Теперь можно изменять программу с целью добавления большего количества критериев выбора или обеспечения возможности работы с различными папками (например, папкой OutBox или подпапками в папке InBox).

Предупреждение

В проекте Messages для отображения имен возможных отправителей почтового сооб­щения используется свойство контактов FullName. Если имена, использованные в папке Contacts, не соответствуют именам отправителей во входящих сообщениях, то программа не будет выбирать все сообщения, которые ожидались. Имеется много методов установления соответствия контактов и сообщений, но они требуют дополнительных затрат. Например, можно использовать адрес электронной почты каждого контакта, поскольку это общий признак, имеющийся у документа, находящегося как в папке Contacts, так и папке InBox. Но контакт может иметь несколько адресов электронной почты, поэтому следует удостовериться, что поиск выполняется по всем адресам электронной почты выбранного контакта.



VB6 в действии: проект AutoMssg

Приложение AutoMssg демонстрирует процесс создания сообщения электронной почты с помощью VB-приложения и рассылки его с помощью Outlook. Кроме того, в нем демонстрируется альтернативный способ получения информации о контактах и организации хранения этой информации. Сначала приложение оты­скивает только названия компаний и отображает их в списке Companies. Пользователь может выбрать компанию и просмотреть ее контакты, используя список Contacts. Чтобы добавить новые имена в список получателей, пользователь должен выполнить двойной щелчок в окне списка Contacts. Список получателей отсортирован, но допускает повторяющиеся пункты. Это связано с тем, что человека с фамилией, например, Смит, можно обнаружить почти в каждой второй компании, поэтому удаление повторяющихся элементов на основании информации о фамилиях полу­чателей — не самая удачная идея Вывод дополнительной информации, делающей каждый пункт списка уникальным, привел бы к загромождению экрана. Поэтому в данном проекте используется сортируемый элемент управления ListBox, в котором содержатся повторяющиеся имена, а пользователю предоставлена возможность выбора.

Программа проекта AutoMssg достаточно проста и здесь не приводится. Можно открыть проект в Visual Basic и ознакомиться с тем, как выполняется обработка сообщения.


Использование


Excel для вычисления математических выражений

В одном из предыдущих параграфов ("Проверка орфографии документов") рассматривался способ заимствования функций проверки орфографии " из Word. Теперь нечто подобное будет проделано с Excel. Excel — превосходное средство для выполнения математических операций. В то же время Visual Basic не содержит функций и методов, позволяющих выполнять вычисления математических выра­жений (заданных в виде строки — прим. ред.). Если Excel установлен на хост-компьютере, можно обратиться к нему непосредственно из приложения Visual Basic и использовать его для вычисления сложного математического выражения.

Самый простой способ вычисления математического выражения заключается в вызове метода Evaluate объекта Excel.Application. Пусть имеется инициализированная объектная переменная ExcelApp, тогда можно, например, вычислить математическое выражение:

1/cos(0.335) * cos(12.45)

Для этого следует вызвать метод Evaluate объекта ExcelApp и передать ему это выражение в виде параметра (строки):

у = ExcelApp.Evaluate "1/cos(0.335) * cos(12.45)"

Именно это происходит при выполнении щелчка на кнопке

Calculate Expression (Вычислить выражение) в форме ExcelVBA. Ниже приводится текст программы обработчика команды Calculate Expression.

Программа 14.17. Команда Calculate Expression

Private Sub bttnCalculate_Click()

Dim wSheet As Worksheet

Dim wBook As Workbook

Dim expression

StartExcel

expression = InputBox ("Enter math expression to evaluate _

i.e., 1/cos(3.45) * log (19.004)")

'(Введите вычисляемое выражение, например...)

On Error GoTo CalcError

If Trim(expression)

<> "" Then

MsgBox AppExcel.Evaluate(expression)

End If

GoTo Terminate

Exit Sub

CalcError:

MsgBox "Excel returned the following error" &   vbCrLf & _

Err.Description

' (Excel возвратил сообщение об ошибке...)

Terminate:

AppExcel.Quit

Set AppExcel = Nothing

End Sub

Программа предлагает пользователю ввести любое математическое выражение. Организовать вычисление произвольных математических выражений, используя программные средства Visual Basic затруднительно. В гл. 20 "Объекты, используемые в сценариях" будет рассматриваться использование элемента управления Script, позволяющего реализовывать вычисление математических выражений.


Visual Data Manager

Visual Data Manager (Визуальный диспетчер баз данных) - инструмент Visual Basic для проектирования баз данных. С некоторыми издержками можно использовать Visual Data Manager для модификации таблиц, обеспечения безопасности данных и экспериментов с SQL. Когда открывается существующая база данных, Visual Data Manager отображает окно базы данных со списком таблиц и свойств этой базы. На рис. 17.7 показано окно Visual Data Manager с базой данных BIBLIO, открытой в режиме разработки. Мы рассмотрим структуру базы данных BIBLIO, но сначала исследуем основные операции приложения Visual Data Manager.

Щелкните правой кнопкой мыши в окне базы данных, чтобы открыть контек­стное меню, и выберите пункт New Table. В появившемся диалоговом окне Table Structure задайте необходимые поля.

Рис. 17.7. Visual Data Manager: изменение структуры базы данных

Когда вы добавляете новое поле к таблице щелчком на кнопке Add Field, открывается диалоговое окно Add Field (рис. 17.8).

Рис. 17.8. Visual Data Manager: добавление таблиц в базу данных и полей в таблицы

Опции диалогового окна Add Field приведены в табл. 17.5. На рисунке некоторые из опций заблокированы — их нельзя прочесть. Откройте диалоговое окно Add Field и просмотрите его опции.

Таблица 17.5. Опции в диалоговом окне Add Field

Опция

Описание

Name

Имя поля

OrdinalPosition

Позиция поля в пределах списка полей

Type

Тип поля. Поле может иметь любой стандартный тип VB и два дополнительных: Binary и Memo. Поля типа Binary хранят двоичные данные — звуки и изображения. Поля Memo хранят длинные сегменты текста. Размер полей Memo не могут быть определены на этапе разработки базы данных. (Текстовые поля имеют только определенную длину )

ValidationText

Текст, отображаемый при попытке ввода недопустимых данных

Size

Размер поля в байтах

FixedField

Поле имеет фиксированную длину

VariableField

Поле имеет переменную длину

ValidationRule

Простые правила, используемые для проверки правильности вводимых значений

DefaultValue

Начальное значение, присваиваемое при создании записи

AutoIncrField

Если поле используется в качестве ключа, то нужно установить для него тип Long и проверить поле. При каждом добавлении в таблицу новой записи полю присваивается значение, на единицу больше значения последней записи

AllowZero Length

Выберите эту опцию, если пустая строка является допустимым значением

Required

Выберите эту опцию, если поле не может быть опущено. В таблице со счетами, например, идентификатор заказчика ID так же, как и дата, является необходимым полем




конструктора DataEnvironment при работе с элементом управления DataGrid

Использование конструктора DataEnvironment упрощает подключение к базе данных и создание иерархии объектов Command, сводя их к технологии "укажи и щелкни". Записи, возвращаемые объектом Command можно переместить на форму и подключить к элементам управления связанным с данными. Если переместить по несколько полей из каждого объекта Command на форму, то останется лишь написать код для перемещения по записям объекта Command 1. Каждый раз при перемещении к другому заказчику поля дочернего объекта Command будет обновляться, отражая, таким образом, итоги для выбранного заказчика.

В этом параграфе показано, как добавить поля в элемент управления DataGrid. Новая форма показана на рис. 18.9. Эта форма не является частью проекта, поэтому перечислим действия, необходимые для создания новой формы.

Рис. 18.9. Отображение полей иерархии объектов Command в элементе управления DataGrid

1. Откройте проект Report (в папке данной главы на компакт диске) и из меню Project выберите команду Add Form, чтобы добавить в проект новую форму Если вы не изменяли имя первой формы, то имя второй формы — Form2.

2. Снова откройте меню Project, выберите команду Project Properties и сделайте добавленную форму стартовой.

3. При открытых окне DataEnvironment 1 и форме Form2 щелкните правой кнопкой на объекте Command 1 и перенесите его на новую форму. После отпускания кнопки мыши появится контекстное меню с приглашением выбрать размещение полей объекта Command 1 на форме. Выберите один из вариантов.

• DataGrid - выбранные поля размещаются в элементе управления DataGnd,

•  Hierarchical FlexGrid - поля размещаются в элементе MSHFlexGrid,

•  Bound Controls - поля размещаются в отдельных элементах управления, связанных с данными (тип этих элементов определяется в поле type).

4. В открытом меню выберите элемент управления DataGrid и поместите его на форму. По умолчанию DataGrid имеет только два столбца.

5. Щелкните правой кнопкой на элементе управления DataGrid и выберите команду Edit для выполнения необходимых настроек.




конструктора DataEnvironment при работе с элементом управления MSHFIexGrid

Один из новых и самых интересных элементов управления

Visual Basic 6 -элемент управления FlexGrid (или MSHFlexGnd) Он похож на элемент управления MSFlexGnd (см гл 9), но предназначен для использования с иерархическими объектами ADO. Каждый объект автоматически размещается в своей собственной группе, причем можно развернуть и свернуть строки иерархического элемента управления FlexGrid, как узлы элемента управления TreeView. В параграфе "Проектирование иерархии объектов Command" были показаны записи, возвращенные иерархией объектов (см. рис. 18.2). Обратите внимание: имя каждой компании, отображенное в первой колонке, имеет перед собой знак "+" или "-" Этот знак показывает, что подробности о соответствующих компаниях можно показать или скрыть.

Построим форму, показанную ранее на рис. 18.2. Для этого выполните следующие действия.

1. Переименуйте форму проекта в DetailsForm и сделайте ее достаточно широкой, чтобы поместились все столбцы.

2. Откройте окно DataEnvironmentI и убедитесь, что оба окна видимы на экране.

Элемент управления MSHFlexGrid по умолчанию на панели элементов управ­ления проекта отсутствует. Он появляется при создании проекта Data. Если значок объекта MsHFlexGrid не виден, то откройте диалоговое окно Components и добавьте компонент Microsoft Hierarchical FlexGrid Control 6.0 (OLEDB). Поместите экземпляр этого компонента на форму.

3. Выберите элемент управления MSHFlexGrid и найдите его свойство DataSource в окне Properties.

4. Установите свойство DataSource в DataEnvironmentI (выберите его из раскры­вающегося списка), а свойство DataMember в Command 1 (подключив, таким образом, иерархию элементов управления из окна DataEnvironmentI к элементу Command I).

5. Щелкните правой кнопкой мыши и выберите из контекстного меню команду Retrieve Structure (Получить структуру). Все поля, перечисленные в окне DataEnvironmentI, добавятся к элементу управления в качестве заголовков. Понятно, что нет надобности отображать все поля определите, какие поля появятся в столбцах и как они будут выглядеть.




ADO

Одним из важнейших компонентов ASP является Database (База данных), представляющий собой ADO-компонент. Использование компонента Database позволяет разработать более сложные и близкие к реальным приложениям сценарии. Хотя для доступа к базам данных на сервере можно использовать и другие компоненты, большинство Web-разработчиков использует ADO-компонент.

ADO является простейшим объектом для доступа к базам данных (см. гл. 18). Его объектная модель много проще, чем у DAO или даже RDO. При этом ADO является мощным инструментом и наиболее часто применяется при создании Web-узлов, использующих активные серверные страницы. Разумеется, вы можете

использовать для этих целей компонент DAO или свои собственные компоненты ActiveX. Но целесообразнее при создании нового Web-узла использовать ADO. Этот компонент работает быстрее упомянутых выше и потребляет меньше ресурсов сервера (что важно для серверов, работающих с большой нагрузкой).



Использование гиперссылок в приложениях


Visual Basic

Одна из наиболее привлекательных возможностей Web-страниц — гиперссылки, позволяющие соединять страницы, находящиеся в World Wide Web. Ниже приведен пример использования гиперссылок, как части интерфейса пользователя приложения Visual Basic.

VB6 в действии: проект DemoPage

Приложение DemoPage показано на рис. 21.5 и находится на прилагаемом компакт-диске. Оно состоит из двух форм:

• VBForm;

• WebForm.

Основная форма - VBForm - используется для построения простых фигур методами Visual Basic WebForm воспроизводит HTML-документ, который содержит команды Visual Basic (методы для рисования). HTML-документ содержит команды и несколько гиперссылок. При активизации гиперссылки новый документ не воспроизводится. Вместо этого рисуется фигура на первой форме.

Разработаем две формы (см. рис. 21.5). Основная форма содержит вверху элемент управления Label, на котором отображается команда. Вторая форма (WebForm) -элемент управления WebBrowser, на котором воспроизводится страница Demo.htm.

После загрузки первая форма загружает вторую и воспроизводит HTML-документ на элементе управления WebBrowser. Весь код формы VBForm размещен в событии Load.

Программа 21.5. Событие Load

Private Sub Form_Load()

Dim target

target = App.Path & "\Demo.htm"

WEBForm.WebBrowser1.Navigate.target

WEBForm.Show

End Sub

Рис. 21.5. Две формы приложения DemoPage

Чтобы избежать абсолютных ссылок, предполагается, что HTML-документ (файл Demo.htm) сохранен в папке проекта. Полная страница Demo htm показана на рис. 21.6.

Рис. 21.6. Страница Demo htm в Internet Explorer

Программа 21.6. Приложение Demo Page

<HTML>

<TITLE>Demo Page</TITLE>

<BODY>

<CENTER>

<Hl>Graphics Demo Page</Hl>

</CENTER>

The hyperlinks on this page contact the VBForm  and draw various shapes on it.

<P>

<H3>Circles</H3>

The Visual Basic method for drawing circles on a     Form or

PictureBox control is called Circle and its syntax is:


<BR>

<CODE>Circle(X, Y), R</CODE>

<BR>

X and Y are the center's coordinates and R is the circle's

radius.

<BR>

<A HREF="http://127.0.0.1./demo.htm#circle">Draw A Circle</A>

<BR>

<BR>

<H3>Squares</H3>

To draw squares use the Line method, whose syntax is:

<BR>

<CODE>Line(X1, Yl) - Step(X, Y)</CODE>

<BR>

X1 and Y1 are the coordinates of the upper left corner of the

square and X and Y are the square's dimension.

<BR>

<A HREF="http://127.0.0.1./demo.htm#box">Draw A Square</A>

</BODY>

</HTML>

Приложение использует событие BeforeNavigate2 для определения активизиро­ванной гиперссылки, затем отменяет переход к этой ссылке и выполняет некоторое действие на первой форме (отображает команду на элементе управления Label и рисует фигуру). Гиперссылки могут быть неверными. Однако событие BeforeNavigate2 не наступает до тех пор, пока гиперссылка не укажет на допустимый URL.

Далее показано определение двух гиперсвязей. Адреса гиперссылок содержат информацию о виде отображаемой формы.

<A HREF="http: //127.0.0.1/demo.htm#circle">Draw A Circle</A>

<А HREF="http: //127.0.0.1/demo.htm#box">Draw A Square</A>

HTML-документ не содержит никаких указаний на имена "circle" и "box", но они и не нужны. Элемент управления WebBrowser генерирует сообщение об ошибке, но все, что действительно нужно получить - это имя точки привязки. Адрес сервера – это IP-адрес локальной машины (127.0.0.1), который является допустимым именем сервера. Посмотрим, как код события BeforeNavigate2 вызывает действия, происхо­дящие на другой форме.

Программа 21.7. Событие BeforeNavigate2

Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object,_

 URL As Variant, Flags As Variant, _

TargetFrameName As Variant, PostData As Variant, _

Headers As Variant, Cancel As Boolean)

Dim Position As Integer, Shape As String



On Error Resume Next

If UCase(Right$(URL,8)) <> "DEMO.HTM" Then Cancel = True

Position = InStr(URL, "#")

Shape = Mid$(URL, Position + 1)

If Shape = "circle" Then

VBForm.CIs

VBForm.Circle(VBForm.Width / 2, VBForm.Height / 2), _

VBForm.Height / 3

VBForm.Label1.Caption = "Circle(Width / 2, Height / 2), 

  _

   Height / 3"

End If

If Shape = "box" Then

VBForm.Cls

VBForm.Line(VBForm.Width / 4, VBForm.Height / 4) _

 -Step(VBForm.Width / 2, VBForm.Height / 2), , В VBForm.Label1.Caption = "Line(Width / 4, Height / 4) _

 -Step(Width / 4, Height / 4), , В"

End If

End Sub

Первый оператор отслеживает ошибку и указывает Visual Basic проигнорировать ошибки и продолжать выполнение со следующего оператора. Понятно, что ошибка непременно произойдет, так как обе привязки гиперссылок неправильные. Поэтому установка значения параметра Cancel в True отменяет передвижение. Условный оператор If проверяет, что другие (возможно допустимые) гиперссылки не отменены. Затем программа исследует последнюю часть адреса URL (правее символа #). Если это строка - "circle", то программа рисует окружность на форме VBForm и воспроизводит команду для рисования окружности на элементе управ­ления Label. Если строка - "box", то рисует квадрат на форме и воспроизводит соответствующую команду на Labell.

Можно изменить приложение, добавив другие возможности, поместив подробную справочную информацию в HTML-документ и включив демонстрацию примеров. Описанный подход нельзя считать элегантным, поскольку гиперссылки не стали частью интерфейса Visual Basic. Приложение, тем не менее, показывает, как включить функциональные возможности гиперссылок в приложения Visual Basic.


Использование элемента управления


Script

Элемент управления Script работает очень просто: запоминает процедуры и выполняет их в любое время. Также он вычисляет произвольные выражения и возвращает результат. Напишем несколько простых программ, в которых исполь­зуется этот элемент управления

Чтобы использовать элемент управления Script в проекте, необходимо добавить его на панель элементов управления. Для этого выполните следующие действия.

1. Откройте новый проект.

2. Щелкните правой кнопкой мыши на панели элементов управления и из контекстного меню выберите команду Components для открытия соответст­вующего диалогового окна.

3. Установите флажок Microsof Script Control 1.0 (или более новую версию, если она доступна) и щелкните на кнопке ОК.

4. Как только элемент будет добавлен на панель элементов управления, поместите его экземпляр на форму.

Перечислим наиболее важные компоненты элемента управления

Script, которые используются в наших примерах.

Метод ExecuteStatement

Этот метод выполняет один оператор и возвращает результат Он принимает единственный аргумент - оператор, который будет выполняться. Имеется оператор VBScript.

MsgBox "Programmers of the world unite!"

'(Программисты всех стран, объединяйтесь!)

Чтобы выполнить его (и вывести сообщение на экран), в метод ExecuteStatement передается строка statement, задающая этот оператор.

statement =

"MsgBox " & Chr(34) &

"Программисты всех стран, объединяйтесь!" & Chr(34)

ScriptControll.ExecuteStatement statement

Выражение Chr(34) добавляет двойные кавычки в строковую переменную. Другой подход — использовать две двойные кавычки подряд и объединить два оператора в один.

ScriptControll.ExecuteStatement _

"MsgBox "" Welcome to VBScript!"""

Возможности метода ExecuteStatement

не ограничиваются вызовом одной функции. VBScript позволяет поместить несколько операторов в одну строку, разделяя их двоеточием. Вот небольшой код на VBScript (пригодный для VB).

X=InputBox ("Enter a value from 0 to 5")


WebBrowser

Элемент управления WebBrowser предназначен для создания собственных броузеров, так как он обладает всеми функциональными возможностями просмотра, присущими Internet Explorer. Можно задействовать кнопки Back и Forward, управлять доступом пользователя к узлам и многое другое.

Конечно же, элемент управления WebBrowser не обладает всеми возможностями Internet Explorer. Наиболее значительное ограничение — невозможность доступа к воспроизводимому документу и сохранение HTML-документа из кода программы. Хотя пользователь может открыть контекстное меню документа и выбрать View Source.

Рассмотрим два приложения, которые демонстрируют использование элемента управления WebBrowser в приложениях Visual Basic. Первое приложение является Web-броузером, во втором приложении показано, как использовать HTML-документ в приложениях Visual Basic и добавлять гипертекстовые ссылки.

VB6 в действии: пользовательский Web-броузер

На рис. 21.4 продемонстрирован интересный подход к построению броузеров. Форма содержит элемент управления TabStrip с несколькими страницами, отобра­жающими различные URL - локальные файлы или страницы с удаленных серверов. Можно использовать локальные файлы подсказки для вашего приложения или подсое­динить пользователей приложения к Web-серверу для обеспечения их оперативной информацией.

Чтобы создать приложение SuperBrowser, выполните следующие действия.

1. Откройте новый Standart ЕХЕ-проект и добавьте элемент управления TabStrip к форме. Увеличьте размер формы, и растяните элемент управления TabStrip, чтобы он занял как можно большую часть формы. Можно оставить немного места для нескольких кнопок, например, Back и Forward (которые в этом примере не используются).

2. Если панель элементов управления не содержит значок WebBrowser, то добавьте его, используя диалоговое окно Components (выберите элемент управления Internet Controls из списка доступных элементов управления). Придется также добавить элемент управления TabStrip к панели элементов управления, используя диалоговое окно Component.




Rates

Перед исследованием кода элемента управления, рассмотрим его использование в тестовом проекте. Тестовый проект состоит из одиночной формы, которая содержит образец элемента управления Rates и кнопку Get Rates. Когда кнопка нажата, элемент управления связывается с Web-сервером и запрашивает курсы обмена различных валют. Код обработчика щелчка на кнопке Get Rates вызывает метод DownLoadRates, передавая URL текстового файла в качестве параметра.

Private Sub bttnGetRates_Click()

RateControll.DownloadRates ("http://127.0.0.I/rates.txt")

End Sub

Файл Rates.txt, используемый в этом примере, находится в корневой папке Web-сервера, который установлен на компьютере. Если на используемом компьютере или другом компьютере в локальной вычислительной сети установлен Internet Information Server или Personal Web Server, то необходимо поместить туда файл Rates.txt и соединится с сервером для его загрузки. Адрес 127.0.0.1 является адресом локальной машины. Если Web-сервер отсутствует, то чтобы узнать, как записать файл на сервер провайдера интернета смотрите инструкции, приведенные в пара­графе " Тестирование элемента управления Rates".

Примечание

Не пытайтесь пока проверять проект Rates. Этот элемент управления должен найти информацию на HTTP-сервере: необходимо обеспечить наличие URL для метода DownloadRates. В параграфе " Тестирование элемента управления Rates"

в конце главы показано, как поместить файл Rates.txt на сервере. Выполните инструкции, приведенные в этом параграфе, а затем запустите проект Rates.



Использование элементов управления


ActiveX в других проектах

Добавляя тестовый проект в проект элемента управления, можно конструировать и испытывать элемент управления в одной и той же среде. Это, действительно, очень удобно, однако в таком виде элемент управления не может использоваться в других проектах. После запуска другого экземпляра Visual Basic и попытки добавить созданный элемент управления в панель элементов управления, элемент FLEXLabel в диалоговом окне Component просто не виден. Обычный проект видит только те компоненты, которые были зарегистрированы в системе.

Чтобы зарегистрировать созданный элемент управления, необходимо создать соответствующий ОСХ-файл. Выберите команду Make FIxLabel ocx меню File ОСХ-файл - это все, что необходимо, чтобы включать элемент управления в другие проекты ОСХ-файлы могут быть расположены в любом месте на диске, но чаще всего находятся в подпапке System папки Windows. Можно создать ОСХ-файл в той же самой папке, в которой находится проект. При создании ОСХ-файла Visual Basic регистрирует его в системном реестре. Следовательно, не следует в дальнейшем перемещать созданный ОСХ-файл. Для того чтобы получить возможность исполь­зования элемента управления в новых проектах, выполните следующие действия.

1. Откройте новый Standard ЕХЕ-проект и добавьте новый элемент управления в панель элементов управления.

2. Щелкните правой кнопкой на панели элементов управления и выберите из поя­вившегося меню пункт Components для вывода одноименного диалогового окна.

3. Отметьте флажок FLEXLABEL и щелкните на кнопке ОК. На панели элементов управления появится пиктограмма специального элемента управления. Обратите внимание, что имя элемента управления то же, что и имя проекта.

Если, используя эту пиктограмму, поместить элемент управления FLEXLabel на форму. Visual Basic автоматически назовет его Label3Dl (если это первый элемент управления на форме; второй будет назван Label3D2 и т. д.).

Созданный элемент управления был зарегистрирован в системном реестре на данном компьютере, но как быть с другими компьютерами? При распространении приложения, которое использует элемент управления, он должен быть установлен на компьютере до того, как приложение сможет его использовать. Для инсталляции элементов управления на других компьютерах можно использовать утилиту Regsvr32, передавая ей имя ОСХ-файла в качестве параметра. Предполагается, что файл FLXLABEL.OCX скопирован в подпапку System папки Windows. Используйте следующую DOS-команду для установки элемента управления на компьютер:

REGSVR32 FLXLABEL.OCX

Если ОСХ-файл располагается в иной папке, перейдите в эту папку и выпол­ните следующую команду:

С:\WINDOWS\SYSTEM\REGSVR32 FLXLABEL.OCX

Чтобы удалить элемент управления из реестра Windows, используйте утилиту REGSVR32 с ключом /U. Следующая команда удаляет элемент управления FLXLabel из реестра:

С:\WINDOWS\SYSTEM\REGSVR32 FLXLABEL.OCX /U



Использование конструктора


ActiveX DataReport

Имеется еще одна важная операция, выполняемая при создании приложений для работы с базами данных - генерация отчетов. Генерация иерархических отчетов с вычислением итогов (например, отчетов для данных, возвращаемых иерархией объектов Command, созданных в предыдущем параграфе) и их распечатка - одна из основных задач разработчика. Понятно, что хотелось бы работать с утилитой, которая генерирует для нас отчеты только с помощью мыши и позволяет корректно их распечатывать. Второй конструктор ActiveX в Visual Basic 6 — DataReport Designer — предназначен именно для этого. Посмотрим, как конструктор DataReport создает отчет, основанный на иерархии объектов Command. Выполните следующие действия.

1. Сделайте активным проект Report и дважды щелкните на DataReport Designer в окне проводника проекта, чтобы открыть его. На экране появится шаблон отчета, который не соответствует созданной структуре иерархии объектов Command.

2. Откройте окно DataReport, чтобы подключить объект DataReport к объекту Command 1.

3. В окне Properties найдите свойства DataSource и DataMember и установите их в DataEnvironment 1 и Command-1 соответственно.

4. Щелкните правой кнопкой на объекте DataReport 1 и из контекстного меню выберите команду Retrieve Structure.

Структура иерархии объектов Command отобразится на объекте DataReport (рис. 18.11).

Рис. 18.11. Объект DataReport после чтения структуры объектов Commandl

Полученный шаблон содержит отчет и заголовок страницы. Затем следуют заголовки двух групп для объектов Command 1 и Command2. Как видно, деталями отчета являются поля объекта Commands. После секции Detail следуют соответству­ющие нижние колонтитулы.

Оставьте заголовок отчета (Report header) пустым (позже можно поместить в него любые строки) и выполните следующие действия.

1. Чтобы удалить место, в котором обычно размещается Report header (даже если он пуст), щелкните на серой панели под секцией Report header (панель Page header), чтобы выделить ее.

2. Перемещайте указатель у верхней части панели, пока он не примет форму двойной стрелки.


3. Нажмите кнопку мыши и переместите панель Page header вверх, чтобы удалить зазор между панелями.

Примечание

Секция Page header содержит номера страниц (и, возможно, другие пункты).

4. Чтобы показать в этом заголовке номер текущей страницы, щелкните правой кнопкой мыши в области Page header (пустое место под панелью с заголовком "Page Header").

5. Из контекстного меню выберите пункт Insert Control, чтобы открыть следующее подменю (рис. 18.12).



Рис. 18.12. Элементы управления, добавляемые в объект Report

6. Добавьте элемент управления Label, а затем - элемент управления Current Page Number.

На рис. 18.13 показан объект Report на последней стадии разработки. Можете использовать этот рисунок в качестве руководства в процессе конструирования вашего отчета.

Элемент управления Label, добавленный в отчет, напоминает стандартный элемент управления Label. Называется он rptLabel,

и у него не так много свойств, как у обычного элемента управления Label. Но их достаточно для того, чтобы определить его внешний вид в отчете. Можно перемещать его с помощью мыши, изменять размер и задавать основные свойства (Font и Caption), используя окно Properties. Это справедливо и для элемента управления Current Page Number. Можно задавать его свойства Font, ForeColor и Caption. По умолчанию Caption установлен в %р — специ­альное значение, указывающее Visual Basic подставить номер текущей страницы.



Рис. 18.13. Проектирование отчета с помощью конструктора DataReport (окончательный вид отчета показан на рис. 18.14)

Первый заголовок группы (Group Header), соответствует полям объекта Command 1. Очевидно, что здесь необходимо поместить название компании (контактное имя и номер телефона) или другое поле, уникальное для каждого заказчика. Здесь же находятся итоговые поля TotalOrders и CustomerTotal.

Выполните следующие действия.

1. Поместите два больших элемента управления Label в область первого заголовка группы и установите их заголовки соответственно в Total Orders и Customer Total.



2. Откройте конструктор DataEnvironment1 и перетащите поля TotalOrders и CustomerTotal, расположенные под объектом Command 1, к двум элементам Label на первом заголовке группы. Выберите подходящий шрифт и выровняйте их.

Следующий заголовок соответствует объекту Command2. Этот объект содержит идентификаторы счетов (поле OrderID) и их итоги (поле OrderTotal). Разместите эти два поля в области второго заголовка группы. Переместите соответствующие поля под объектом Command2 в конструкторе DataEnvironmentI в область второго заголовка.

Если хотите печатать заголовки столбцов для этих двух полей, то поместите их в предыдущий заголовок группы (иначе они будут появляться перед каждым счетом). Разместите два других элемента управления Label и установите их заголовки соответственно в "Order ID" и "Order Total" (см. рис. 18.13).

Перейдем к секции Detail (Детали). Здесь должны быть поля объекта Command3 (этот объект использовался для вычисления итогов), но пока поля объекта Commands нас не интересуют. Поэтому в нашем отчете не будет секции Detail. Второй заголовок группы представляет собой суть секции Detail отчета (эта ситуация достаточно типична при разработке отчетов). Чтобы поэкспериментировать с секцией Detail, поместите в нее подробные сведения о счетах.

Установите высоту секции Detail в 0, передвинув разделитель этой секции вверх. В этом примере мы не используем нижние колонтитулы, но их можно настроить так же, как и заголовки. Вообще, можно поместить любой элемент управления, используя меню Insert, и манипулировать его свойствами с помощью окна Properties.

Чтобы вывести отчет на экран, вызовите метод Show объекта DataReportl. Разместите на форме командную кнопку, назовите ее Report

и введите код обра­ботчика ее события Click.

Private Sub Command1_Click()

DataReport1.Show

End Sub

Запустите проект снова, нажмите кнопку Report и вы увидите разработанный отчет в отдельном окне на экране (рис. 18.14). Две кнопки вверху окна DataReport позволяют распечатать его на любом принтере или экспортировать его в текстовый формат или формат HTML. Практически, конструктор DataReport сделал всю работу. Наиболее важный аспект этого процесса состоит в том, что распечатка отчета создавалась без написания какого-либо кода.



Рис. 18.14. Окончательный вид отчета сгенерирован конструктором ActiveX DataReport


Использование мастера страницы свойств


Для использования мастера страницы свойств выполните следующие действия.

1. Откройте проект FLEXLabel, если он еще не активен.

2. Выберите команду Property Page Wizard в меню Add-Ins, чтобы открыть диалоговое окно Add Property Page.

3. Выберите VB Property Page Wizard.

Мастер страницы свойств поможет по шагам создать страницы свойств элемента управления.

Введение

Это вводное окно, которое, в дальнейшем, можно пропускать, отметив флажок Skip This Screen in Future.

Выбор страниц свойств

В этом окне можно выбрать, какие из стандартных страниц свойств нужны конструируемому элементу управления. Сюда входят следующие страницы.

•  StandardFont. Позволяет устанавливать шрифт.

•  StandardPicture. Позволяет устанавливать свойства изображения.

•  StandardColor. Позволяет устанавливать цвет.

Для нашего элемента управления нужна страница

StandardColor, плюс специ­альная страница, которую можно добавить, нажав кнопку Add. Мастер при этом запрашивает имя новой страницы. Введите TextProperties и нажмите кнопку Next.

Понятно, почему мастер выбрал страницу StandardColor? Элемент управления имеет свойства Backcolor и ForeColor, которые устанавливаются через страницу свойств StandardColor. Если страница свойств для этих свойств не нужна, очистите флажок, который стоит перед именем страницы свойств. Но нам она нужна для установки цвета, поэтому оставьте эту страницу отмеченной. Кроме того, можно также переименовывать страницы свойств с помощью кнопки Rename.

Связывание свойств со страницами свойств

В этом окне задаются свойства, которые необходимо отобразить на каждой странице свойств. Мастер уже связал свойства цвета со страницей StandardColor, свойства шрифтов со страницей StandardFont, а свойство Picture со страницей StandardPicture. Но специальные свойства не были связаны ни с одной страницей, потому что мастер не знает, кому они принадлежат. Добавить свойство Caption к странице Text можно следующим образом.

1. Выберите вкладку Text.

2. Выберите свойство Caption из списка слева и нажмите кнопку с одиночной стрелкой вправо, чтобы добавить свойство к странице свойств Text


3. Щелкните на кнопке Next, чтобы перейти на последнюю страницу мастера, и затем щелкните на кнопке Finish.

При более тщательном рассмотрении этого окна мастера можно обратить вни­мание на некоторую странность. В списке доступных свойств появились не все специальные свойства. Вместо этого появились имена других свойств. Мастер не может обрабатывать свойства нестандартного типа. TextAlignment и Effect — специ­альные (пользовательские) типы данных (перечислимые типы AJign и Effects, кото­рые определены в коде), поэтому они пропущены. Если нужна страница свойств, на которой разработчик может задавать вид элемента управления, нужно добавить свойства TextAlignment и Effect на страницу Text. К сожалению, нет возможности добавить эти свойства посредством мастера. Придется сделать это вручную.

Но сначала давайте посмотрим, что сделал для нас мастер. Выполните следующие действия.

1. Переключитесь на тестовую форму и щелкните правой кнопкой мыши на элементе управления FLEXLabel.

2. Из меню выберите Properties (Свойства), чтобы просмотреть две страницы свойств, показанные на рис. 16.10 и 16.11.



Рис. 16.10. Страница свойства Color элемента управления FLEXLabel



Рис. 16.11. Страница свойства Text Properties элемента управления FLEXLabel

Страница Color выглядит хорошо, а вот страница Text Properties нуждается в улучшении. Мастер только поместил на страницу элемент Label и элемент TextBox, a теперь необходимо помимо настройки этих элементов написать соответствующий код.

Вкладка Color имеет список свойств, который содержит имена свойств, связанных с цветом. Если создать еще несколько таких свойств, то они появятся на этой же странице. Чтобы назначить новое значение свойству, сделайте одно из двух:

•  выберите свойство, а затем выберите стандартный цвет из палитры Windows, или

•  создайте свой цвет нажатием кнопки Edit Custom Color.

Новый цвет появляется перед именем свойства в списке. При нажатии кнопки Apply соответствующая часть элемента управления будет перерисована в соответствии с новой установкой. Страница Text Properties позволяет определять значение свойства Caption, вводя значение в элемент управления TextBox. Поэкспериментируйте с другими вкладками страниц свойств, чтобы посмотреть, как они себя ведут.



В окно Project мастер добавил другую папку - Property Pages. Эта новая папка содержит файл свойств Caption. Выполните на ней двойной щелчок и страницы откроются в режиме конструирования. Обратите внимание, что кнопки OK, Cancel и Apply не являются частью формы. Они принадлежат элементу управления TabStrip, который отображает страницы свойств во время выполнения (этот элемент управления не доступен и не может быть даже настроен). Кроме того, нет формы для свойств Font, Color и Picture. Это стандартные страницы свойств и они управляются Visual Basic. Модифицировать страницы, сгенерированные мастером, нельзя, однако можно создать свою страницу для выбора цвета, если уж не нравится имеющаяся.

Итак, исследуем код, созданный мастером для страницы свойств CaptionProperties.

Программа 16.10. Станица свойств CaptionProperties

Private Sub txtCaption_Change()

Changed =

True

End Sub

Private Sub PropertyPage_ApplyChanges ()

SelectedControls(0).Caption = txtCaption.Text

End Sub

Private Sub PropertyPage_SelectionChanged ()

txtCaption.Text = SelectedControls(0).Caption

End Sub

Подпрограмма txtCaption_Change() вызывается каждый раз, когда пользователь что-либо печатает в поле txtCaption. Устанавливая переменную Changed в Тruе, код разблокирует кнопку Apply (которая заблокирована до тех пор, пока свойство Caption не изменится). Visual Basic использует свойство Changed для определения момента разблокирования кнопки Apply.

Конечно, новые установки не применяются к элементу управления автоматически. Код, который фактически производит изменения, должен быть вставлен в обработчик события PropertyPages_ApplyChanges, которое вызывается каждый раз, когда нажимается кнопка Apply. Это событие и модифицирует свойства элемента управления. Поскольку страница свойств является отдельной формой, она не может знать, какой элемент управления выбран в данный момент (поскольку на форме может присутствовать несколько экземпляров одного элемента управления). Из-за этого для доступа к выбранному элементу управления код использует объект SelectedControls() - семейство, которое представляет собой все выбранные элементы управления на форме. Заметим, что элемент семейства с индексом 0 является пер­вым выбранным элементом управления.

И, наконец, событие PropertyPage_SelectionChanged() вызывается всякий раз, когда пользователь выбирает другую вкладку страницы свойств. Это хорошее место для размещения кода инициализации. Код обработчика процедуры PropertyPage_SelectionChanged() присваивает текущие установки свойству Caption выбранного элемента управления элементу TextBox, в котором пользователю предлагается ввести новое значение свойства.


Использование метода


HitTest

Для работы с различными элементами управления можно использовать метод HitTest, который позволяет обнаруживать объект, заданный координатами точки. Этот метод использовался в проекте LVWDemo (см. гл. 8). Сейчас же рассмотрим метод HitTest подробнее, чтобы увидеть, как он использован совместно с функцией GetCursorPos().

Метод HitTest применяется только по отношению к некоторым элементам управления, являющимся контейнерами. Например, объект

ListView может содер­жать несколько объектов Listltem. Когда пользователь выполняет двойной щелчок в окне объекта ListView, вызывается событие DblClick,

но с его помощью нельзя определить место, где был выполнен щелчок. Чтобы выяснять, на каком именно объекте был выполнен двойной щелчок, следует использовать функцию GetCursorPos(). Она позволяет определить координаты указателя и передать их методу HitTest, который возвратит ссылку на объект, расположенный в указанном месте.

Вернемся к проекту LVWDemo и рассмотрим обработчик события DblClick в объекте ListView. Окно объекта ListView заполнено названиями компаний и связанными с ними данными. Поскольку эти объекты отображаются в виде значков (рис. 13.6), то нужно определить, на каком именно значке был выполнен щелчок (или двойной щелчок). Об отслеживании одиночного щелчка "беспокоится" обработчик события ItemClick,

генерирующий соответствующее сообщение. Обра­ботчик события ItemClick объявляется следующим образом.

Private Sub ListViewl_ItemClick(ByVal Item As ComctLib.Listltem)

Однако обработчик события ItemDblClick отсутствует, вместо него объявлен обработчик события DblClick.

Private Sub ListViewl_DblClick()

Хотя обработчик события DblClick не позволяет получить сообщение об объекте, на котором он выполнен, обычной практикой является использование элемента управления ListView для реакции на двойной щелчок. При этом программа может косвенно обнаруживать объект, на котором выполнен двойной щелчок с помощью функции GetCursorPos() и метода HitTest. Чтобы определить координаты точки, в которой был выполнен двойной щелчок, выполните следующее.




Рис. 13.6. Приложение LVWDemo использование функции GetCursorPos() для получения информации об объекте, на котором выполнен щелчок.

Сначала объявите в модуле функцию GetCursorPos() и структуру данных POINTAPI.

Type POINTAPI

х As Long

у As Long

End Type

Declare Function GetCursorPos Lib "user32" Alias "GetCursorPos" _

(IpPoint As POINTAPI) As Long

В обработчике события DblClick необходимо организовать вызов функции GetCursorPosQ, чтобы выяснить координаты указателя в момент выполнения двой­ного щелчка.

GetCursorPos dPoint

Членами структуры dPoint являются координаты Х и Y указателя мыши, выраженные в пикселях в системе координат экрана. Другими словами, если функция GetCursorPosQ вызывается из обработчика события DblClick элемента управления ListView, то в результате она возвращает пару координат. Если после этого пользователь переместит форму (приложение) в другое место экрана, а затем выполнит двойной щелчок на том же значке, то координаты точки, в которой выполняется щелчок, изменятся. Следовательно, необходимо предусмотреть проце­дуру преобразования координат экрана в координаты окна приложения. Для этого нужно вычесть значения свойств Left и Тор окна приложения и элемента управления ListView в этом окне из значений соответствующих координат, возвращаемых функцией GetCursorPos().

X = dPoint.X - Me.Left – ListViewl.Left

Y = dPoint Y - Me.Top – ListViewl.Top

Однако данные действия не вполне корректны, поскольку координаты dPoint. Х и dPoint.Y заданы в пикселях, а все остальные координаты - в твипах (twips). Перед нахождением разности все координаты необходимо преобразовать в пиксели с помощью методов ScaleX и ScaleY. Ниже приведены выражения, позволяющие преобразовать экранные координаты во внутренние координаты элемента управ­ления ListView

Х = dPoint.X - ScaleX(Me.Left + ListViewl.Left,

vbTwips, vbPixels) Y = dPoint.

Y = ScaleY(Me.Top + ListViewl.Top, _

vbTwips, vbPixels)

где Х и Y - координаты указателя в пикселях в момент выполнения двойного щелчка. Координаты (0, 0) соответствуют левому верхнему углу окна приложения. Значения переменных Х и Y должны быть переданы методу HitTest, возвращаю­щему ссылку на объект, на котором выполнен двойной щелчок. Однако для обра­щения к методу HitTest требуется, чтобы координаты были определены в твипах. Вызов метода HitTest показан ниже.



Set LItem = ListViewl.HitTest(ScaleX(X, vbPixels, vbTwips),

ScaleY(Y, vbPixels, vbTwips))

Значения переменных Х и Y сначала преобразуются в твипы, а затем переда­ются методу HitTest. В результате возвращается хранящаяся в переменной LItem ссылка на объект, на котором выполнен двойной щелчок. Эта переменная объяв­ляется как Listitem.

Dim LItem As Listltem

Используя переменную LItem, можно получить доступ к свойствам объекта, на котором был выполнен двойной щелчок. Например, можно организовать подсветку этого элемента непосредственно из программы

LItem.Selected = True

или организовать чтение элементов нижнего уровня как членов семейства.

LItem.ListSubItems

Если двойной щелчок выполнен в пределах элемента управления ListView в месте, не содержащем объектов, то переменная LItem получит значение Nothing. В этом случае попытка обратиться к свойствам элемента управления приведет к ошибке выполнения. Чтобы избежать этого, используйте оператор

On Error Resume Next

и организуйте проверку значения переменной LItem.

On Error Resume Next

Set LItem = ListViewl.HitTest(ScaleX(X, vbPixels, vbTwips), _

ScaleY(Y, vbPixels, vbTwips))

If LItem Is Nothing Then Exit Sub

(набор операторов, обеспечивающих доступ к значениям свойств LItem)

Ниже приведен текст программы обработчика события

DblClick элемента управ­ления ListView. Этот фрагмент программы (без операторов, с помощью которых выполняется обработка членов переменной LItem} можно использовать непосред­ственно в пользовательской программе, если требуется организовать реагирование программы на двойной щелчок на ListView.

Программа 13.8. Обработчик события DblClick элемента управления ListView

Private Sub ListViewl_DblClick()

Dim dPoint As POINTAPI

Dim LItem As Listltem

GetCursorPos dPoint

X = dPoint.X - ScaleX(Me.Left + ListViewl.Left, vbTwips,

vbPixels)

Y = dPoint.Y - ScaleY(Me.Top + ListViewl.Top, vbTwips, vbPixels)

On Error Resume Next

Set LItem = ListViewl.HitTest(ScaleX(X, vbPixels, vbTwips),     _



ScaleY(Y, vbPixels, vbTwips))

If LItem Is Nothing Then Exit Sub

If ListViewl.View = Ivwicon Or ListViewl.View = IvwSmalllcon Then

LItem.Selected = True

msg = LItem.Text & vbCrLf

For i = 1 To LItem.ListSubItems.Count

msg = msg & "   " & LItem.ListSubItems(i).Text & vbCrLf

Next

MsgBox msg

End If

End Sub

Приведенный пример — не единственный способ использования метода HitTest (и даже не самый типичный). Впрочем, этот пример нетривиален, именно поэтому он столь подробно рассматривался. Этот метод был разработан в основном для обработки события DragDrop. Обработчик события DragDrop сообщает координаты точки, в которую помещен объект. Если объект операции перенести-и-оставить (drag-and-drop) находится в окнах элементов управления типа ListView или TreeView, то требуется знать элемент управления, на который был перемещен объект Ниже приведено объявление обработчика события DragDrop.

Private Sub TreeViewl _ DragDrop(Source As Control, x As Single,_

у As Single)

Поскольку координаты точки, в которую перенесен объект, известны, их можно передать в метод HitTest. чтобы выяснить, на какой из элементов управления был перенесен объект. Заметьте: при этом не требуется преобразовывать или пересчи­тывать значения координат, поскольку обработчик события DragDrop возвращает их значения, выраженные во внутренней системе координат (в твипах).


Использование модуля класса


Реализуем этот же проект, но с использованием модуля класса. Модуль класса полностью скрывает детали реализации. Он предоставляет через свой интерфейс некоторые функциональные возможности, и разработчику больше не нужно просматривать или редактировать его исходный программный код.

Предупреждение

При попытке открыть проекты примеров с компакт-диска (или из папки диска, куда они были скопированы), появится сообщение об ошибке, означающее, что проект ссылается на компонент, который недоступен. Каждый проект из этой главы создает новый класс, который неизвестен системе. Проигнорируйте это сообщение, откройте проект и добавьте к нему ссылку на класс.

Сохраните существующий проект и начните новый (это будет проект CTIMER из папки для этой главы на компакт-диске). Чтобы создать новый класс сделайте следующее:

1. В диалоговом окне New Project выберите ActiveX DLL. Visual Basic добавит папку Class Modules в окно Project Explorer, а в нее - модуль класса. Модуль класса называется по умолчанию Class 1. Проект ActiveX DLL не имеет форм.

2.  Измените свойство Name модуля класса на CTimer.

3.  Для нового компонента будет отображено окно Code, так как модуль класса не        имеет визуального интерфейса.

4. Введите строки программного кода 15.3 в окно Code модуля классов.

Программа 15.3. Код класса CTimer

Dim totallnterval As Double

Dim Tl As Double

Public Sub StartCounting ()

Tl = Time

End Sub

Public Sub StopCounting()

totallnterval = totallnterval + Time - Tl

End Sub

Property Get ElapsedTime () As Double

ElapsedTime = totallnterval

End Property

Public Sub ResetTimer()

totallnterval - 0

End Sub

Содержимое модуля классов очень напоминает содержимое обычного модуля, но не имеет общедоступных переменных. Переменная totallnterval не должна быть доступной из какой-либо процедуры за пределами модуля класса. Ее значение может быть прочитано только с использованием процедуры ElapsedTime(). Необходимо отметить, что это специальный тип процедуры, называемый Property Get (Получить свойство). Каждый раз, когда приложение пытается прочитать значение переменной totallnterval, вызывается процедура ElapsedTime(). Ее код считывает значение локальной переменной totallnterval


и назначает его процедуре ElapsedTime(). Затем это значение передается в вызывающее приложение.

Когда приложение пытается установить значение свойства, вызывается похожая процедура

Property Let (Установить свойство).

Рассматриваемый класс не имеет свойств, которые можно установить таким образом, и в нем нет процедур Property Let. Обе процедуры (Property Let и Property Get) обсуждаются далее после рассмот­рения небольшого примера. Они действуют подобно буферам обмена между классом и приложением, которое его использует. Поэтому приложение не может установить значение свойства непосредственно.

Примечание

Класс CTimer не предоставляет процедуру Property Let для свойства totallnterval. Как результат, это свойство доступно только для чтения.

Методы модуля класса идентичны методам модуля. Добавление метода к классу является таким же простым, как объявление общедоступной функции или процедуры. Любая процедура может стать методом класса, если она определена в модуле класса и объявлена как Public.

Примечание

Некоторые члены класса могут быть реализованы как методы или как свойства, и не всегда легко сказать, какой путь выбрать. К счастью, это не является настолько важным. Необходимо пытаться придерживаться парадигмы встроенных элементов управления или элементов управления "от третьего лица". Например, если класс явля­ется элементом управления ActiveX, то член, который хотелось бы видеть в окне Properties, должен быть реализован как свойство (обратное верно не всегда). Методы должны соответствовать действиям, а свойства — атрибутам. Схема наименований также важна. Имя, имеющее вид GetElapsedTime, наводит на мысль о методе, а имя ElapsedTime - ближе к свойству.


Использование набора записей


В ASP-приложениях Recordset (Набор записей) используется для извлечения и отображения информации, а не изменения содержимого базы данных. Объект Recordset имеет два важных свойства:

• CursorType, указывающий на тип курсора (cursor), используемого с данным объектом;

• LockType, задающий тип блокировки при редактировании набора записей.

Описание этих свойств смотрите в гл. 18. Для перемещения по набору записей используются методы MoveNext (Перейти к следующей), MovePrevious (Перейти к предыдущей), MoveFirst (Перейти к первой), MoveLast (Перейти к последней). Можно создавать закладки для определенных записей, чтобы обращаться к ним незамедлительно. Для отображения всех записей данного набора используется следующий цикл.

<%

Do While Not SelRecords.EOF

{обработка полей}

SelRecords.MoveNext Loop

%>

Чтобы получить доступ к полям Recordset, используйте имя набора и поля или порядковый номер поля в наборе. Например, для доступа к полю ProductName набора записей SelRecords используется такое выражение.

SelRecords ("ProductName")

Если поле ProductName является первым (это определяется предложением SELECT SQL-оператора), то используйте следующее выражение.

SelRecords(1)

Информации, предлагаемой в этой главе, достаточно для построения интерактивных ASP-приложений, которым доступны базы данных на сервере и отображающих выбранные записи. Далее мы покажем, как использовать эти объекты при построении активных серверных страниц. В наших примерах используется база данных NWIND и предполагается, что источник данных для нее настроен надлежащим образом.



Использование операций перетащить-и-опустить в


OLE

В гл. 4 рассматривалось программирование операций перетащить-и-опустить. С их помощью пользователь может "взять" элемент управления в форме и "положить" его в окно другого элемента управления (находящегося на той же или другой форме). Объект-получатель "знает", когда на него опушен другой объект, а его реакция на событие программируется. И все же разработчику необходимо добавить несколько строк в обработчик события Drag Drop.

Во многих приложениях допускается перетаскивание не только элементов управления, но и документов или их частей. Например, можно выделить блок ячеек рабочего листа Excel и перенести его в документ Word. Если для этой операции используется правая кнопка мыши, то можно выполнить связывание данных, содержащихся в документе-источнике, с документом-получателем. Эта операция называется OLE-операцией, так как она выполнима только между приложениями, поддерживающими OLE.

Чтобы добавить возможности OLE-переноса к некоторым элементам управления, размещенным на форме, необходимо установить значения следующих свойств элементов управления.

• OLEDragMode. Определяет, может ли элемент управления инициализировать операцию перетащить-и-опустить (подобно свойству DragMode). Может иметь значения 0 — Manual (Вручную) (элемент управления перемещается только под управлением программы) или 1 — Automatic (Автоматически) (элемент управ­ления перемещается автоматически).

•  OLEDropMode. Свойство эквивалентное свойству DropMode Определяет, может ли элемент управления выступать в качестве адресата OLE-операции перетащить-и-опустить. Принимает следующие значения: 0 - None (Нет) (элемент управления не может быть адресатом), 1 - Manual (Вручную) (элемент управления должен быть запрограммирован для реагирования на OLE-операции перетащить-и-опустить) или 2 — Automatic (Автоматически) (элемент управления автоматически становится адресатом).

Простейший способ включения операции перетащить и-опустить в прило жение - это установка значения 1 (Automatic) для свойства OLEDragMode и значения 2 (Automatic) для свойства OLEDropMode.


На рис. 14. 13 показано окно проекта OLEDDAUTO (см. папку Oledd на компакт-диске). Главная форма проекта содержит элементы управления RichTextBox, TextBox и PictureBox. Щелкните на кнопке Load Image, чтобы загрузить изображение в окно элемента PictureBox, и введите какой нибудь текст в окна элементов RichTextBox и TextBox. Можете открыть текстовый файл в окне элемента управления TextBox, щелкнув на кнопке Load Text File.



Рис. 14.13. Проект OLEDDAUTO автоматическое выполнение OLE-перетаскивания

Если изображение переносится в окно элемента управления RichTextBox, то оно будет вставлено в текст в позиции расположения курсора. Можно взять часть текста из окна элемента TextBox и поместить его в окно RichTextBox: он также будет вставлен в место расположения курсора. Таким образом, используя установки Automatic для значений свойств OLEDragMode и OLEDropMode, можно вставить OLE операции перетащить и опустить непосредственно в приложение, не написав при этом ни одной строки кода.

Объект получатель OLE-операции должен быть в состоянии определять и отображать разнообразную информацию. С этой точки зрения, использование элемента управления RichTextBox представляется оправданным. В данном прило­жении также демонстрируется очень важное свойство элемента управления RichTextBox – OLEObjects. Свойство OLEObjects элемента управления RichTextBox является семейством, в которое входят все объекты данного элемента управления, кроме текста. Перетащите одно или два изображения в окно элемента управления RichTextBox приложения OLEDDAUTO. Затем перетащите несколько файлов с рабочего стола или из любой папки. Проверьте, что приложение и окно папки, содержащее требуемый файл, отображается на экране, а затем перетащите значок файла в окно элемента управления RichTextBox. Чтобы поместить текст в окно элемента управления TextBox, выделите его с помощью мыши и перетащите в окно элемента управления RichTextBox.

После того как объекты помещены в окно элемента управления RichTextBox, щелкните на кнопке List All Object Files. Вы увидите описание каждого объекта, находящегося в окне элемента управления. Программа обслуживания командной кнопки просматривает семейство OLEObjects и выводит в окне проверки значение свойства Class каждого элемента. Для растровых изображений значением свойства Class является StaticDIB.

Элементы семейства OLEObjects имеют и другие свойства, например, свойство DisplayType

(определяет, в каком виде объект отображается в окне элемента управ­ления — в виде значка или содержимого) и семейство ObjectVerbs (содержащий все команды-глаголы, распознаваемые объектом). Чтобы узнать, какие действия может выполнять встроенный объект, вызовите метод Fetch Verbs.

Set AllVerbs = RichTextBoxl.OLEObjects (1).FetchVerbs

For i = 1 to AliVerbs.Count

{перечисление всех команд}

(на каждой итерации выводится значение AllVerbs(i)}

Next

Следующий оператор используется для выполнения специфического действия (например, Play для мультимедиа-файла) над одним объектом.

RichTextBoxl.OLEObjects(1).DoVerb("Play")


Использование сценариев


Поначалу роль броузера сводилась к воспроизведению Web-страницы на компьютере клиента. Web-страницы — это простые текстовые файлы с текстом и информацией о том, как текст появляется в окне броузера. HTML — это такой же язык форматирования документов, как и RTF (Rich Text Format — расширенный текстовый формат). Он не является языком программирования. Отображение на экране Web-страницы в окне броузера напоминает воспроизведение RTF файла в элементе управления RichTextBox. Нельзя использовать HTML для выполнения даже простых вычислений, например, для сложения или отображения названия дня недели в окне броузера.

Большинство клиентских компьютеров обладает мощностью гораздо большей, чем требуется для простого отображения документов на экране. Для использования вычислительной мощности клиентов были введены языки написания сценариев, наиболее простым из которых является VBScript. Написание сценариев позволяет Web-разработчикам создавать динамические структуры, вставляя исполняемый сценарий прямо в HTML-страницу. Можно использовать VBScript для программи­рования элементов Web-страницы так же, как и приложения сервера (используя Сервер активных страниц (CGI)). Позже мы расскажем, как Web-страница может взаимодействовать с броузером, используя сценарии, и как некоторые вычис­ления, обычно выполняющиеся на сервере, выполняются клиентом.



Использование SQL-операторов


Теперь, когда основные SQL-операторы известны, извлечем данные из баз, используя приложение SQLExec (см. параграф " VB6 в действии: проект SQLExec" этой главы). Как использовать SQL-операторы в собственном приложении?

SQL операторы — это определения объектов RecordSet. Свойство RecordSet элемента управления Data не обязательно должно быть именем таблицы. Как правило, оно содержит только определенные строки таблицы или объединяет данные более чем одной таблицы. Набор записей, который выбирает SQL-оператор из базы данных, назначается элементу управления Data. Рассмотрим простой пример.

Приложение Data1, рассмотренное ранее в главе, отображает несколько полей из таблицы Customers базы данных NWIND. Свойство RecordSource элемента управления Data установлено на имени таблицы Customers, выбранном из раскрыва­ющегося списка. Список рядом с именем свойства RecordSource в окне Properties — комбинированный список. В него можно вводить данные.

Предположим, необходимо, чтобы приложение Datal отобразило имена заказ­чиков только из Германии. Чтобы выбрать часть таблицы, задайте SQL-оператор, который создаст соответствующий RecordSet в свойстве RecordSource. Выполните следующие действия.

1. Откройте приложение Datal и выберите элемент управления Data.

2. В окне Properties найдите свойство RecordSource и введите следующий SQL-оператор (рис. 17.17).

SELECT * FROM Customers WHERE Country = "Germany"

3. Запустите приложение и используйте кнопки элемента управления Data для перемещения по именам заказчиков из Германии.

Рис. 17.17. Чтобы получить RecordSet (часть таблицы или объединение нескольких таблиц), присвоите свойству RecordSource SOL-оператор

Так как SQL-операторы распространены при работе с базами данных, допус­кается их непосредственное включение в базы данных. Если открыть список свойства RecordSource элемента управления Data, соединенного с базой данных NWIND, то видно, что он содержит не только имена таблиц. Он содержит имена SQL операторов, сохраненных непосредственно в базе данных. Например, элемент Category Sales for 1995 (категории товаров, проданных в 1995г.) не является именем таблицы. Это — имя запроса, который возвращает уровень продаж за 1995 год, сгруппированный по категории изделия. Если назначить этот объект свойству RecordSource, то поля результирующего RecordSet появятся в списке свойства DataField элемента управления, связанного с данными. В запросе Category Sales for 1995 имена полей, отображаемых в связанных с данными элементах управления — это CategoryName и CategorySales.



Использование связанного с данными элемента управления


List

Элемент управления List связан с определенным столбцом RecordSet и исполь­зуется как поисковая таблица. Он может использоваться как таблица просмотра для упрощения передвижения по RecordSet (рис. 17.21).

Рис. 17.21. Приложение DBList: элемент управления List используется для просмотра

Этот список содержит имена всех товаров в списке

Products базы данных NWIND, загруженных во время запуска программы. Каждый раз, когда выбирается новый элемент, программа обновляет связанные с данными элементы управления, размещенные на форме, чтобы отобразить поля выбранной записи.

Элемент управления List отличается от элементов управления, связанных с данными, которые были рассмотрены ранее: его можно подсоединить к двум элементам управления Data. Он имеет стандартные свойства DataSource/DataField, которые используются как любой другой элемент управления, связанный с данными, и свойства RowSource и List Field, которые определяют, как заполняется элемент управления.

• RowSource задает источник (RecordSet или элемент управления Data) для начальной загрузки списка.

•  ListFieId задает поле, которое используется для заполнения списка.

VB6 в действии: проект DBList

Приложение DBList демонстрирует использование связанного с данными элемента управления List в качестве инструмента перемещения. Форма, показанная на рис. 17.21, содержит ряд полей из таблицы Products базы данных NWIND. Создайте ее, связывая различные текстовые поля с соответствующими полями таблицы элементом управления Data, будто вы собираетесь перемещаться по списку товаров с помощью кнопок перемещения, размещенных на элементе управления Data.

Проблема с элементом управления Data состоит в том, что невозможно реально использовать его для перемещения по RecordSet, даже если он проиндексирован, потому что в каждый момент видима только одна запись. Если бы было можно помещать ключевые значения в элемент управления ListBox и использовать его как инструмент перемещения, то пользовательский интерфейс стал бы удобнее.


ComboBox

Элемент управления ComboBox используется как поисковая таблица (см. при­ложение Data Entry, рассмотренное ранее в этой главе). Чтобы заполнить список элемента управления ComboBox, необходимо установить свойство RowSource на элемент управления Data, соединенный с базой данных и таблицей, из которой выбираются данные.

Приложение Data Entry (папка DEntry на компакт-диске) содержит скрытый элемент управления Data (называемый Data2), который соединен с таблицей Publishers базы данных BIBLIO. Свойство ListField элемента управления ComboBox — это имя поля, использующееся для заполнения списка. В приложении Data Entry это свойство установлено на поле Name таблицы Publishers. При запуске программы элемент управления ComboBox автоматически заполняется именами издателей из базы данных (рис. 17.22).

Рис. 17.22. Элемент управления ComboBox на форме приложения Data Entry содержит имена всех издателей из базы данных

Элемент управления ComboBox имеет обычные свойства DataSource и Data Field, как и другие элементы управления, связанные с данными. Необходимо, чтобы в приложении Data Entry элемент управления ComboBox функционировал следующим образом.

1. При запуске программы элемент управления заполняется именами всех издателей.

2. При перемещении по таблице Titles элемент управления ComboBox извлекает идентификаторы издателей из таблицы Titles, ищет это значение в таблице Publishers и отображает значение поля Name соответствующей записи в окне редактирования.

3. При добавлении новой записи пользователь определяет издателя книги, выбирая имя в элементе управления ComboBox, а элемент управления сообщает соответ­ствующий идентификатор первому элементу управления Data.

Это выглядит сложно, но все это встроено в элемент управления ComboBox. Уже известно, как реализовать первый пункт с помощью свойств RowSource и ListField. Два других пункта типичны для элементов управления, связанных с данными. Необходимо использовать окно редактирования элемента управления ComboBox как обычное текстовое поле, связанное с полем PubID таблицы Titles. Для этого выполните следующие действия.




Grid

Элемент управления Grid - один из наиболее гибких и мощных элементов управления Visual Basic. Пользователи Microsoft Access знакомы с этим элементом управления. Связываемый с данными элемент управления Grid похож на элемент управления MSFlexGrid (см. гл.9), но имеет два отличия:

•   заполняется автоматически из RecordSet,

•   имеет встроенные механизмы ввода данных, с помощью которых можно редактировать RecordSet (если он может модифицироваться).

Все, что нужно сделать для заполнения элемента Grid из RecordSet — это устано­вить его свойство DataSource на элемент управления Data. Сетка будет заполнена строками из RecordSet. Ввиду двумерного расположения данных в элементе управ­ления Grid можно увидеть реальную структуру и содержание всего RecordSet. Этот элемент управления использовался для отображения RecordSet на некоторых рисунках в начале главы. Также он использовался для отображения результатов SQL-операторов в приложении SQLExec (которое мы сейчас рассмотрим).

VB6 в действии: проект SQLExec

Ранее в этой главе для экспериментов с SQL-операторами использовалось приложение SQLExec. Создадим это приложение. Для этого выполните следующие действия.

1. Откройте новый Standard EXE проект.

2. Чтобы добавить связанный с данными элемент управления Grid на панель Toolbox, выполните щелчок правой кнопкой мыши на Toolbox и выберите команду Components.

3. В диалоговом окне Components установите переключатель Microsoft Data Bound Grid Control. В этом проекте используется элемент управления Common Dialogs, поэтому установите переключатель Microsoft Common Dialogs Control 5.0 и щелкните на кнопке Close.

4. Создайте элементы управления (рис. 17.23). Кроме видимых элементов управ­ления, на форме расположен элемент управления Common Dialogs (невидимый во время выполнения) и элемент управления Datal, у которого свойство Visible установлено в False

Рис. 17.23. Приложение SQLExec запросы к базе данных с помощью SQL-операторов и отображение результатов в элементе управления Grid.




Поместите элемент управления List на форму и установите его свойство RowSource на имя элемента управления Datal, а свойство ListFieId — на имя по­ля, которое необходимо отобразить в списке. Для приложения DBList - это поле ProductName. Свойства DataSource и DataField элемента управления List пусты.

Если запустить приложение сейчас, то ничего не случится, потому что не определено, как элемент управления List реагирует на событие Click. Обработчик события должен переместить элемент управления Data на строку RecordSet, которая содержит в поле ProductName то, же значение, что и строка элемента управления List, на которой выполнен щелчок. Для этого добавьте следующий код в обработчик события Click элемента управления List.

Private Sub DBListl_Click()

Datal.Recordset.Bookmark = DBList1.SelectedItem

End Sub

Свойство Bookmark определяет строку в RecordSet. Установка значения этого свойства вынуждает элемент управления Data размещаться на определенной строке. Свойство Selectedltem (Выбранный пункт) элемента управления - это не текст, отображаемый в окне редактирования элемента управления, а закладка записи, которой принадлежит выбранное поле. Этот код позиционирует элемент управления Data в RecordSet и обновляет связанные с данными метки на форме. Учитывая размер этого приложения, можно сказать, что оно действительно выполняет очень много.



1. Выберите элемент управления ComboBox и установите его свойство DataSource на Datal (элемент управления Data, связанный с таблицей Titles).

2. Установите свойство DataField на имя поля, которое необходимо обновить в базе данных. Это поле - PubID.

Поле PubID отображается в элементе управления

ComboBox. Но пользователь видит в ComboBox идентификаторы, а не имена.

Связанный с данными элемент управления ComboBox имеет еще одно свой­ство — BoundColumn, которое является именем поля в его собственном RowSource и связывает поле, отображаемое в списке, с фактическим полем. Значение свойства BoundColumn должно быть индексным полем, чтобы механизм JET мог быстро его найти. Установите свойство BoundColumn на поле PubID и выполните приложение снова На этот раз в ComboBox появится имя издателя текущей книги. Если выбрать в списке имя другого издателя, то в текущей записи сохранится идентификатор нового издателя.

С помощью свойств DataSource, DataField и BoundColumn можно использовать элемент управления ComboBox как поисковую таблицу. Это позволяет выбрать значения содержательных полей и сохранить значения ключей в базе данных. И все это без единой строки кода! Обратите внимание: имена издателей не отсортиро­ваны. Связанный с данными элемент управления ComboBox не имеет свойства Sorted для автоматической сортировки элементов. В случае необходимости сорти­ровки нужно создать новый (соответственно, отсортированный) RecordSet и исполь­зовать его для заполнения элемента управления ComboBox.



5. Элемент управления TextBox, с помощью которого вводятся SQL-операторы, называется txtSQL. Установите его свойство MultiLine в True, а свойство Scrollbars - в 2-Vertical

6. Запрограммируем кнопки. Код кнопки Open Database открывает стандартное диалоговое окно File Open (напомню, мы используем элемент управления Common Dialogs), в котором можно выбрать базу данных. Имя базы отображается на элементе управления Label рядом с кнопкой Command.

Программа 17.13. Кнопка Open Database

Private Sub DBOpen_Click()

On Error GoTo NoDatabase

CommonDialog1.CancelError = True

CommonDialog1.Filter = "Databases | *.MDB"

CommonDialogI.ShowOpen

Data1.DatabaseName = CommonDialog1.FileName

Data1.Refresh

If Err = 0 Then

Label1.Caption = CommonDialog1.FileName

Else

MsgBox Err.Description

End If

NoDatabase:

On Error GoTo 0

End Sub

7. Кнопка Execute SQL (выполнить запрос) выбирает SQL-оператор из текстового поля txtSQL и присваивает его свойству RecordSource элемента управления Datal.

Private Sub ExecuteSQL_Click()

On Error GoTo SQLError

Data1.RecordSource = txtSQL

Data1.Refresh

Exit Sub

SQLError:

MsgBox Err.Description

End Sub

Оператор ОnЕггог определяет любую ошибку при выполнении SQL-оператора и отображает информацию о ней в окне сообщений. Присваивание нового значения свойству RecordSource элемента управления не модифицирует его содержимое. Чтобы прочитать новые данные из базы данных и принудительно выполнить модификацию, вызывается метод Refresh элемента управления Data.


Элемент управления


OLE Container

Рассмотрим, как OLE-технология используется в VB-приложениях. Чтобы включить функциональные возможности OLE в VB-приложения, необходим элемент управления OLE Container, позволяющий вставлять в программу объекты из других приложений. В элемент управления OLE Container можно поместить только один объект. На форму можно поместить несколько элементов OLE Container, каждый из которых может содержать собственный объект.

Элемент управления OLE Container — это доступ к различным объектам опера­ционной системы, которые Visual Basic не в состоянии использовать самостоятельно (например, документы Word, звуковые файлы, растровые изображения или электронные таблицы Excel). Элемент управления OLE Container может содержать любой из объектов, перечисленных в диалоговом окне Insert Object (Вставка объекта), и сделать вашу программу на Visual Basic приложением-контейнером. Преимуществом использования OLE Container является то, что он скрывает сложности, связанные с применение OLE. Встраивать объекты в OLE Container можно как при разработке приложения, так и при выполнении.


FLEXLabel

Начнем наше исследование элементов управления ActiveX с простого примера. Первый элемент, который будет сконструирован в этой главе — это элемент управления FLEXLabel (улучшенный элемент управления Label), показанный на рис. 16.1. Он реализует все возможности элемента управления Label плюс несколько весьма интересных особенностей, таких как выравнивание текста во всех возможных направлениях и трехмерное изображение.

Рис. 16.1. Элемент управления FLEXLabel является улучшенным вариантом элемента управления Label, который может отображать трехмерный текст и выравнивать его по вертикали и горизонтали.

Для построения элемента управления FLEXLabel следует выполнить следующие действия.

1. Включить все компоненты стандартного элемента управления Label.

2. Добавить дополнительные члены и написать код для их реализации.

3. Испытать элемент на форме.

Сейчас, скорее всего, стоит задуматься о программе, которая выравнивает текст и выводит его в виде вдавленного или выпуклого изображения. Начнем со стандартного проекта, который отображает строку на форме и выравнивает ее всеми возможными способами. Элемент управления — это приложение, созданное таким образом, что позволяет ему отображаться на форме, а не на рабочем столе. В большинстве случаев такой элемент может быть реализован с помощью обычной формы. На рис. 16.2 показана форма проекта FLabel, которая делает в точности то же, что должен делать элемент управления FLEXLabel. Этот проект находится в папке с одноименным названием на компакт-диске. Откройте его и посмотрите, как он работает.

Рис. 16.2. Проект FLabel отображает строку в трехмерном представлении, выравнивая ее по вертикали и горизонтали, подобно элементу управления FLEXLabel.

В общем случае, создавать элемент управления как

Standard ЕХЕ-приложение не следует, но, для начала, это, возможно, может помочь. Получив код, управляющий видимым интерфейсом разрабатываемого элемента управления, можно сосредо­точиться на процедурах, специфичных для разработки элементов управления ActiveX. Есть еще одна веская причина, по которой выбран этот подход, а именно, возможность сопоставления подходов к конструированию обычных приложений и элементов управления ActiveX.




Data

Наборы RecordSet являются основой программирования баз данных. Рассмотрим пример, который поможет представить, что такое набор RecordSet, и исследовать элемент управления Data Приложение Datal (рис 17 3) — это интерфейс для доступа к таблице в базе данных.

Рис. 17.3. Приложение Datal позволяет просматривать строки таблицы без написания строк кода

VB6 в действии: проект Data1

Для создания данного приложения выполните следующие действия.

1. Откроите новый проект типа Standard EXE и разработайте форму (см. рис. 17.3). Начните с размещения в нижней части формы элемента Data - это ваши "двери" к базе данных.

2. Выбрав Data, откройте окно свойств, найдите свойство DatabaseName (Имя базы данных) и нажмите кнопку с многоточием, чтобы открыть диалоговое окно Open.

3. Выберите базу данных NWIND, которая поставляется вместе с Visual Basic.

4. В окне свойств найдите свойство RecordSource (Источник записей) и откройте список доступных источников записей. Вы увидите список всех таблиц в базе данных NWIND. Выберите таблицу Customers.

5. Разместите на форме четыре элемента управления Textbox (см. рис. 17.3).

6. Выберите первый элемент Textbox и в окне свойств найдите свойство DataSource (Источник данных). Установите его значение в Data1.

7. Установите значение свойства DataField (Поле) элемента Textbox в CompanyName. Свойство DataField — это раскрывающийся список с названиями всех полей таблицы Customers.

8. Установите в свойствах DataSource (Источник данных) остальных элементов Textbox значение Data1, а в свойствах DataField (Поле) выберите Country (Страна), Phone (Телефон) и Fax (Факс), соответственно.

Запустите приложение. Элементы управления Textbox отобразят содержимое соответствующих полей таблицы Customers базы данных NWIND. Используя кнопки элемента Data, можно двигаться по записям (строкам) таблицы. При нажатии крайней левой кнопки отображается первая запись таблицы, а при нажатии кнопки, расположенной правее и рядом с ней — предыдущая запись. Соответственно, при нажатии крайней правой кнопки отображается последняя запись таблицы, а при нажатии кнопки, расположенной левее и рядом с ней — следующая запись.




ADO Data

Визуальные инструменты для работы с базами данных не являются единственным средством работы с DAO. Одним из новых элементов управления, добавленных на панель элементов управления, является ADO Data (сходный с элементом Data). Он позволяет подключаться к большим базам данных различных типов, причем с помощью одного приложения и используя один интерфейс

Простейший путь применения ADO в проекте — добавление на форму элемента управления ADO Data и использование его подобно элементу управления Data. Чтобы использовать элемент управления ADO Data со стандартным ЕХЕ-проектом, добавьте его на панель элементов управления.

Откройте меню Project и выберите команду Components для вызова одноимен­ного диалогового окна Components. Отметьте опцию Microsoft ADO Control 6.0 (OLEDB). Для использования усовершенствованных связанных с данными элементов управления (например. List и ComboBox) отметьте также опцию Microsoft Data List Control 6.0 (OLEDB). Щелкните на кнопке ОК для возврата в среду разработки Visual Basic.

Теперь панель элементов управления содержит элементы управления ADO — Data Control, DataList и DataCombo Элементы управления DataList и DataCombo подобны элементам управления DBList и DBCombo, только они предназначены для объектов ADO Data, а не Data.

Приведем пример использования элемента управления ADO Data. Разработаем очень простую форму, которая позволит просматривать заказчиков в базе данных NWIND. Проект ADODC (см. рис. 18.15) состоит из формы с несколькими текстовыми полями, отображающими поля таблицы Customer базы данных NWIND. Текстовые поля связаны с элементом управления ADO Data, который подключает их к текущей записи в таблице Написание кода не требуется.

Рис. 18.15. Проект ADODC: основные свойства элемента ADO Data идентичны свойствам элемента Data

Чтобы создать проект ADODC, выполните следующие действия.

1. Откройте новый проект и добавьте элемент управления ADO Data на панель инструментов проекта.

2. Поместите экземпляр элемента управления ADO Data на форму.




Script

В дополнение к построению сценариев Web-страниц,

VBScript можно исполь­зовать для написания сценария в приложениях Visual Basic. Функциональные возможности VBScript встраиваются в приложения с помощью элемента управления Script, выпущенного несколькими месяцами раньше Visual Basic 6. В этой книге элемент Script получен из Web-узла http://www.microsoft.com/scripting. По этому адресу можно найти дополнительную документацию по элементу управления Script и примеры его использования. Что касается версии VBScript, использо­вавшейся при написании книги, то документация по нему скупа, сам элемент управления содержал несколько ошибок, но разработка сценариев с помощью Visual Basic - занятие настолько захватывающее, что на указанные недостатки можно не обращать внимания.

Что может сделать элемент управления Script для приложения? Он может вычислять выражения во время выполнения (имеются в виду выражения, которые передаются приложению в виде строки - прим. ред.). А поскольку элементом управления Script можно управлять из кода приложения, то и само приложение приобретает эту возможность.

Предположим, необходимо разработать калькулятор, который вычисляет мате­матические выражения. Visual Basic вычисляет любое математическое выражение, если оно является частью кода. Например, пользователю во время выполнения необходимо вычислить математическое выражение типа 99,9/log(2,5) или нарисо­вать график кривой 9*Sin(x)/Cos(x).

Как разрешить эту задачу средствами Visual Basic? Единственный способ — создать собственный элемент управления, способный воспринимать и вычислять выражения в ходе выполнения программы. В гл. 6 рассмотрено приложение Graph, которое рисует график функции, определение которой является частью кода приложения. Этот подход имеет очень ограниченную сферу применения.

В этой главе мы модифицируем приложение Graph так, чтобы оно могло рисовать любую функцию, задаваемую пользователем во время выполнения. Такую возможность предоставляет элемент управления Script. Элемент управления Script вычисляет не только математические, но и логические выражения, выполняя те или иные действия на основе полученного результата, например, организацию цикла. Он позволяет использовать все разнообразие операторов и функций VBScript. Ниже приведен код на VBScript, который определяет, какая из двух функций имеет большее значение для текущего аргумента x.




WebBrowser

Элемент управления WebBrowser попросту является окном Internet Explorer. Любой HTML-документ, который отображается в Internet Explorer, может отображаться на элементе управление WebBrowser. Элемент управления WebBrowser добавляет возможности броузера в приложения. Он позволяет пользователю просматривать узлы в World Wide Web, локальные файлы или ActiveX-документы, например документы Word или Excel из приложения Visual Basic.

Поскольку WebBrowser — элемент управления ActiveX, его можно установить на любой форме Visual Basic. Перед использованием необходимо добавить этот элемент на панель элементов управления. Для этого выполните следующее.

1. Щелкните правой кнопкой мыши на панели элементов управления и из контекстного меню выберите Components чтобы открыть диалоговое окно Components.

2. Выберите Microsoft Internet Controls и щелкните на кнопке ОК. На панели инструментов появятся два новых значка WebBrowser и ShelFolderViewOC.

3. Выберите значок WebBrowser и поместите элемент управления на форму.

Размеры элемента управления WebBrowser можно изменять. Поскольку размеры элемента управления нельзя изменять во время работы программы необходимо их отрегулировать по размерам контейнера которым является форма Visual Basic. Когда пользователь меняет размеры формы элемент управления WebBrowser также меняет свои размеры.

Для отображения Web страницы на элементе управления WebBrowser используется метод Navigate. Можно переместиться по списку URL. Элемент управления WebBrowser автоматически создает список посещенных URL. Далее будут рассмотрены свойства, методы и события элементов управления. Начнем с разработки простого приложения которое демонстрирует основные характеристики элементов управления.

VB6 в действии: проект Browser

В этом параграфе разработано приложение, основанное на элементе управления WebBrowser и демонстрирующее как добавить возможности Web броузера в приложения Visual Basic (проект Browser на компакт диске), На рис, 21,1 показано приложение Browser, отображающее Web-узел Sybex. Пользователь может выбрать URL из комбинированного списка или локальный HTML-файл, щелкнув на кнопке Open HTML File.



Класс


String

Последний пример в этом разделе — это очень простой класс, который реализует несколько полезных операций со строками. Класс String предусматривает три метода, реализованных в виде общедоступных функций.

•  Integer2Binary(number As Long). Преобразует свой числовой аргумент в двоичное число и возвращает двоичное значение в виде строки.

•  Number2String(number As integer). Преобразует свой числовой аргумент в строку и возвращает ее. Если число 395 передать этому методу в качестве аргумента, то возвращаемым значением будет строка "триста девяносто пять".

•  LowerCaps(str As String). Преобразует свой аргумент в нижний регистр, причем первые буквы всех слов становятся заглавными, и возвращает новую строку. Если значение "триста девяносто пять" передать в качестве аргумента этому методу, то возвращаемым значением будет строка "Триста Девяносто Пять".

Члены класса String довольно просты, но они могут служить в качестве отправной точки при создании класса с функциями для манипуляции строками и числами, которые часто используются, но не реализованы в Visual Basic в чистом виде.

Три метода класса String реализованы в виде общедоступных функций, и показаны ниже.

Программа 15.17. Методы класса String

Public Function Number2String(Number)

Dim tenth As Integer

Dim leftover As Integer

Dim hundred As Integer

Dim thousand As Integer

If Number < 20 Then ' Чтение чисел меньших 20

NumString = ReadSingle(Number)

Elself Number < 100 Then   ' Чтение чисел меньших 100

tenth = Fix(Number / 10)

NumString   ReadTenths(tenth * 10)

leftover = Number   (tenth * 10)

If leftover > 0 Then

NumString = NumString & " " & ReadSingle(leftover)

End If

Elself Number < 1000 Then   ' Чтение чисел между 100 и 999

hundred = Fix(Number / 100)

NumString =

ReadSingle(hundred) & " hundred"

leftover = Number - (hundred * 100)

If leftover > 0 Then

tenth = Fix(leftover / 10)

If tenth > 0 Then NumString = _


NumString & " " & ReadTenths(tenth * 10)

leftover = Number - (hundred * 100) - (tenth * 10)

If leftover > 0 Then

NumString = NumString & " " & _

ReadSingle(leftover)

End If

End If

Else              ' Чтение чисел между 1000 и 9999

thousand = Fix(Number / 1000)

NumString = ReadSingle(thousand) & " thousand"

leftover

= Number - (thousand * 1000)

If leftover > 0 Then

hundred

= Fix(leftover / 100)

If hundred > 0 Then

NumString

= NumString & " " &_

ReadSingle(hundred) & " hundred"

End If

leftover

= Number – (thousand * 1000)- _

(hundred *100)

If leftover > 0 Then

tenth   Fix(leftover / 10)

If tenth > 0 Then

NumString = NumString & " " & _

ReadTenths(tenth * 10)

End If

leftover = Number - (thousand * 1000) - _

(hundred * 100)

- (tenth * 10)

If leftover > 0 Then

NumString

= NumString & " " & _

ReadSingle(leftover)

End If

End If

End If

End If

Number2String = NumString

End Function

Public Function LowerCaps( str As String) As String

Dim newWord As String, newStr As String

Dim tempStr As String

Dim WDelimiter As Integer

tempStr = Trim(str)

WDelimiter = InStr(tempStr, " ")

While WDelimiter > 0

newWord = Left(tempStr, WDelimiter)

tempStr = Right(tempStr, Len(tempStr) - WDelimiter)

newStr = newStr & UCase(Left(newWord, 1)) & _

Mid(newWord, 2, Len(newWord) - 1)

WDelimiter = InStr(tempStr, " ")

Wend

newWord = tempStr

newStr = newStr & UCase(Left(newWord, 1)) & _

Mid(newWord, 2, Len(newWord) - 1)

LowerCaps = newStr

End Function

Public Function Integer2Binary(ByVal Number As Long) As String

HexNum = Hex(Number)

For i = 1 To Len(HexNum)

BinNum = BinNum & BinaryDigits("&H" & Mid(HexNum, i, 1))

Next

Integer2Binary = BinNum

End Function

Функция Number2Stnng() наиболее сложная. Она похожа на функцию, которая используется проектом READNUM в приложении С (на компакт-диске) для считывания числовых значений. Функция Number2Stnng() может преобразовывать целые значения в диапазоне от 0 до 9999, но можно легко добавить код для работы с большими и нецелыми значениями. Функция Number2Stnng() вызывает функции ReadTenths() и ReadSingle(), которые являются закрытыми членами класса, т.е. их можно вызывать из компонентов класса, но внешние программы не имеют к ним доступа. Если просмотреть члены класса StringClass в броузере объектов, то можно увидеть закрытые члены класса. Однако они будут представлены как Private, напо­миная о том, что к ним нет доступа из их приложений.



Тестовая форма класса StringClass показана на рисунке 15.10. Пользователь может ввести числовое значение в текстовое окно наверху формы и щелкнуть кнопки Convert to String или Convert to Binary для преобразования значения в строку или двоичное значение соответственно. Когда текстовое окно под кнопкой Convert to String содержит строку (строка, соответствующая числовому значению или значению, введенному пользователем), то пользователь может щелкнуть кнопку Convert to LCaps для преобразования строки в нижний регистр.



Рис. 15.10. Тестовая форма класса String

Код тестовой формы достаточно прост. Вначале объявляется объектная перeменная, которая будет использоваться для доступа к классу String:

Dim NS As New NumStrings.StringClass

NumStrings это имя проекта, a StringClass — имя модуля класса. Код, соответст­вующий трем командным кнопкам, показан ниже.

Private Sub Command1.Click()

Text2.Text = NS.Number2String(Text1.Text)

End Sub

Private Sub Command2_Click ()

Dim NStr As String

NStr = NS.Number2String(Text1.Text)

Text3.Text = NS.LowerCaps(NStr)

End Sub

Private Sub Command3_Click()

Text4.Text =

NS.Integer2Binary(Text1.Text)

End Sub

Каждая кнопка вызывает различные методы переменной NS.

Код, соответст­вующий кнопке Command2, вызывает два метода друг за другом. Вначале он преобразует числовое значение из поля Textl в строку, а затем вызывает метод LowerCaps для преобразования строки в нижний регистр. Два вызова можно объединить в один оператор, как показано ниже:

Text3.TextNStr =

NS.LowerCaps(NS.Number2String(Text1.Text))

В папке этой главы на компакт-диске находится проект NumStr. Откройте его в Visual Basic, исследуйте код или добавьте к нему новые члены. Сейчас самое время для регистрации этого класса в системе, чтобы его можно было использовать в примерах главы 22, где будет создана страница активного сервера, которая исполь­зует этот компонент для создания HTML-страниц.

В следующей главе внимание будет сосредоточено на второй категории компо­нентов ActiveX — элементах управления ActiveX. Элементы управления ActiveX намного проще, чем ActiveX DLL, и несколько интереснее, поскольку они имеют видимый интерфейс пользователя. Программирование интерфейса элементов управления ActiveX такое же, как и для программных компонентов ActiveX. Процесс реализации свойств и методов для элементов управления ActiveX также идентичен описанному в этой главе. В дополнение, необходимо создавать видимый интерфейс элементов управления, что очень похоже на создание форм.



Глава 16. Конструирование элементов управления ActiveX

• Конструирование элементов управления ActiveX

• Конструирование элемента управления FLEXLabel

• Взаимодействие с объектом-контейнером

• Конструирование страниц свойств

• Построение базового элемента управления

• Улучшение существующих элементов управления

Если и есть хоть одна возможность Visual Basic, которая привлекает всех без исключения разработчиков, так это — ActiveX. Сейчас Visual Basic является простым, легким в изучении и наиболее популярным языком конструирования элементов ActiveX. Элемент управления ActiveX - это то, что раньше называлось элементом управления OLE. Можно предположить, что элементы управления ActiveX являются расширением Visual Basic. Это объекты, представленные на панели элементов управления Visual Basic маленькими значками, которые можно добавлять в любые формы разрабатываемого приложения для расширения его функциональных возможностей.

Первый вопрос, который возникает: почему они называются элементами управления ActiveX? Скорее всего, это вопрос коммерции. OLE-элементы ассоции­ровались с тяжелым и кропотливым программированием на С. Название, вроде «ActiveX» должно помочь среднему программисту преодолеть робость. И действи­тельно, эта часть VB была так хорошо реализована, что даже для среднего программиста теперь доступна разработка элементов управления ActiveX. Речь идет не только о том, что с помощью Visual Basic 6 можно создавать элементы управления ActiveX, а и о том, как легко это можно сделать. Кроме того, появилась возмож­ность использования ActiveX на Web-страницах — одной из самой быстро расту­щих арен для разработки программ на Visual Basic.

Кто должен конструировать элементы управления

ActiveX? Если можно было обойтись без ActiveX раньше, почему их необходимо использовать сейчас? Дейст­вительно, еще некоторое время многие пользователи VB смогут не заниматься разра­боткой собственных элементов управления ActiveX. Но, рано или поздно, все же придется этим заняться. Если разрабатывается интересная утилита, которая может использоваться в нескольких приложениях, почему бы ни сделать ее элементом управления ActiveX? Кроме того, зачем отказывать себе в удовольствии попробовать что-нибудь новое? ActiveX помогут программисту на VB расширить диапазон собст­венных возможностей. Быть способным конструировать элементы для использования их и на вашем компьютере, и в Internet представляется прекрасной перспективой для тех, кто зарабатывает себе на жизнь программированием на Visual Basic.