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

VBScript
Web является средой типа клиент/сервер. Нагрузка сбалансирована между сервером, хранящим информацию, и клиентом, ее обрабатывающим. До недавнего времени процедура обработки заключалась в воспроизведении Web-страницы (включая графику) на компьютере клиента. При помощи VBSript можно добавлять маленькие программы на страницы, которые выполняются на сервере. С появлением DHTML, языков написания сценариев (VBScript и JavaScript), элементов управления ActiveX для Web большая часть обработки переносится с сервера на компьютер-клиент.
По определению Web-страницы являются интерактивными: при щелчке на гиперссылке пользователю предоставляется другая страница. Этот вид взаимодействия не привычен для пользователей Windows. Кроме того, на каждом шаге он требует обращения к серверу. Web-страница не реагирует на каждое событие, например, нажатие кнопки мыши, поскольку HTML не язык программирования. Он даже не отображает дату и не выполняет простых вычислений.
Последняя тенденция в оформлении Web-страниц — это их активизирование. Активной является страница, которая работает как приложение. Она имеет свой интерфейс пользователя, состоящий из элементов Windows (командных кнопок, полей ввода и элементов управления ActiveX, реализованных для Web), и взаимодействует с пользователем как обычное Windows приложение. Активной странице не требуется обращение к серверу, чтобы отобразить дату или выполнить вычисления.
Встроенное приложение называется сценарием.
Сценарии - это простые программы, встроенные в HTML-страницу в виде ASCII-текста. Когда загружается страница, вместе с ней загружается сценарий и запускается на выполнение броузером на компьютере клиента. Идея, лежащая в основе активизирования страниц — это использование вычислительной мощности компьютера-клиента. Задача компьютера-клиента - это воспроизведение HTML-документов на экране. Но большинство клиентов имеют мощные PC, способные на большее, чем просто отображать Web-страницы на экране. Активные страницы используют доступную вычислительную мощность для передачи процесса обработки от сервера клиенту.

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

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


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

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



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

OLE
OLE Automation (Автоматизация OLE) — это еще один шаг вперед по сравнению со связыванием При выполнении связывания объектов выполняется заимствование функциональных возможностей другого приложения. Используя автоматизацию OLE можно управлять исходным документом непосредственно из вашего приложения. Приложения, которые поддерживают автоматизацию OLE, предоставляют свои объекты другим приложениям. Например, объектом, который предоставляет Word, может быть и предложение, и абзац, и весь документ. Объектом, который может предоставить Excel, может быть макрос, блок ячеек или весь рабочий лист.
Управлять предоставленными объектами из приложения Visual Basic можно с помощью свойств и методов, предоставленных приложением-источником. Важной особенностью Visual Basic является то, что он позволяет обращаться как к объектам приложения сервера OLE, так и к его функциональным возможностям для работы с этими объектами. Преимуществом автоматизации OLE является то, что можно, работая в единой среде, использовать любые OLE-средства, доступные в других приложениях.
Когда компания Microsoft начала разрабатывать автоматизацию OLE, основная идея была проста: создать общий язык и среду программирования, позволяющую использовать средства и возможности ряда основных приложений. В результате был разработан язык Visual Basic for Applications (VBA).
Используя только VBA нельзя разработать требуемое вам приложение, независимо от его типа VBA предоставляет в распоряжение разработчика только основные управляющие структуры, математические и строковые функции, а также возможности манипулирования переменными. Реальная эффективность VBA определяется приложениями, поддерживающими его.
С появлением VBA версии 5.0 фирма Microsoft начала продавать лицензии на него тем компаниям разработчикам программного обеспечения, которые хотели добавить к своим продуктам дополнительные средства программирования. Например язык программирования, использовавшийся в пакете AutoCAD компании AutoDesk, был уникален и не мог использоваться другими приложениями. Многие другие изготовители включали в свои программные продукты языки, позволяющие разрабатывать сценарии и прочие средства автоматизации но потребность в некоем глобальном языке который мог бы помочь объединить отдельные части различных приложении была очевидна. В конце концов, фирма Microsoft разработала VBA (версии 5), который соответствовал потребностям других разработчиков. Теперь VBA идет своей дорогой, становясь универсальным языком, позволяющим создавать универсальные приложения для Windows.

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

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


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

