Активирование клиента с помощью
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 (Кнопка отмены) |
Теперь можно написать код приложения.
Программа 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 |
После нажатия на кнопку 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 |
Чтение/Запись Чтение/Запись Чтение/Запись Чтение/Запись |
Чтение/Запись Чтение/Запись Чтение/Запись Чтение/Запись |
Теперь можно открыть окно 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 |
• Свяжите текстовое поле, в котором отображается название книги, с полем 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 |
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 |
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.