Для облегчения разработки Web-приложений активный сервер предоставляет следующие объекты для обеспечения функциональных возможностей, широко используемых в Web-разработках.
Database.
Обеспечивает подключение к базам данных, поддерживающим протокол ODBC или OLE DB, созданный на основе объекта ADO, что позволяет Web-разработчикам без проблем осуществлять подключение баз данных к активной Web-странице.
File Access. Предназначен для доступа к текстовым файлам на сервере. Серверные сценарии, как и клиентские, должны быть безопасными. Объект File Access полностью отвечает этим требованиям, поскольку с его помощью можно получить доступ только к файлам в определенных папках на сервере.
Content Linking.
Предназначен для работы со списком URL, что позволяет обращаться со страницами Web-узла, как со страницами обычной книги. После создания страницы объект Content Linking генерирует таблицу содержимого и навигационных связей с предыдущей и последующей страницами. Используя методы и свойства этого объекта, можно добавлять, удалять и упорядочивать отдельные HTML-файлы.
Browser Capabilities.
Позволяет ASP-файлу распознавать тип и отличительные особенности броузера, приславшего запрос, и динамически настраивать параметры узла. Если возможность распознать тип броузера во время сеанса связи отсутствует, то вам понадобится иметь копии каждой страницы для броузера каждого типа либо оповещать пользователя о том, что он может открыть данную страницу, используя броузер конкретного типа.
Advertisement Rotator.
Позволяет отображать рекламные объявления в соответствии с преопределенными критериями, когда запрашивается ASP-файл. По мере того как все больше людей осознают значение Web, как средства бизнес-медиа, и все больше узлов становятся коммерческими, возрастает потребность в средствах работы с объявлениями в Web. Поэтому Web-менеджерам требуются средства для автоматической замены рекламных объявлений в их страницах в соответствии с запросами пользователей. Для упрощения этого процесса в ASP включен объект Advertisement Rotator.
В этой главе рассмотрены некоторые встроенные и базовые компоненты ASP, позволяющие использовать навыки программирования на Visual Basic в Web-разработках.



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

Почти все деловые приложения хранят большие объемы данных, организованные в формате, упрощающем их поиск. Системы управления базами данных (СУБД) являются механизмом управления табличными данными с помощью команд высокого уровня. Система управления базами данных скрывает подробности низкоуровневого управления (например, сохранения данных в базе), позволяя программисту концентрироваться на управлении информацией, а не на управлении файлами или поддержании связей между ними.
Visual Basic предоставляет большой набор инструментальных средств для создания и доступа к базам данных как на индивидуальных машинах, так и на сетевых Но два основных из них — это:
•  элемент управления Data и
•   объект Data Access (или DAO — Data Access object).
Элемент управления Data предоставляет доступ к базам данных без какого-либо программирования. Можно установить несколько свойств этого элемента управления и использовать такие средства, как текстовые поля, чтобы отобразить значения полей базы данных. Это бескодовый подход к программированию баз данных, который в полной мере реализован в Visual Basic. Как можно догадаться, этот подход не позволяет добиться большего. Рано или поздно, но наступит необходимость писать программу.
Объект Data Access — это структура объектов, предназначенная для доступа к базам данных из кода программы. Все функциональные возможности элемента управления Data доступны программе посредством DAO.
Что такое база данных (database)? В простом понимании, это — сгруппированная, связанная информация, организованная специальным образом для облегчения обработки и поиска (рис. 17.1). Фактически, данные в базе хранятся в таблицах (table), подобных файлам с произвольным доступом. Данные в таблице состоят из столбцов
и строк. Строки содержат однотипную по структуре информацию и напоминают записи файлов с произвольным доступом. Запись — это множество (коллекция) значений, называемых полями.
Базы данных и системы управления базами данных

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



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

База данных NWIND, поставляемая с Visual Basic, предусматривает целостность некоторых отношений. Чтобы увидеть, как это работает, выполните следующие действия.
1. Используя Visual Data Manager, откройте базу данных NWIND и дважды щелкните на таблице Orders (Заказы), содержащей все счета.
2. Выберите счет и запомните ID заказчика, которому выдан счет.
3. Закройте таблицу и дважды щелкните на ее имени таблицы, чтобы открыть ее в режиме ввода данных.
4. Выберите заказчика, ID которого появлялся в счете, и нажмите Delete Механизм JET отобразит сообщение об ошибке (рис. 17.12).
Целостность ссылок

Рис. 17.12. Механизм JET отслеживает целостность отношении
Сообщение об ошибке показывает, что запись, которую пытаются удалить, связана с записями в другой таблице и не может быть удалена.
Если целостность отношений (ссылок) для базы данных важно, то укажите механизму JET следить за его сохранностью. Поддержка целостности ссылок — одна из наиболее важных возможностей системы управления базами данных. Иначе программист следил бы за этим сам, а это — задача не простая.
Хотя можно защитить некоторые ссылки из кода программы, все-таки лучший способ — включить целостность ссылок непосредственно в базу данных. Visual Data Manager для этого не подходит, но можно использовать более совершенные инструменты разработки баз данных, например Microsoft Access, чтобы определить, какие отношения должны быть защищены системой. Эта информация будет сохранена в базе данных
VB6 в действии: проект Data Entry
Построим реальное приложение для ввода данных с возможностями добавления и удаления записей (рис. 17.13). Когда пользователь щелкает на кнопке Add Record, приложение вызывает метод AddNew и обе кнопки одновременно "прячутся". На их месте отображаются обычные кнопки ОК. и Cancel. Можно сохранить новую запись в базе данных, щелкнув на кнопке ОК, или отказаться от сохранения, щелкнув на кнопке Cancel. В любом случае, кнопки ОК и Cancel скроются и снова отобразятся кнопки Add Record (Добавить запись) и Delete Record (Удалить запись).

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


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

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

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

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

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

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

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

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

Caption

Name

Add Record

Delete Record

OK

Cancel

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

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

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

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

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

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

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

Private Sub AddBttn_Click()

HideButtons


Data1.Recordset.AddNew

End Sub

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

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

Private Sub OKBttn_Click()

On Error GoTo CancelUpdate

Data1.Recordset.Update

ShowButtons

Exit Sub

Cancel-Update:

MsgBox Err.Description

Data1.Recordset.Cancel-Update

ShowButtons

End Sub

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

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

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

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

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

Private Sub CancelBttn_Click()

Data1.Refresh

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

ShowButtons

End Sub

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

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

Private Sub DelBttn Click()

On Error Resume Next

Datal.Recordset.Delete

If Not Data1.Recordset.EOF Then

Data1.Recordset.MoveNext

Elself Not Data1.Recordset.BOF Then


Data1.Recordset.MovePrevious

Else

MsgBox " This was the last record in the table"

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

End If

End Sub

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

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

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

Sub ShowButtons()

AddBttn Visible = True

DelBttn.Visible =  True

OKBttn.Visible = False

CancelBttn.Visible = False

Data1.Visible = True

End Sub

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

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

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

MsgBox Err Description

Response =  0

Data1.Recordset CancelUpdate

End Sub

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

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

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

Dim reply

If txtTitle.DataChanged Or txtISBN.DataChanged Or _

txtDescription.DataChanged Or txtSubject DataChanged _

Or txtComments.DataChanged Then

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

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

   If reply = vbNo Then

  Save = False

   End If

End If

End Sub

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


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

Метод
AddCode элемента управления Script позволяет добавлять к нему несколько процедур. Иногда ему необходим список имен всех процедур. Свойство Procedures является семейством, содержащим все процедуры, добавленные в элемент управления Script. Оно имеет свойство Count,
которое возвращает количество процедур, и свойство /tern, возвращающее, собственно, процедуру. Приведенный ниже цикл сканирует все процедуры в списке.
For i=1 To ScriptControll.Procedures.Count
{обработка элемента ScriptControll.Procedures (i)}
Next
Каждый элемент в семействе Procedures имеет свойство Name, которое соответствует имени процедуры, и свойство HasReturn Value, которое возвращает значение True, если процедура возвращает результат (т.е. является функцией). Кнопка List Procedures на форме SEdit выводит список имен и типов всех процедур в нижний элемент управления TextBox.
Программа 20.10. Список процедур
Private Sub Coinmand2 Click ()
On Error GoTo CodeError
ScriptControll.AddCode Text1.Text
For i=1 To ScriptControll.Procedures.Count
If ScriptControll.Procedures(i).HasReturnValue Then
Text2.Text = Text2.Text & vbCrLf & "Function " _
& ScriptControll.Procedures(i).Name
Else
Text2.Text = Text2.Text & vbCrLf S "Subroutine " _
& ScriptControll.Procedures(i).Name
End If
Next
Exit Sub
CodeError:
MsgBox Err.Description
End Sub
Обратите внимание, как код различает процедуры и функции с помощью свойства
HasReturn Value.
Совет
Хотелось бы, чтобы существовало какое-нибудь свойство, называемое, например, Code, возвращающее текст процедуры. К сожалению, такого свойства не существует. Нет простого способа получить код отдельной процедуры. Более того, отсутствует метод удаления отдельной процедуры. Необходимо удалить все процедуры методом Reset элемента управления Script, а затем добавить их по одной, исключив ненужную. При этом придется сохранить список процедур в отдельном элементе (например, в TextBox). В проекте SEdit для извлечения отдельной процедуры выполняется просмотр содержимого верхнего элемента управления TextBox.



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

Компания 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()). Начнем с разработки нескольких активных серверных страниц, а затем рассмотрим объекты активного сервера.



Что такое

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



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

Давайте поэкспериментируем немного с событиями кнопок элемента управления. Сделайте следующее.
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, рассказано в следующем параграфе.



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

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


Site Map





Popular Titles from SYBEX




DEVELOPERS HANDBOOKS



  • The NetWare 3.12 Administrator's Handbook (2nd Ed)
  • Access and SQL Server Developer's Handbook
  • Microsoft Access 2 Developer's Handbook




    FAST TRACK


  • Fast Track to Visual Basic 4
  • The ABCs of JavaScript




    MASTERING


  • Mastering Web Design
  • Mastering the Internet (2nd Ed)
  • Mastering Windows NT Server 4
  • Mastering Java
  • Mastering Windows 95




    NETWORK PRESS


  • The Encyclopedia of Networking (2nd Ed)
  • Introduction to Local Area Networks
  • Networking The Small Office




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

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

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





    MASTERING




    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.



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

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

  • Mastering Web Design

  • Mastering the Internet (2nd Ed)

  • Mastering Windows NT 4

  • Mastering Windows 95








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

    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-документ, а затем для обеспечения реакции на действия пользователя каждый активный радел заключается в пару тегов
    . Все, что находится между ними, является отдельным элементом, а его атрибутами можно управлять при помощи операторов VBScript.

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

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

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

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

    • Объект FileSystemObject

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

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

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

    • Объект Shell

    В предыдущей главе VBScript использовался для описания Web-страниц, в том числе сценариев, использующих вычислительную мощность компьютера клиента. Сценарии - это простые программы, которые загружаются в текстовом формате и выполняются на компьютере клиента. Сам по себе, VBScript является ядром языка программирования. Самостоятельно он выполняет очень мало. Подлинные возможности сценариев заключаются в том, что VBScript обеспечивает доступ к объектам, предоставляемым броузером. Если проигнорировать объекты, которыми можно управлять с помощью VBScript (такими как
    -тэги или встроенные элементы управления 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.


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

    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, который передает данные на сервер под управлением программы.



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

    В процессе работы программы можно изменить элементы меню. Эти возможности показаны на примере программы 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. Например, следующий код является определением стиля, который выделит все заголовки первого уровня голубым цветом, а все заголовки второго уровня — красным.

    Если вставить этот оператор в начало 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
    Класс является практически новым тегом, но поскольку он является производным от уже существующего класса, то вместо определения абсолютно нового тега определяются атрибуты существующих тегов. Тег <Н1
    class=title> содержит все атрибуты тега <Н1>, кроме заданных в определении класса: ширина шрифта, цвет фона и текста.
    Можно использовать классы для приспособления существующих тегов HTML к собственным потребностям. После того как тег вставлен в документ, он уже не может быть изменен. Пока наша страница является статической. Как мы увидим позже, DHTML позволяет переопределить стили, после воспроизведения страницы в окне броузера. Например, можно указать, что цвет свойства тега <Н1> изменится, когда указатель мыши будет находиться на нем или пользователь выполнит другое действие. Броузер распознает действия пользователя и генерирует события для каждого из них. Если предоставить соответствующий обработчик событий, то документ будет реагировать на эти события.



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

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

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

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

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

    EnterFocusColor.

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

    LeaveFocusColor.

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

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

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

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

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

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


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

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

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

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

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

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

    Private Sub UserControl_Resize()

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

    End Sub

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

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

    Appearance

    KeyDown

    MouseUp

    OLEGiveFeedback

    Backcolor

    KeyPress

    MultiLine

    OLESetData

    Click

    KeyUp

    OLECompleteDrag

    OLEStartDrag

    Change

    Max Length

    OLEDrag

    PasswordChar

    DblClick

    MouseDown

    OLEDragDrop

    Refresh

    Enabled

    Mouselcon

    OLEDragMode

    Text

    Font

    MouseMove

    OLEDragOver

    ToolTip

    ForeColor

    MousePointer

    OLEDropMode

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


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

    EnterFocusColor.

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

    LeaveFocusColor.

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

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

    MandatoryColor.

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

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

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

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

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

    Свойство

    Тип данных

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

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

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

    EnterFocusColor LeaveFocusColor Mandatory MandatoryColor

    OLECOLOR OLECOLOR Boolean OLECOLOR

    &HOOFFFF &HFFFFFF False &HFFOOOO

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

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

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

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

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

    Const m_def_Mandatory =


    False

    Const m_def_EnterFocusColor = &HFFOOFF

    Const m_def_MandatoryColor = &HFF

    Const m_def_LeaveFocusColor = &HFFFFFF

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

    Dim m_Mandatory As Boolean

    Dim m_EnterFocusColor As Variant

    Dim m_MandatoryColor As OLE_COLOR

    Dim m_LeaveFocusColor As OLE_COLOR

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

    Enum Flat3D

    Flat

    [3D]

    End Enum

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

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

    Public Property Get Appearance() As Flat3D

    Appearance = Text1.Appearance

    End Property

    Public Property Let Appearance(ByVal New Appearance As Flat3D)

    Text1.Appearance() = New Appearance

    PropertyChanged "Appearance"

    End Property

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

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

    Public Property Let MandatoryColor(ByVal New_MandatoryColor As _

    OLE_COLOR)

    m_MandatoryColor = New_MandatoryColor

    If m_Mandatory Then Text1.Backcolor = New_MandatoryColor

    PropertyChanged "MandatoryColor"

    End Property

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

    Enum ReqOpt

    [Optional]

    Required

    End Enum

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


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

    Public Property Get Mandatory() As ReqOpt

    Mandatory = m_Mandatory

    End Property

    Public Property Let Mandatory(ByVal New_Mandatory As ReqOpt)

    m_Mandatory = New Mandatory

    If m Mandatory = Required Then

    Text1.Backcolor = m_MandatoryColor

    Else

    Text1.Backcolor = m_def_LeaveFocusColor

    End If

    PropertyChanged "Mandatory"

    End Property

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

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

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

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

    Private Sub Textl_LostFocus ()

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

    Text1.BackColor = m_MandatoryColor

    Else

               Text1.BackColor = LeaveFocusColor

    End  If

    End Sub

    Примечание

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

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

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


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

    Private Sub Textl_GotFocus()

    Text1.Backcolor = EnterFocusColor

    End Sub

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

    • Ввод данных

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

    • Введение в SQL

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

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

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

    Примечание

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


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

    Имеется возможность разрабатывать пользовательские элементы управления ActiveX, которые расширяют возможности существующих элементов управления. Вряд ли найдется хоть один пользователь, который не хотел бы добавить "новые" возможности к существующим элементам управления. Многие программисты добавляют новые возможности к стандартным элементам управления ActiveX с помощью соответствующего кода в их приложении. Например, недостатком элемента управления ComboBoxt является то, что любые новые значения, добавляемые в поле ввода, не добавляются в список значений. Другими словами, элемент управления ComboBox позволяет ввести новое значение, но это значение автоматически не добавляется к списку значений. Многие программисты перехватывают нажатие клавиши ENTER в элементе управления ComboBox и вручную добавляют новые значения в список элемента управления.
    Уверен, что каждый программист хотел бы добавить свое собственное небольшое усовершенствование к стандартному элементу управления VB. В этом разделе рассматривается, как доработать существующие элементы управления ActiveX и оформить их в виде заказных (специальных) элементов управления. Очевидно, что нельзя изменить базовые функции существующего элемента управления, поскольку нет никакого доступа к их коду. Но можно сделать очень многое, добавляя некоторый код и оформляя существующий элемент управления вместе с добавленным кодом как новый элемент управления.
    В этом разделе будет показано, как можно доработать элемент управления TextBox. Заказной элемент управления CTextBox представляет собой обычный элемент TextBox, который изменяет свое поведение в зависимости от того, принимает ли он обязательное или необязательное поле.
    На компакт-диске, в папке этой главы, можно найти проект CLDesign, который демонстрирует, как в режиме конструирования можно добавить к элементу управления дополнительные возможности для режима выполнения. Вы когда-либо пробовали задать значение элемента управления Scrollbar в режиме конструирования, двигая его бегунок? Большинство пробовали это, и результатом было перемещение всего элемента управления на форме. Значение элемента управления ScrollBar не может быть установлено визуально в режиме конструирования. Интересное расширение элемента управления ScrollBar может обеспечить механизм, который позволит разработчику определять, должен ли элемент управления перемещаться или должен функционировать так, как и во время выполнения, даже в том случае, если он находится в режиме конструирования. Проект CLDesign достаточно прост, и поэтому не будет обсуждаться в этой главе. Все то, что нужно знать для того, чтобы заставить элемент управления вести себя в режиме конструирования так же, как и в режиме выполнения - это свойство EditAtDesignTime объекта UserControl. Если установить это свойство равным True, команда будет добавлена к контекстному меню. Выполните щелчок правой кнопкой на элементе управления тестовой формы и выберите команду Edit. Элемент управления будет вести себя так, как будто он находится в режиме выполнения. Например, если он содержит элемент управления Scrollbar, то можно изменить значение элемента управления с помощью мыши. Элемент управления CLDesign, показанный на форме, изображенной на рис. 16.17, позволяет разработчику выбирать начальный цвет в режиме конструирования с помощью трех полос прокрутки.
    Доработка существующих элементов управления

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



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

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



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

    В предыдущем параграфе рассмотрены методы объекта
    FileSystemObject, которые позволяют обращаться к файлам на локальном диске. Объект FileSystemObject поддерживает много других методов для операций с файлами и папками, (позволяющими копировать и удалять файлы и папки), которые более интересны для программиста на VB, чем методы доступа к текстовым файлам. Хотя в Visual Basic имеются операторы и функции для доступа к файловой системе, но объект FileSystemObject предоставляет целостный, иерархический подход к файловой системе, поэтому рекомендуется использовать именно его.
    Примечание
    Только объект FileSystemObject позволяет обратиться к файловой системе из сценария.
    CopyFile. Копирует один или более файлов из одной папки в другую. Он имеет следующий синтаксис.
    FSys.CopyFile source, destination, overwrite
    Аргумент
    source - путь к файлу-источнику. Он может содержать и символы шаблона (для копирования нескольких файлов). Аргумент destination - путь к папке-приемнику, в которую копируются файлы. Он, что естественно, не может содержать символы шаблона. Последний аргумент — overwrite — необязателен и принимает булево значение (True/False) и определяет, будет ли существующий файл перезаписан. Метод CopyFile генерирует ошибку выполнения, если у файла-приемника установлен атрибут "только для чтения" независимо от значения аргумента overwrite. Свойство Attributes рассмотрено в примере обновления файла с установленным атрибутом "только для чтения".
    CopyFolder.
    Копирует папку, включая подпапки (это называется рекурсивным копированием). Синтаксис метода CopyFolder приведен ниже.
    FSys.CopyFolder source, destination, overwrite
    Здесь
    source - путь к папке-источнику (из которой копируются файлы), может содержать символы шаблона при копировании группы файлов. Destination — путь к папке-приемнику (в которую копируются файлы) — не может содержать символы задания шаблона. Последний аргумент overwrite - необязателен и его значение (True/False) определяет, можно ли существующие файлы в папке перезаписывать. Чтобы защитить уже существующие файлы в папке-приемнике, установите его в False.

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

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

    где

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

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

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

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

    FSys.DeleteFile filespec, force

    Здесь

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

    DeleteFolder.

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

    FSys.DeleteFolder folderspec, force

    Здесь

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

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

    FSys.MoveFile source, destination

    Здесь

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

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

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

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

    FSys.MoveFolder source, destination

    где

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


    FileExist, FolderExists.

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

    FSys.FileExists(fileSpec)

    и

    FSys.FolderExists(folderSpec)

    GetFile, GetFolder.

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

    Примечание

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

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

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

    Переменная

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

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

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

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

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

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

    Примечание

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


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

    RecordSet
    Связанные с данными элементы управления могут отображать поля текущей записи в объекте RecordSet элемента управления Data, но необходимо также обращаться к значениям полей из кода программ. К полям можно обращаться через объект Field набора записей RecordSet. Следующее выражение задает поля (столбцы) набора записей RecordSet.
    recordset.Fields
    Переменная recordset представляет собой объект RecordSet (это может быть свойство RecordSet элемента Data, например, Data I. RecordSet или переменная с именем RecordSet).
    Обращайтесь к отдельным полям по имени поля или его порядковому номеру в таблице Если элемент управления Data с именем Datal связан с таблицей Titles базы данных BIBLIO, то можно обращаться к полю Title текущей записи с помощью любого из следующих операторов.
    bookTitle = Datal.Recordset.Fields(0)
    bookTitle = Datal.Recordset.Fields ("Title")
    Другие два свойства, представляющие интерес - это свойство RecordCount объекта RecordSet (возвращает число записей в RecordSet) и свойство Count объекта Fields (возвращает число полей в строке RecordSet). Эти два свойства фактически являются размерами объекта RecordSet.. Число записей в RecordSet элемента Datal определяет строка
    Datal.RecordSet.RecordCount
    а число столбцов в этом же RecordSet — следующая строка:
    Datal.RecordSet.Fields.Count
    VB6 в действии: просмотр RecordSet
    Разработаем небольшое приложение, демонстрирующее, как можно просматривать записи в наборе RecordSet и обрабатывать их поля. Обработка довольно тривиальна: помещение строк объекта RecordSet в элемент управления ListBox. Программа демонстрирует, как просматривать RecordSet и извлекать конкретные поля.
    Чтобы создать это приложение, выполните следующие действия.
    1. Откройте новый проект и поместите элементы управления ListBox и Data на форму (рис. 17.14).
    2. Установите свойство Visible элемента управления Data в False. Нельзя использовать элемент управления Data для перемещения по RecordSet после того, как все записи отображены в элементе управления ListBox.

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

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


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

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

    Private Sub Form_Load()

    Dim i As Integer

    Data1.Refresh

    Data1.Recordset.MoveLast

    Data1.Recordset.MoveFirst

    For i = 1 To Data1.Recordset.RecordCount

    List1.AddItem Data1.Recordset.Fields(1)

    Data1.Recordset.MoveNext

    Next

    End Sub

    Совет

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

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

    Seek operator, key

         Параметр

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

    •   = (равно)

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

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

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

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

    Параметр

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


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

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

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

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

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

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

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


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

    Примечание

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

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

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


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

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

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


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

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

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

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

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

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

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

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

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

    RecordSource

    TITLES

    Titles

    PUBLISHERS

    Publishers

    AUTHORISBN

    Title Author

    AUTHORS

    Authors

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

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

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


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

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

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

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

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

    Private Sub Form Load ()

    PUBLISHERS.Refresh

    AUTHORISBN.Refresh

    AUTHORS.Refresh

    PUBLISHERS.Recordset.Index = "PrimaryKey"

    AUTHORISBN.Recordset.Index = "ISBN"

    AUTHORS.Recordset.Index = "PrimaryKey"

    End Sub

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

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

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

    Private Sub TITLES_Reposition()

    PUBLISHERS.Recordset.Seek "=",

    TITLES.Recordset.Fields ("PubID")

    If PUBLISHERS.Recordset.NoMatch Then

    lblPublisher.Caption = "***"

    AUTHORISBN.Recordset.Seek "=", _

    TITLES.Recordset.Fields ("ISBN")

    If AUTHORISBN.Recordset.NoMatch Then

    lblAuthor.Caption = "***"

    Exit Sub

    End If

    AUTHORS.Recordset.Seek " ", _

    AUTHORISBN.Recordset.Fields ("Au_ID")

    End Sub

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


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

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

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

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


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

    Существуют SQL-операторы для всех типов операций, которые можно выполнять с базой данных. SQL-операторы используются для создания новой базы данных и добавления в нее таблиц и индексов. Можно использовать SQL-операторы для обновления базы данных. SQL - функционально полный язык для управления базами данных, но наиболее часто он используется для выборки данных из базы. Выборка данных из базы называется запросом к базе данных, а SQL-операторы для осуществления запросов к базе данных называются командами выбора (Select-statements), потому что они содержат глагол SELECT (Выбирать).
    Общий формат команд выбора следующий. SELECT (список полей) FROM (список таблиц) WHERE (выражение).
    Примечание
    Ключевые слова SQL в книге печатаются прописными буквами, но SQL не чувствителен к регистру. Использование верхнего регистра — вопрос стиля. Это помогает читателям, которые не знакомы с SQL, находить ключевые слова и лучше понимать его сложные элементы.
    (список полей)
    Эта часть команды SQL — список полей, разделенных запятыми, которые будут включены в запрос. Если имя элемента (поля или таблицы) содержит пробел, необходимо заключить его в квадратные скобки ([ ]) Например, чтобы включить в запрос поле Customer Name (Имя заказчика), нужно ввести [Customer Name].
    Полное имя каждого поля предваряется именем таблицы, которой оно принадлежит Эта запись обеспечивает уникальность имен полей, даже если несколько таблиц имеют поля с одинаковыми именами. Например, полное имя поля Total (Итог) в таблице Customer Orders (Счета заказчика) — [Customer Orders] Total. Если имя поля Total не появляется ни в какой другой таблице, то имя таблицы можно опустить и обратиться к этому полю как Total.
    Результат выполнения запроса Select содержит записи таблицы, соответствующие критериям, и строку заголовков. Заголовки — это имена полей, задаваемые при проектировании базы данных. При отображении результатов запроса с помощью связанного с данными элемента управления Grid (Сетка) в качестве заголовков отображаются имена полей. Чтобы изменить заголовки, используйте ключевое слово AS после имени поля. Это удобно, когда для имени поля таблицы возникает неоднозначность в контексте запроса, содержащего несколько таблиц с совпадающими именами в различных таблицах. Например, если имеется поле Total в таблице Customer Orders, то можно отобразить заголовок Order Total этого поля следующим образом.

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

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

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

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

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

    (выражение)

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

    field_name BETWEEN value1 AND value2

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

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

    SELECT Customers.CompanyName, Customers.ContactTitle,

    Customers.City, Customers.Country FROM Customers WHERE

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

    ORDER BY Customers.Country

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


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

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

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


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

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

    Символ

    Пояснение

    Пример

    *

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

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

    ?

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

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

    #

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

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

    []

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

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

    [!]

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

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

    [-]

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

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

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

    SELECT Customers.CompanyName, Customers.ContactName,

    Customers.Country, Customers.City FROM Customers

    ORDER BY Customers.Country, Customers.City

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

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



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

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


    Все элементы управления помещаются между двумя тегами. Атрибут NAME (не обязательный) — имя формы. Он используется, если страница содержит несколько форм Атрибут ACTION — имя приложения на сервере, вызванного для обработки информации. Атрибут METHOD определяет, как значения элементов управления передаются на сервер. Информация, необходимая броузеру для установления контакта с приложением на сервере, содержится в теге
    .
    Перечислим элементы управления, поддерживаемые HTML. На рис. 19.7 показана Web-страница с формой, содержащей большинство встроенных элементов управления HTML. HTML-код для этой страницы приведен в параграфе "Web-страница FORM.HTW
    Элемент управления TEXT
    Элемент управления Text - это поле, в которое пользователь вводит текстовую строку (название, адрес и т.п.). Чтобы вставить элемент управления Text на форму, используется следующий тег.

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

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

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


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

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

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

    Поскольку элемент управления TextArea позволяет задать несколько строк исходного текста, он вставляется не обычным тегом , а парой тегов