Спецификации элемента управления
FLEXLabel
Элемент управления FLEXLabel должен отображать надпись (как и обычный элемент Label), то есть в нем должны быть предусмотрены свойства Caption и Font, которые позволяют разработчику задавать текст и его вид. В дополнение, элемент управления FLEXLabel может выравнивать надпись по вертикали и горизонтали. Эта возможность будет обеспечиваться свойством TextAlignment, возможные значения которого показаны в табл. 16.1.
Таблица 16.1. Значения свойства TextAlignment элемента управления FLEXLabel
Значение Описание
0 Слева вверху
1 Вверху посередине
2 Справа вверху
3 В центре слева
4 В центре
5 В центре справа
6 Слева внизу
7 Внизу посередине
8 Справа внизу
Названия, указанные в колонке Описание,
отображаются в раскрывающемся списке свойства TextAlignment. Заметим, что свойства с ограниченным набором значений отображаются в виде раскрывающегося списка в окне свойств. Этот список содержит описательные имена (вместо чисел), и разработчик может выбрать только корректное значение.
Аналогично, текстовые эффекты управляются с помощью свойства
Effect, чьи значения приведены в табл. 16.2.
Таблица 16.2. Значения свойства Effect элемента управления FLEXLabel
Значение
| Описание | ||
0 | Нет | ||
1 | Слабо тисненный | ||
2 | Средне тисненный | ||
3 | Сильно тисненный | ||
4 | Слабо выпуклый | ||
5 | Средне выпуклый | ||
6 | Сильно выпуклый |
Подобно свойству TextAlignment, свойство Effect имеет мало значений, которые задаются в окне свойств содержательными именами.
В дополнение к новым свойствам, элемент FLEXLabel должен также предусматривать стандартные для элемента управления Label свойства, такие как Font, Tag, BackColor и т.д. Разработчики ожидают увидеть эти свойства в окне свойств и, следовательно именно там необходимо их реализовать. Элемент управления FLEXLabel не имеет никаких дополнительных методов, но он должен предусматривать стандартные методы элемента управления Label, как например, метод Move. Аналогично, хотя элемент не инициирует никаких специальных событий, он должен поддерживать стандартные события элемента управления Label например, события мыши и клавиатуры.
Большая часть функциональных возможностей элемента управления уже реализованы, и должен существовать простой способ заимствования их у других элементов вместо того чтобы реализовывать их самостоятельно. На самом деле так и есть Visual Basic снабжен мастером который генерирует код стандартных частей элемента управления а разработчику только остается написать код для дополни тельных свойств.
SQL-объединения
Объединения определяют, как связываются несколько таблиц в запросе. Существует три типа объединений.
• Left Outer (Левое внешнее)
• Right Outer (Правое внешнее)
• Inner (Внутреннее)
Операция объединения соединяет все строки одной таблицы со строками другой таблицы. Объединения обычно сопровождаются условием, которое определяет какая запись на каждой стороне объединения появится в RecordSet.
Left Outer (Левое внешнее объединение). Это объединение отображает все записи из левой таблицы и только те записи правой таблицы, которые удовлетворяют задаваемым пользователем критериям. Это объединение имеет следующий синтаксис.
FROM (первичная таблица) LEFT JOIN (вторичная таблица) ON
(первичная таблица).(поле) (сравнение) (вторичная таблица).(поле)
В левом внешнем объединении всем записям в первичной таблице поставлены в соответствие записи из вторичной таблицы, отвечающие заданным критериям. Записи из левой таблицы (имя которой указано слева от ключевого слова LEFT JOIN) включаются даже тогда, если для них нет соответствующих записей во вторичной таблице.
Right Outer (Правое внешнее объединение). Это объединение подобно левому внешнему объединению, но в данном случае отображаются все записи правой таблицы и соответствующие критерию записи левой таблицы. Это объединение имеет следующий синтаксис.
FROM (вторичная таблица) RIGHT JOIN (первичная таблица) ON
(вторичная таблица).(поле) (сравнение) (первичная таблица).(поле)
В правом внешнем объединении всем записям в первичной таблице поставлены в соответствие отвечающие заданным критериям записи вторичной таблицы. Записи первичной таблицы включаются даже тогда, если для них нет соответствующих записей во вторичной таблице.
Внешние объединения возвращают огромные наборы записей. Поэтому необходимо избегать их использования без особой необходимости. С другой стороны, внутренние объединения просты и с ними строят большинство команд SQL.
Inner (Внутреннее объединение). Это объединение возвращает строки обеих таблиц включаемых в операцию, которые соответствуют заданным критериям. Внутреннее объединение имеет следующий синтаксис.
FROM (первичная таблица) INNER JOIN (вторичная таблица) ON
(первичная таблица).(поле) (сравнение) (вторичная таблица).(поле)
Рассмотрим подробнее несколько примеров. В простейшем виде внутренние объединения похожи на предложения WHERE. Следующий SQL-оператор объединяет записи из таблиц Titles и Publishers базы данных BIBLIO, если у них совпадают поля PubID. Она возвращает набор записей с именами всех книг и их издателей.
SELECT Titles.Title, Publishers.Name FROM Titles, Publishers
WHERE Titles.PubID = Publishers.PubID
Можно получить такой же RecordSet, используя внутреннее объединение.
SELECT Titles.Title, Publishers.Name FROM Titles, Publishers,
INNER JOIN Titles ON Titles.PubID = Publishers.PubID
Результаты работы этой команды показаны ниже.
Рассмотрим более сложную операцию объединения. На этот раз необходимо получить из базы данных BIBLIO все названия изданий наряду с их авторами и издателями. Следующее утверждение действительно сложно и отражает реальную ситуацию.
SELECT Titles.Title, Titles.ISBN, Authors.Author,
Titles.[Year.Published], Publishers.[Company Name] FROM
(([title author] INNER JOIN Titles ON
[title author].ISBN = Titles.ISBN) INNER JOIN Authors ON
[title author].Au ID = Authors.Au ID) INNER JOIN Publishers ON
Titles.PubID = Publishers.PubID ORDER BY Titles.Title
Результаты работы команды показаны ниже.
В предыдущей команде в квадратные скобки заключены имена полей, которые содержат пробелы. Все имена полей предваряются соответствующим именем таблицы (хотя большинство имен полей уникально), чтобы сделать команду более легкой для чтения.
В списке полей устанавливаются следующие поля:
• Titles.TitIe - название книги;
• Titles.ISBN - ISBN код книги;
• Authors.Author — автор книги;
• Titles.[Year Published] — год публикации книги;
• Publishers. [Company Name] — издатель книги.
Вы, возможно, помните, что база данных BIBLIO содержит четыре таблицы, а наш запрос требует данных из всех таблиц Фактически, никакие данные из таблицы Title Author в результатах запроса не отображаются, но эта таблица связывает названия и имена авторов (через ISBN код книги), поэтому ее необходимо использовать в SQL-запросе.
Поля не выбираются из каждой конкретной таблицы непосредственно. Их получают из ряда внутренних объединений. Первое внутреннее объединение следующее.
[title author] INNER JOIN Titles ON [title author].ISBN =
Titles.ISBN
Это выражение извлекает (и соединяет) каждое название издания с иден тификатором его автора, если ISBN код в обеих таблицах совпадает. В сущности, будет получен идентификатор автора для каждого издания. Назовем это выражение (которое является объектом RecordSet) Title-AuthorIDs. Этот RecordSet помещен в круглые скобки и соединен с другим RecordSet.
(Title-AuthorIDs) INNER JOIN Authors ON [title author].Au_ID =
Authors Au ID
Этот RecordSet соединяет идентификаторы авторов предыдущего RecordSet с фактическими именами авторов. Мы создали RecordSet с именами авторов и названиями изданий. Назовем его Titles-Author. Последняя операция объединения соединяет RecordSet, который содержит имена авторов и изданий, с таблицей Publishers следующим образом.
(Titles-Author) INNER JOIN Publishers ON Titles.PubID =
Publishers.PubID
На этот раз идентификаторы издателей должны совпадать. Результирующий RecordSet содержит названия изданий, авторов и издателей и является источником данных. Последнее ключевое слово в этой SQL-команде — ORDER BY — задает порядок отображения заказов.
Страница
ALLPRODS.ASP
Страница ALLPRODS.ASP отображает список категорий товаров в базе NWIND (рис. 22.8).
ASP-страница читает наименования категорий товаров и отображает их в виде гиперссылок. Когда пользователь выбирает гиперссылку, он переходит на другую страницу (PRODCAT.ASP), которая отображает все товары, принадлежащие этой категории, их цены и количество (рис. 22.9).
Если посмотреть на код страницы PRODCAT.ASP, то можно заметить, что в ней мало HTML-кода, поскольку это серверный сценарий, который открывает базу данных NWIND, создает набор записей с наименованиями категорий и отображает их в виде гиперссылок.
Наибольший интерес представляет строка, создающая гиперссылки. Если не обращать внимания на обрамление этого выражения тегами серверного сценария, то выглядит оно как обычный HTML-тег для создания гиперссылки. Поскольку имя гиперссылки и ее целевая страница в момент создания этого файла неизвестны, поместим в него выражения, которые будут замещены при обработке файла активной серверной страницей.
Рис. 22.8. Страница ALLPRODS.ASP: категории товаров в базе данных NWIND в виде гиперссылок
Рис. 22.9. файл PRODCAT.ASP: товары в категории, выбранной на рис. 22.8
Обратите внимание: все гиперссылки обращаются к одному
URL на сервере (файл PRODCAT.ASP), но каждая ссылка передает другое значение параметра. Этим значением является идентификатор (ID) категории - поле записи, хранящей сведения о каждом товаре. Страница PRODCAT ASP использует это значение для выбора товаров заданной категории. В качестве второго параметра передается наименование категории. Этот параметр не используется при выборке записей -он нужен только для отображения наименования категории. Если опустить этот параметр, то страница PRODCAT.ASP откроет таблицу Categories (Категории), чтобы найти наименование выбранной категории, отобразить его в заголовке страницы, а затем открыть таблицу Products (Товары) для извлечения наименований товаров. Передавая наименование категории в качестве второго параметра, мы избавляем сценарий от необходимости установления еще одной связи с базой данных для получения уже известной информации.
Программа 22.8. Файл ALLPRODS ASP
<HTML>
<%
Set DBObj =
Server.CreateObject("ADODB.Connection")
DBObj.Open "NWindDB"
SQLQuery = "SELECT CategoryID, CategoryName FROM Categories"
Set RSCategories = DBObj.Execute(SQLQuery)
%>
<CENTER>
<H1>List Of Product Categories</H1>
</CENTER>
<TABLE>
<% Do While Not RSCategories.EOF %>
<TR>
<TD> <FONT FACE-"Verdana" SIZE=2>
<% CategoryName = RSCategories ("CategoryName") %>
<A HREF="/ASPages/ProdCat.asp?CategoryID= _
<% "RSCategories ("CategoryID") %>&CategoryName= _
<% =CategoryName %> "> <% = CategoryName %> </A>
</FONT>
</TD>
</TR>
<%
RSCategories.MoveNext
Loop
DBObj.Close
%>
</HTML>
Файл PRODCAT ASP, обрабатывающий запросы, сделанные страницей ALLPRODS ASP, несколько сложнее Сначала он извлекает значения параметров, переданных клиентом Операторы
ReqCategory=Request.QueryString ("CategoryID")
ReqName=Request.QueryString ("CategoryName")
сохраняют эти значения в переменных ReqCategory и ReqName
Семейство QueryString хранит эти значения для дальнейшего использования Прочесть их, воспользовавшись соответствующими именами, не составляет труда Значение переменной ReqCategory необходимо для построения SQL-оператора, извлекающего записи из таблицы Products
SQLQuery = "SELECT ProductName, UnitPrice, UnitInStock _
FROM Products WHERE CategoryID = " & ReqCategory & " _
ORDER BY ProductName"
Этот SQL-оператор возвращает набор записей, содержащий сведения о товарах из выбранной категории. Затем сценарий просматривает записи и выводит их в строках таблицы. Фрагмент кода, который строит таблицу, выглядит достаточно сложно, поскольку в него входят HTML-операторы и операторы сценария. Чтобы понять, как он работает, замените каждое выражение, заключенное в теги <% и %>, соответствующем значением (например, наименованием товара в выражении <% = RSProducts ("ProductName") %> и т.д.).
Программа 22.9. Файл PRODCAT.ASP
<HTML>
<%
ReqCategory=Request. QueryString ("CategoryID")
ReqName=Request. QueryString ("CategoryName")
Set DBObj = Server.CreateObject ("ADODB.Connection")
DBObj.Open "NWindDB"
SQLQuery = " SELECT ProductName, UnitPrice, UnitsInStock FROM Products
WHERE CategoryID = " & ReqCategory S " ORDER BY ProductName"
Set RSProducts = DBObj.Execute(SQLQuery)
%>
<CENTER>
<H1>Query Results</H1>
<H3>List of products in category <% = ReqName %></H3>
</CENTER>
<TABLE>
<% Do While Not RSProducts.EOF %>
<TR>
<TD> <FONT FACE="Verdana" SIZE=2>
<% = RSProducts ("ProductName") & " (" &
RSProducts ("UnitPrice") & ")" %>
</FONT></TD>
<TD><FONT FACE="Verdana" SIZE=2>
<% = RSProducts ("UnitsInStock") %>
</FONT></TD>
</TR>
<%
RSProducts.MoveNext
Loop
%>
</TABLE>
</HTML>
Этот пример достаточно прост. Если некоторые его фрагменты выглядят непонятно, то отделите выражения, вычисляющиеся на сервере, от HTML-кода. При этом можно использовать символические имена - ProductName и UnitPrice. Убедившись, что код работает, замените их действительными переменными серверного сценария.
Структура базы данных
BIBLIO
Одна из двух стандартных баз данных, поставляемых с Visual Basic, называется BIBLIO. База данных BIBLIO имеет простую структуру, почти тривиальную, но демонстрирует многие из рассмотренных ранее тем. Откройте базу BIBLIO с помощью Visual Data Manager и исследуйте ее структуру.
База BIBLIO содержит заголовки книг имена авторов и издателей в виде четырех таблиц (рис. 17.11). Вместо имен полей каждой таблицы на рисунке отображены некоторые содержащиеся в них данные. Приведены только те поля, которые необходимы, чтобы показать связи между таблицами. Имена полей отображены как заголовки столбцов. Первое правило при проектировании базы данных — не дублировать данные. Хранение имени автора совместно с заголовками нарушило бы это правило, поскольку автор обычно пишет больше одной книги. В этом случае необходимо было бы повторить имя автора в более чем одной строке таблицы Titles. Имена авторов хранятся в отдельной таблице – Authors. Это же справедливо и для издателей. Так как каждый издатель появляется во многих книгах то информация об издателях в таблице Titles не хранится. Зачем повторять адрес издателя с каждым заголовком?
Пока обосновано существование трех таблиц в базе данных. Но в базу данных BIBLIO входит четвертая таблица. Каждая книга может иметь более одного автора, а имя автора может появляться не только в одном заголовке Хранение имен каждого из авторов или их ID для каждого наименования книги потребовало бы соответствующих полей в таблице Titles. Отличие поля с ID автора от поля PubID (ID издателя) состоит в том, что книга может иметь несколько авторов, и необходимо предусмотреть ряд полей для хранения идентификаторов Author ID (AuthorIDl, AuthorID2 и т.д.). Очевидно, что имена авторов не могут обрабатываться подобно именам издателей.
Рис. 17.11. Структура базы данных BIBLIO
Таблица Title Author находится между таблицами Titles и Authors и соединяет их с парой полей — ISBN книги и ID автора. Для просмотра имени автора конкретной книги необходимо выполнить следующие действия.
1. Найдите искомый заголовок в таблице Titles.
2. Прочитайте значение ISBN в Title и используйте его как ключ для нахождения соответствующей строки (строк) в таблице Title Author.
3. Из каждой соответствующей строки таблицы Title Author прочтите ID автора и используйте его в качестве ключа для поиска имени автора в таблице Authors.
Тем, кто не знаком с программированием баз данных, эта процедура может показаться сложной, но это не так. Далее в этой главе показаны два способа поиска конкретных записей с помощью ключей. Описанная методика не сможет эффективно работать, если нет способа быстрого поиска записи по значению конкретного поля. А он может быть выполнен при соответствующей индексации таблиц.
Как видно, индексы - неотъемлемая часть разработки базы данных. Например, таблица Title Author (Автор книги) индексируется по полю ISBN. Если необходимо обеспечить поиск в противоположном направлении (дано имя автора, а требуется найти книги, в которых оно появляется), необходимо проиндексировать таблицу Title Author по полю AuID. Очевидно, таблица Authors (Авторы) должна быть индексирована по полю AuID, так как в таблице Title Author хранятся ID авторов, а не их имена. Таблица Publishers (Издатели) индексируется по полю PubID, чтобы можно было быстро перейти от названия книги к ее издателю.
Структура HTML-документов
HTML-файлы — это файлы, которые содержат текст и команды форматирования. Командами являются строки со специальным синтаксисом, что позволяет броузеру отличить их от текста. Каждый тег HTML заключен в угловые скобки (<>). Тег <I> подключает атрибут курсива, и текст выделяется курсивом, пока не встретится тег </I>. Следующая строка
HTML is <I>the</I> language of the Web.
воспроизводится броузером без тегов, а слово the выделяется курсивом.
HTML is the
language of the Web.
Большинство тегов (обычно они следуют парами) влияет на часть текста. Один тег включает данный атрибут, а другой - отключает его. Примером может служить тег <I>, <В> и <U>, которые включают атрибуты курсив, полужирный и подчеркивание. Тегу, отключающему атрибут, всегда предшествует символ "/". Для отображения части текста полужирным шрифтом ее заключают в теги <В> и </В>.
Теги не чувствительны к шрифтам. Можно ввести теги курсива в виде <i> и </i>. В этой книге и на прилагающемся компакт-диске используются заглавные буквы для HTML-команд (чтобы выделить их из остального текста документа). Большинство WYSIWYG-редакторов HTML вставляют HTML-теги в виде строчных символов.
Примечание
Наличие второго тега — для отключения атрибута — не всегда является обязательным. Например, не нужно использовать пару
<Р> и </Р> для вставки новой строки: это с успехом сделает один тег <Р>.
Структура HTML-документа показана ниже. Если сохранить следующие строки в текстовом файле с расширением htm, а затем открыть его с помощью Internet Explorer, то вы увидите традиционное приветствие.
<HTML>
<HEAD>
<TITLE>Your Title Goes Here </TITLE>
</HEAD>
<BODY>
Hello, World!
</BODY>
</HTML>
Базовый HTML-документ следует начинать тегом
<HTML> и завершать тегом </HTML>. Раздел заголовка документа выделяется тегами <HEAD> и </HEAD>. Обычно в него помещаются следующие элементы:
• название документа;
• теги МЕТА и BASE;
• сценарий.
Название документа — это текст в заголовке окна броузера. Он задается тегами <TITLE> и </TITLE>. МЕТА-теги не отображаются на экране, но содержат полезную информацию о содержании документа: описание и ключевые слова, используемые устройством поиска. Например:
<HTML>
<HEAD>
<TITLE>Your Title Goes Here</TITLE>
<META NAME="Keywords" CONTENT= _
"health, nutrition, weight control, _
chronic illness">
</HEAD>
</HTML>
Атрибуты
Многие теги HTML распознают специальные ключевые слова, которые называются атрибутами. Например тег <BODY>, отмечающий начало тела документа, распознает атрибуты BGCOLOR и BACKGROUND, задающие цвет фона и изображение являющееся фоном документа. Можно задать цвет фона документа (если нет фонового изображения) и ею текста используя атрибуты BGCOLOR и TEXT
</HTML>
</HEAD>
<TITLE>Your Title Goes Here</TITLE>
</HEAD>
<BODY BACKGROUND="paper.jpg">
<Hl>Tiled Background</Hl>
<P>The background of this page was created with a small image,
which is tiled vertically and horizontally by the browser.
(Фон страницы создан с помощью небольшого изображения,
воспроизведенного броузером в виде повторяющейся мозаики)
<BR>
The image was designed so that its left edge matches with its
riqht edge and its top edge matches with the bottom edge. Notice
that you can't detect where one instance ends and the next one
begins.
(Верхний срез изображения соответствует нижнему срезу. Заметьте: обнаружить, где оно начинается и кончается, нельзя.)
</BODY>
</HTML>
Мозаика фонового изображение начинается в левом верхнем углу и проходит через весь экран вниз (рис. 19.1). Можно создать привлекательный фон, используя непрерывную мозаику и составить фоновое изображение из мелких и крупных фрагментов. Будьте внимательны, соединяя границы фрагментов изображения, иначе можете увидеть не то, что ожидали. Конечно, в этом примере текст любого цвета будет нечитабельным кроме случая когда он будет достаточно крупным и иметь хорошую контрастность.
Рис. 19.1. Фоновое изображение в виде мозаики
Связывание и встраивание объектов во время выполнения программы
Рассмотрим создание и встраивание объектов во время выполнения приложения на примере приложения OLERTime (папка этой главы на компакт диске). Приложение OLERTime демонстрирует следующие возможности:
• вставку объекта;
• выбор между связыванием и встраиванием;
• установку размеров окна контейнера элемента управления или размера объекта;
• отображение информации об объекте.
Возможность встраивания и связывания объектов с элементом управления OLE Container позволяет открыть диалоговое окно Insert Object (Вставка объекта) из кода программы. В предыдущих примерах это выполнялось вручную. Операции выполняются непосредственно из окна VB-приложения пользователь может выби рать объекты и самостоятельно устанавливать некоторые их свойства. Главная форма приложения показана на рис. 14.9.
Рис. 14.9. Главное окно приложения OLERTime
После щелчка на кнопке Insert Object (Вставка объекта), приложение отображает диалоговое окно Object Type (Тип объекта) (рис. 14.10), в котором можно установить режим изменения размеров (Stretch Object) и тип OLE-связи (встраивание или связывание). Если щелкнуть на кнопке ОК, то на экране появится диалоговое окно Insert Object, в котором определяется новый объект или выбирается существующий.
Рис. 14.10. Диалоговое окно Object Type приложения OLERTime
Для проверки приложения установите переключатели в диалоговом окне Object Type (Тип объекта) в положение Stretch Container Control и Embedded, после чего щелкните на кнопке ОК. В открывшемся диалоговом окне Insert выберите объект Excel Chart. В окне элемента управления появится диаграмма, содержащая произвольные данные. Из приложения OLERTime ее можно редактировать, масштабировать (так как установлен переключатель Stretch Container Control) и даже изменять, сохраняя в отдельном файле. Приложение можно остановить, запустить и загрузить в него диаграмму из отдельного файла.
VB6 в действии: приложение OLERTime
Для разработки приложения выполните следующие действия.
1. Откройте новый проект и присвойте форме имя frmOLE. Эта форма содержит элемент управления OLE Container, пять командных (Command) кнопок (см. рис. 14.9) и элемент управления Common Dialogs.
2. При помещении элемента управления OLE Container на форму появится диалоговое окно Insert Object (Вставка объекта). Щелкните на кнопке Cancel, чтобы поместить на форму пустой контейнер. Затем измените размеры окна элемента управления OLE Container и поместите на него командные кнопки (см. рис. 14.10).
3. Добавьте к проекту новую форму и поместите на нее элементы управления (см. рис. 14.10).
4.
Сохраните все формы и проект в новой папке. После этого добавьте фрагмент программы, который позволит выполнять следующие действия:
• отображать на экране второе окно (frmType) и активизировать диалоговое окно Insert Object;
• отображать информацию об объекте.
Откройте программу обработчика события Click кнопки Insert Object и введите следующие строки.
Private Sub cmdInsObj_Click()
frmType.Show
End Sub
Для отображения информации об объекте предусмотрена кнопка Object Info (вскоре мы узнаем, как объект выбирается и вставляется). После щелчка на этой кнопке выполняется следующий фрагмент программы (oleDisplay —
имя элемента управления OLE).
Программа 14.3. Обработчик события
Click для кнопки Object Info
Private Sub cmdObjInfo_Click()
Dim SourceText As String
Dim TypeText As String
Dim MsgText As String
SourceText = "The object's source file is " + oleDisplay. SourceDoc
' (Файл объекта источника:...)
TypeText = "The type of object is " + oleDisplay.Class
' (Тип объекта:...)
MsgText = SourceText + Chr(13) + TypeText
MsgBox MsgText, vblnformation, "Object Information"
' (Информация об объекте)
End Sub
Символ ввода новой строки (vbCrLF) позволяет разбить длинное сообщение на несколько коротких строк. Если встроенный (или связанный) объект - документ Word, то отобразится следующая информация.
The object's source file is C:\My Documents\FileName
The type of object is Word.Document
(FileName будет заменено именем файла, встроенным в элемент управления OLE) На рис. 14.11 показано, что отображает кнопка Object Info, если в элемент управления OLE Container встроен объект Excel Chart. Поскольку объект Excel Chart - вновь созданный, то поле SourceDoc пусто.
Рис. 14.11. Информация, выводимая приложением OLERTime, для связанного растрового изображения
Свойства SourceDoc и Class. Кнопка Object Info позволяет отобразить значения свойств SourceDoc и Class. Значение свойства SourceDoc — это имя связанного или встроенного файла. Свойство Class устанавливает или возвращает имя класса встроенного объекта, которое, по сути, является его типом. Объекты других типов — это таблицы Excel (Excel.Sheet), растровые изображения, созданные программой Paint, и объекты, которые мы создадим в этой главе чуть позже. Если создать новый объест с помощью Excel, Word или другого (поддерживающего OLE) приложения, то у него не будет свойства SourceDoc встроенный объект - это еще не документ, который хранится в файле на диске.
Свойство Sourceltem. Свойство Sourceltem указывает на часть документа, которая встроена или связана. Во многих случаях значение этого свойства не определено, поскольку связан весь объект. Впрочем, для встраивания можно выделить только часть объекта. Нельзя выбрать часть документа Word или растрового изображения, но можно выбрать часть рабочего листа Excel. Если выбрать блок ячеек, то значение свойства Sourceltem будет, например, таким "R1C1 R1C10". Хотя приложение OLERTime позволяет выбрать файл для операции встраивания, но метод перетащить-и-опустить им не поддерживается. Поэтому ячейка, содержащая значение свойства Sourceltem, будет пустой.
Если щелкнуть на кнопке Insert Object, то на экране появится окно, в котором пользователю будет предоставлена возможность выбора типов данных Можно выбрать
Linked (Связанный) или
Embedded (Внедренный). Также можно задать размер отображаемого объекта, установив свойство SizeMode в окне Properties (Свойства) элемента управления OLE Container. Возможны такие варианты:
• "растянуть" окно элемента управления
OLE Container, чтобы подогнать его к размерам объекта (2-AutoSize);
• "растянуть" объект, чтобы подогнать его к размерам контейнера (1-Stretch).
Если пользователь выполнит щелчок на кнопке ОК, то в открывшемся диалоговом окне Insert Object (Вставка объекта) можно выбрать данные для вставки.
Вставьте командные кнопки, кнопки переключателей и рамки, изображенные на рис. 14.10. Добавьте следующий фрагмент в программу для обработчика нажатия кнопки Cancel.
Программа 14.4. Обработчик события Click для кнопки Cancel формы frmType
Option Explicit
Private Sub cmdCancel_Click()
Unload frmType
End Sub
Эта процедура закрывает приложение, выгружая форму frmType.
Установка размера окна элемента управления OLE Container. Если встраивание объектов в OLE Container происходит во время выполнения приложения, то нужно учитывать, что пользователь не может изменить размер окна элемента управления с помощью мыши. Объявим переменные OLEHeight и OLEWidth так, чтобы размеры окна элемента управления приравнивались значениям, введенным во время разработки. Чтобы непосредственно не указывать в программе значения высоты и ширины, можно использовать более гибкий способ — OLEHeight
и OLEWidth. Добавим следующие операторы в раздел объявления формы frmOLE.
Public OLEHeight As Integer
Public OLEWidth As Integer
и в обработчик события Load формы:
OLEHeight = oleDisplay.Height
OLEWidth = oleDisplay.Width
Теперь можно вернуться к форме frmType и добавить фрагмент, который позволяет организовать вызов диалогового окна Insert Object после установки опций пользователем.
Программа 14.5. Вызов диалогового окна Insert Object
Private Sub cmdOK_Click()
With frmOLE oleDisplay
.Height = frmOLE.OLEHeight
.Width = frmOLE.OLEWidth
End With
If opt3tretch0b]ect Value - True Then
frmOLE oleDisplay SizeMode - 1 ' Stretch
Else
frmOLE oleDisplay SizeMode = 2 ' AutoSize
End If
Добавление следующей строки позволяет скрыть форму.
FrmType Hide
В завершение, следующие операторы открывают диалоговое окно Insert Object и выполняют вставку объекта.
frmOLE.oleDisplay.InsertObjDlg
If frmOLE.oleDisplay.Class <> "" Then
frmOLE.cmd0b]lnfo.Enabled = True
End If
Unload frmType
Если объект вставлен, то становится доступной кнопка
Object Info.
InsertObjDIg - это метод элемента OLE Container, позволяющий выводить диалоговое окно Insert Object (Вставка объекта), для того чтобы пользователь мог создавать связанный или встроенный объект, выбирая его тип и приложение для создания объекта. Установки пользователя автоматически присваиваются значениям соответствующих свойств элемента управления OLE.
Чтобы изменить размер контейнера, выполните следующие действия.
1. Запустите приложение, а затем щелкните на кнопке Insert Object, чтобы отобразить диалоговое окно Object Type.
2. Щелкните на одной из кнопок Size Mode (Установка размера), а затем - на Object Type (Тип объекта). На экране появится диалоговое окно Insert Object (рис. 14.12).
Ниже приводится исходный текст формы frmOLE. Обратите внимание на обработчик события Resize элемента управления OLE Container. Если предусмотрена возможность изменения размеров элемента управления во время выполнения, то обработчик события Resize вызывается каждый раз, когда пользователь изменяет размеры окна. Событие Resize передает с помощью параметров HeightNew и WidthNew новые размеры окна элемента управления обработчику, который использует их для изменения размеров формы.
Insert Object
Рис. 14.12. В диалоговом окне Insert Object установлен переключатель Create from File и отображается путь к файлу данных
Программа 14.6. Форма frmOLE
Option Explicit
Private Sub cmdClose Click()
Dim Quit As String
Quit = MsgBox ("Are you sure you want to quit?" vbYesNo + vbQuestion)
' (Вы уверены, что хотите закрыть приложение?...)
If Quit = vbYes Then
End
End If
End Sub
Private Sub cmdInsObj_Click()
frmType.Show
End Sub
Private Sub cmdObjInfo_Click()
Dim SourceText As String
Dim TypeText As String
Dim MsgText As String
SourceText = "The object's source file is " + oleDisplay. SourceDoc
' (Файл объекта источника:...)
TypeText = " The type of object is " + oleDisplay.Class
' (Тип объекта:...)
MsgText = SourceText + Chr(13) + TypeText
MsgBox MsgText, vblnformation, "Object Information"
'(Информация об объекте)
End Sub
Private Sub bttnLoad_Click()
Dim fnum As Integer
On Error GoTo LoadCancel
fnum = FreeFile
CommonDialogl.ShowOpen ' Показать диалог Open File
Open CommonDialogI. FileName For Binary As #1 ' Открыть файл
oleDisplay.ReadFromFile (fnum) ' Прочитать файл No.1
Close #fnum
Exit Sub
LoadCancel:
MsgBox "Could not load file"
' (Файл не был загружен)
Close #fnum
End Sub
Private Sub bttnSave_Click()
Dim fnum As Integer
On Error GoTo SaveCancel
CommonDialogI.ShowSave ' Показать диалог Save As
fnum = FreeFile
Open CommonDialogI.FileName For Binary As #1 ' Открыть файл
oleDisplay.SaveToFile (fnum) ' Запись в файл No. 1
Close ttfnum ' Закрыть файл
Exit Sub
SaveCancel:
MsgBox "Could not save file"
' (Файл не был сохранен)
Close #fnum
End Sub
Private Sub oleDisplay_Resize(HeightNew As Single, WidthNew As Single)
frmOLE.Width = oleDisplay.Left + WidthNew + 20 * _
Screen.TwipsРеrPixelX
frmOLE.Height = oleDisplay.Top + HeightNew + 80 * _
Screen.TwipsPerPixelY
End Sub
Программа 14.7. Форма frmType
Option Explicit
Private Sub cmdCancel_Click()
Unload frmType
End Sub
Private Sub cmdOK_Click()
With frmOLE.oleDisplay
.Height = frmOLE.OLEHeight
.Width = frmOLE.OLEWidth
End With
If optStretchObject.Value = True Then
.SizeMode = 1
Else
.SizeMode = 2
End If
If optTypeEmbedded.Value = True Then
frmOLE.oleDisplay.OLETypeAllowed = 1 ' Связывание
Else
frmOLE.oleDisplay.OLETypeAllowed = 0 ' Встраивание
End If
' Скрыть форму frmType
frmTipe.Hide
' Вставка объекта
frmOLE.oleDisplay.InsertOb]Dlg
If frmOLE.oleDisplay.Class <> "" Then
frmOLE.cmdOb]Info.Enabled = True
End If
Unload frmType
End Sub
Можете попробовать встраивать различные объекты в окно элемента управления OLE формы OLERTime и редактировать их, выполняя на объекте двойной щелчок.
Вы увидите, что у элемента управления OLE Container все еще несколько расплывчатые края. Для встраивания или связывания объекта требуется время, поэтому иногда при переключении в режим редактирования панель инструментов приложения-сервера может оказаться невидимой. При программировании на Visual Basic встраивание объектов в элемент управления OLE Container используется достаточно редко. Позднее мы узнаем, как использовать автоматизацию OLE, чтобы заставить приложение-сервер выполнять требуемые действия и возвращать результаты VB-приложению.
Свойства элемента управления
Data
К наиболее важным свойствам элемента управления
Data можно отнести свойства, перечисленные ниже.
• DatabaseName (Имя базы данных). Определяет используемую базу данных.
• RecordSource (Источник записей). Определяет выбранную для использования часть базы данных.
В любой момент времени Data установлен на единственную строку (запись) в наборе RecordSet. Пользователь может перемещаться на другую запись с помощью кнопок перемещения, расположенных на элементе управления Data.
Каждый элемент управления TextBox связан с одним полем текущей строки. При установке Data на другую запись в RecordSet элементы TextBox обновляются. При изменении данных в TextBox новое значение записывается в базу данных, когда Data устанавливается на другую запись. Элемент управления TextBox соединен с полем в RecordSet с помощью Data и называется связанным с данными (он связан с полем в наборе записей RecordSet).
Ниже приведены наиболее важные свойства элементов управления, связанных с данными.
• DataSource (Источник данных). Это имя элемента управления Data. Посредством этого имени элементы управления (например, TextBox и CheckBox) связываются с элементом Data. Другими словами, это имя элемента управления Data, с помощью которого связанные с данными элементы "видят" базу данных.
• DataField (Поле). Это имя поля в наборе RecordSet, которое отображается и обновляется (в случае изменения) в элементе управления.
Примечание
Элемент управления TextBox, связанный с конкретным полем, называется связанным с данными. Существуют другие элементы управления, которые можно связывать с набором записей элемента управления Data. Чтобы предотвратить редактирование содержимого таблицы, используются элементы управления Label. Если таблица содержит логические поля (принимающие только значения True или False), то можно связывать их с элементами управления CheckBox (флажок). Некоторые общие элементы управления не связываются с данными. Например, элемент ListBox. Фирма Microsoft предоставляет его расширенную версию — связанный с данными ListBox, который автоматически заполняется значениями из столбца набора записей. Позже мы рассмотрим, как использовать эти элементы управления в приложениях.
Можно устанавливать в окне свойств или использовать в тексте программ (с целью управления) следующие свойства элемента управления Data.
EOF (Конец файла).
Возвращает значение True или False, которое указывает, находится ли текущая позиция записи после последней записи в объекте RecordSet.
BOF (Начало файла).
Возвращает значение True или False, которое указывает, находится ли текущая позиция записи перед первой записью в объекте RecordSet.
BOFAction.
Устанавливает или возвращает значение, указывающее, какое действие должен произвести элемент управления Data, когда свойство BOF равно True. Эти действия перечислены в табл. 17.1.
Таблица 17.1. Значения, возвращаемые свойством BOFAction
Константа |
Значение |
Действие |
vbBOFActionMoveFirst VbBOFActionBOF |
0 1 |
Устанавливает управление на первую запись (значение по умолчанию). Перемещает управление в начало RecordSet и устанавливает на несуществующую запись с одновременным вызовом события Validate элемента Data для первой записи. Далее показано, как обработать данную ситуацию. |
EOFAction.
Устанавливает или возвращает значение, указывающее, какое действие должен произвести элемент управления Data, когда свойство EOF равно True (табл. 17.2).
ReadOnly.
Возвращает или устанавливает значение, определяющее, открыт ли объект RecordSet только для чтения.
RecordsetType.
Возвращает или устанавливает значение, задающее тип RecordSet, создаваемый Data. Может иметь одно из значений, приведенных в табл. 17.3.
Options.
Устанавливает одну или более характеристик объекта RecordSet. Возможные значения этого свойства приведены в табл. 17.4.
Таблица 17.2. Значения, возвращаемые свойством EOFAction
Константа |
Значение |
Действие |
vbEOFActionMoveLast vbEOFActionEOF Vb EO FActionAddN ew |
0 1 2 |
Устанавливает управление на последнюю запись (значение по умолчанию) Перемещает управление в конец RecordSet и устанавливает на недействительной записи с одновременным вызовом события Validate элемента Data для последней записи. Позже рассмотрим, как обработать данную ситуацию Добавляет новую пустую запись в RecordSet, которую пользователь может редактировать. Новая запись в базу данных записывается при переходе элемента управления Data на другую запись |
Таблица 17.3. Значения свойства RecordsetType
Константа |
Значение |
Описание |
vbRSTypeTable vbRSTypeDynaset vbRSTypeSnapshot |
0 1 2 |
Типа Table Типа DynaSet (по умолчанию) Типа SnapShot |
Таблица 17.4. Значения свойства Options
Константа |
Значение |
Описание |
dbDenyWrite |
1 |
В многопользовательской среде другие пользователи не могут изменить записи в RecordSet |
DbDenyRead |
2 |
В многопользовательской среде другие пользователи не могут читать записи (Только для RecordSet типа Table) |
DbReadOnly |
4 |
Пользователь приложения читает, но не может изменять записи в RecordSet |
DbAppendOnly |
8 |
Пользователь приложения добавляет новые записи в RecordSet, но не может читать |
существующие |
||
Dblnconsistent |
16 |
Обновления применяется ко всем полям RecordSet, даже если они нарушают условие объединения (применяется к RecordSets, основанных на SQL-запросах) |
DbConsistent |
32 |
Обновления применяются к полям, которые не нарушают условие объединения (применяется в RecordSets, основанных на SQL-запросах) (по умолчанию) |
DbSQLPassThrough |
64 |
Когда используется элемент Data с SQL-оператором в свойстве RecordSource, передает SQL-запрос базе данных, поддерживаемой ODBC (например, SQL Server или Oracle) |
DbForwardOnly |
256 |
Объект RecordSet поддерживает только прокрутку вперед. MoveNext — единственный разрешенный метод перемещения. Эта опция не используется в объектах RecordSet, управляемых элементом Data |
DbSeeChanges |
512 |
Генерирует блокируемую (trappable) ошибку, если другой пользователь изменяет данные, которые вы редактируете |
Bookmark. Свойство типа Variant, идентифицирующее строку в RecordSet. Каждая строка имеет собственную, уникальную закладку, которая не связана с порядком записей в RecordSet. Сохраните свойство Bookmark в переменной, чтобы можно было вернуться к этой записи, присвоив свойству Bookmark данную переменную.
Свойства модуля класса
Несмотря на то, что свойства класса могут быть реализованы как общедоступные переменные, для доступа к ним Visual Basic предоставляет процедуры Property Let и Property Get. Для корректной реализации свойства класса необходимо добавить следующие процедуры:
Private m_IntProperty
Public Property Let IntProperty(newValue As Integer)
m_IntProperty = newValue
End Property
Public Property Get IntProperty() Аs Integer
IntProperty = m_IntProperty
End Property
Закрытая переменная m_IntProperty - это локальная копия значения свойства. Каждый раз, когда приложение устанавливает значение этого свойства, автоматически вызывается процедура Property Let и новое значение используется в качестве аргумента. Другими словами, строка
IntProperty = 100
вызывает следующую процедуру класса:
Property Let IntProperty(100)
Назначение свойству некоторого значения приводит к вызову процедуры Property Let (имеющую то же имя, что и свойство). Код процедуры может проверить новое значение на допустимость и либо принять его (и присвоить его значение локальной переменной), или отвергнуть. Аналогично, когда приложение запрашивает значение свойства IntProperty, передается значение локальной переменной m_IntProperty.
В процедуру Property Let можно добавить любой необходимый код проверки корректности значения. Например, свойство Age (Возраст) может быть реализовано следующим кодом:
Private m_Age
Public Property Let Age(newValue As Integer)
Select Case newValue
Case < 0: m_Age = 0
Case > 100 : m_Age = 100
Else m Age = newValue
End Select
End Property
Public Property Get Age() As Integer
IntProperty = m_Age
End Property
Если в приложении определено неверное значение возраста, класс выполняет некоторые действия, которые впоследствии предотвращают серьезные ошибки. Объем программного кода проверки зависит от природы свойства, а его можно добавить столько, сколько будет необходимо.
Можно также принудительно вызвать ошибку изнутри процедуры Property Let, которая может быть обработана кодом приложения. Например, можно так реализовать свойство Age:
Public Property Let Age(newValue As Integer)
If newValue < 0 or newValue > 100 Then
Err.Raise 1999, _
" Invalid Age. It must be greater than zero _
and less than 100"
' (Неверное значение. Возраст должен быть больше ' нуля и меньше 100)
Else
m_Age = newValue
End Property
Ошибка возвращается приложению, которое либо генерирует ошибку времени выполнения, либо обрабатывает ее.
Можно подумать об отображении сообщения с помощью функции MessageBox() внутри кода процедуры. Но это не очень хорошо по двум причинам.
1. Окно сообщения может не отображаться на мониторе пользователя. Если класс находится на сервере и используется приложением удаленно посредством сети (или Internet), окно сообщения будет отображено на сервере, а не на компьютере клиента. Так как пользователь приложения не видит окно сообщения, у него нет возможности нажать кнопку ОК. и, как результат, приложение зависнет.
2. Так как ошибка генерируется не кодом приложения, то нельзя выдать пользователю действительно точную информацию об ошибке. Возможно только общее сообщение типа "Пожалуйста, введите правильное значение". Это действие должно выполняться кодом приложения, и лучший способ реагирования на ошибки в классах - это выявить ошибки в вызывающем приложении и предоставить их обработку этому приложению.
Тем не менее, есть возможность отображать окна сообщений из кода класса или даже вывести всю форму или диалоговое окно с запросом к пользователю о вводе данных. Следует только помнить, что видимый интерфейс класса может стать невидимым, если класс выполняется удаленно.
Некоторые классы предоставляют свойства только для чтения. Самый простой способ реализации свойства только для чтения - опустить процедуру Property Let, как это было сделано с классом CTimer. Можно также инициировать ошибку времени выполнения, которую приложение может перехватить и действовать соответственно. Как вызвать ошибки внутри класса, описано далее в этой главе.
Свойства объекта
Wscript
Объект Wscript в дополнение к свойству Arguments имеет и другие свойства. Они относятся к программе, управляющей выполнением сценария (WSCRIPT.EXE) и, собственно, к исполняемому сценарию.
Application.
Возвращает синоним имени объекта Wscript - строку "Windows Scripting Host" (аналогичное значение возвращается свойством Name).
FullName.
Возвращает путь и имя программы, управляющей выполнением сценария (WSCRIPT.EXE).
Name. Возвращает синоним имени объекта Wscript — строку "Windows Scripting Host".
Path. Возвращает имя папки, в которой находится WSCRIPT.EXE или CSCRIPT.EXE (обычно c.\windows).
ScriptFullName.
Возвращает путь и имя сценария, выполняемого WSCRIPT.EXE.
Version. Возвращает версию WSCRIPT.EXE. Версия, поставляемая с Windows 98 - 5.0.
ScriptName.
Возвращает имя сценария, выполняемого WSCRIPT.EXE. Сценарий WSCRIPT.VBS демонстрирует некоторые из этих свойств. На рис. 20.9 показан результат его работы.
Программа 20.15. Сценарий WSCRIPT.VBS
msg = "Script File Name " & Wscript.ScriptName & vbCrLf
msg = msg & "Script Path Name " & Wscript.ScriptFullName & vbCrLf
msg = msg & "Executed by " & Wscript .Application & " (version " & _
Wscript.Version & ")" & vbCrLf
MsgBox msg
Рис. 20.9. Результат работы сценария WSCRIPT.VBS
Решение этой проблемы состоит в использовании свойства
Cookie (Заготовка) объекта Document - строки, которая может быть сохранена на клиентском компьютере. Cookie совершенно безопасны, потому что это текстовые файлы, которые записываются на диск, читаются с диска броузером и располагаются в специальной папке. Это не исполняемые файлы (никакой угрозы для остальной части файловой системы они не представляют), и к ним можно обратиться только при помощи броузера. Свойство Cookie не может заменить файловый ввод-вывод, но позволяет сохранить фрагмент информации на клиентском компьютере, чтобы в следующий раз при исполнении сценария он смог найти там информацию.
Информация, сохраненная на клиентском компьютере посредством
Cookie, ограничена. Нельзя сохранять большие файлы с текстом или числами. Но можно сохранить информацию о настройках: имя пользователя и имена наиболее часто используемых страниц, чтобы (когда пользователь запросит ту же страницу) прочитать значения, сохраненные на клиентском компьютере в прошлый раз, и настроиться самостоятельно на пользователя.
Примечание
Наиболее общим применением Cookie является сохранение данных настройки.
Другая причина использования Cookie - предоставление нескольким страницам возможности совместного использования некоторой информации. Корзина покупателя - типичный тому пример. Сфера действия сценария, как известно, ограничена одной страницей. Если страница со сценарием загружает другую страницу, то первоначальный сценарий прекращает существование. Сценарий, загруженный с новой страницы, перехватывает управление. Некоторые узлы позволяют выбирать "товар для покупки" с различных страниц, сохраняя при этом ссылку на уже приобретенный товар, находящийся в покупательской корзине. Если каждая страница -отдельный объект, и страницы не могут совместно использовать информацию, то как это реализовать?
Ответ - свойство Cookie объекта Document. Когда страница передает некоторую информацию другим страницам, она может оставить свойство Cookie на клиентском компьютере. Страница, которая нуждается в информации, считывает ее. У пользователя создается впечатление, что различные страницы обмениваются информацией как формы приложения, аналогично формам в Visual Basic.
VB6 в действии: страница Cookie
Чтобы сохранить строку в системе клиентского компьютера и иметь доступ к ней из другой страницы или доступ при следующем открытии, используется свойство Cookie. Страница Cookie (рис. 21.8) является измененной страницей Pagel. На этот раз запрашивается имя пользователя, которое сохраняется в свойстве Cookie объекта Document. При следующем открытии страницы имя пользователя появляется автоматически.
Чтобы проверить страницу Cookie, необходимо установить Web-сервер. Открытие страницы Cookie с помощью Internet Explorer не дает результата. Страницы Cookie сохраняются на клиентском компьютере броузером, если они созданы сервером Можно использовать любой Web сервер, например Frontpage Web-сервер или Personal Web Server.
Рис. 21.8. Свойство Cookie объекта Document: настройка страниц
Совет
Personal Web Server является частью Frontpage и Internet Explorer 4. Также он доступен на Web-узле Microsoft (http://www.microsoft.com/sitebuilder).
Для проверки этого примера использовался Frontpage Web сервер (работающий как Personal Web Server). Для экспериментов со свойством Cookie выполните следующие действия.
1. Скопируйте файл Cookies.htm с компакт-диска в папку Cookie в корневом каталоге на сервере.
2. Переименуйте его в Index.htm.
3. Запустите Frontpage Web-сервер или любой другой сервер, установленный в системе (если он еще не загружен).
4. Запустите Internet Explorer и соединитесь с URL.
http://127.0.0.1/Cookie
Символы 127.0.0.1 — IP-адрес локального сервера, a Cookie — имя папки, в которую скопирован узел (содержащий одну страницу).
5. Когда появится запрос на ввод имени, сценарий отобразит его на странице и сохранит в свойстве Cookie объекта Document.
6. Соединитесь с другим URL, введя его в поле Address окна просмотра.
7. Щелкните на кнопке Back, чтобы возвратиться к странице Cookie. На этот раз не придется вводить имя. Оно уже хранится в свойстве Cookie.
Теперь рассмотрим сценарий страницы Cookies.htm.
Программа 21.8.
Документ
Cookies.htm
<HTML>
<HEAD>
<TITLE>Cookie Demo Page</TITLE>
<SCRIPT LANGUAGE="VBSCRIPT">
If Document.Cookie = " " Then
UserName = InputBox ("Please enter your name")
' (Введите, пожалуйста, ваше имя)
document.cookie = UserName
Else
UserName = Document.Cookie
End If
Document.write "<Hl> Welcome to our Active Pages, " &
UserName & "</H1>"
' (Добро пожаловать на наши активные страницы)
Document.write "<BR>"
Document.write "This page was opened on " & date() & ",
at " & time ()
' (Эта страница была открыта)
Document.write "<BR>"
Document.write "The document's cookie is: " & Document.cookie
' (Свойство Cookie документа:)
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>
If-структура сценария проверяет значение свойства Cookie. Если это свойстве не имеет значения, то запрашивается имя пользователя. Затем введенное пользователем имя сохраняется в свойстве Cookie.
Свойство Cookie имеет значение при следующем подключении к этой странице и выполняется структура Else, которая присваивает свойству Cookie значение переменной UserName. Остальная часть кода такая же, как на странице Pagel кроме последнего метода Write, который отображает текущее значение свойстве Cookie на странице.
Такое использование свойства Cookie не является привычным. Cookies обычно сохраняются в виде пар имен и значений, разделенных точкой с запятой. Более разумно присвоить Cookie следующее значение.
"UserName = Cibil; Age = 24; Browser = IE3.02"
Как видите, можно сохранять много значений переменных, но методы длх чтения значения одной переменной отсутствуют. Необходимо считывать век заготовку, а затем использовать функции работы со строками
(InStr(), Mid() и другие), чтобы изолировать каждую пару и извлечь имя переменной и ее значение.
Срок действия заготовок
Заготовки имеют дату окончания действия. Если не определить дату окончания (дата окончания действия не использовалась в примере
Cookie), то действие свойства Cookie оканчивается после завершения текущего сеанса. Чтобы запустить новый сеанс, необходимо выключить Web-сервер и запустить его снова. Закрытие и перезапуск Internet Explorer не запускает новый сеанс.
Для задания даты окончания добавьте следующую строку в Cookie.
expires = Thu, 01 Jan 1998 12:00:00 GMT
Эта строка добавляется в Cookie следующим образом.
Document.cookie = UserName s & expires = Thu, 01 Jan 1998
12:00:00 GMT"
Заготовки с датами окончания хранятся на диске в виде текстовых файлов, которые можно просматривать обычным текстовым редактором. Заготовки для каждого Web-узла хранятся в папке Cookies папки Windows.
Anchor (Привязка). Anchor - свойство объекта Document. Подобно другим свойствам, оно является объектом. Свойство Length объекта Anchor
возвращает число привязок в документе. Индивидуальные привязки сохранены в массиве привязок, к которым, как к элементам массива, можно обратиться, используя индексы. Имя первой привязки в документе - Anchor(O) (это значение атрибута NAME тега <А>, который вставил привязку в документ), Anchor(l) - вторая привязка и т.д. Следующие операторы отображают число привязок в текущем документе в окне сообщения.
TotalAnchors = Document.Anchors.Length
MsgBox "The document contains "& TotalAnchors & "anchors"
' (Документ содержит... привязок)
Можно просмотреть все привязки в документе с помощью следующего цикла.
For i=0 to TotalAnchors-1
ThisAnchor = Document.Anchors(i)
{какие-либо операции с привязкой}
Next
Просматривать привязки текущего документа из раздела сценария того же документа не практично. Но можно открыть другой документ во фрейме и обратиться к привязкам фрейма через массив Frame(l). Document. Anchors. Еще один пример дан в примерах DocumentLinks этой главы.
link (Ссылка). Подобно свойству Anchor, но в отличие от него, задает гиперсвязи в текущем документе. Подобно массиву привязок, массив связей является свойством объекта Document и единственным объектом, содержащим связи. Основное свойство объекта Link - свойство Length, которое возвращает число связей в документе.
Каждая связь — это элемент массива Links. Первая связь — Links (0), вторая — Links (1) и т.д. В связи с тем, что гиперсвязи в документе - адресаты, свойства объекта Link идентичны свойствам объекта Location, но доступны только для чтения.
Чтобы получить число связей в документе, отображаемом в окне броузера, необходимо использовать следующее выражение.
Window.Document.Links.Length
Для просмотра гиперсвязи в документе и исследования ее адресатов используют цикл, подобный следующему.
For i = 0 to Window.Document.Links.Length - 1
{обработка гиперсвязи}
Next
При каждой итерации цикла текущая гиперсвязь задается следующим выражением.
Window.Document.Links(i).href.
lastModified (Дата модификации). Это свойство возвращает дату последнего изменения текущего документа. Можно использовать свойство lastModified объекта Document, чтобы отобразить дату и время последнего изменения. При этом нет необходимости изменять код непосредственно в документе.
Referrer (Указатель).
Это свойство возвращает URL ссылающегося документа.
Свойства объекта TextStream
Кроме перечисленных методов, объект TextStream имеет свойства, позволяющие определить местоположение указателя в текущем TextStream.
AtEndOfLine. Это свойство только для чтения. Возвращает значение True, если файловый указатель находится в конце строки объекта TextStream, в противном случае возвращается значение False. Свойство AtEndOfLine применимо к файлам, открытым для чтения. Позволяет организовать цикл посимвольного считывания строки из файла.
Do While TStream.AtEndOfLine = False
newChar = TStream.Read(1)
{обработка newChar}
Loop
Этот цикл считывает и обрабатывает символы из файла, заданного объектом TStream, пока не будет достигнут конец текущей строки.
AtEndOfStream.
Свойство только для чтения, возвращающее значение True, если указатель файла достиг конца объекта TextStream. Это свойство применимо только к файлам, открытым для чтения. Следующий цикл позволяет использовать его для чтения всего файла построчно.
Do While TStream.AtEndOfStream = False
newLine = TStream.ReadLine
{обработка строки}
Loop
Column. Свойство только для чтения, возвращающее номер текущего символа в строке TextStream. Первый символ в строке имеет номер 1. Используйте это свойство для чтения данных, упорядоченных в колонки без знаков табуляции и других разделителей.
Line. Это свойство тоже только для чтения и возвращает номер текущей строки в TextStream. Свойство Line первой строки равно 1.
VB6 в действии: проект MakeFile
Проект MakeFile (см. рис. 20.1) демонстрирует некоторые методы объекта TextStream. Это приложение создает текстовый файл и сохраняет в нем содержимое элемента управления Text Box. Затем открывает файл, считывает текстовые строки и отображает их на том же элементе управления Text Box.
Рис. 20.1. Проект MakeFile: использование объекта TextStream для доступа к текстовому файлу
Чтобы создать приложение, выполните следующие действия.
1. Откройте новый Standard ЕХЕ-проект.
2. Добавьте ссылку на компонент FileSystemObject.
3. Откройте диалоговое окно References и выберите компонент Microsoft Scripting Runtime.
4. Добавьте следующие объявления в окно Code формы:
Dim FSys As New FileSystemObject
Областью видимости переменной FSys
является форма, поэтому она доступна из всех процедур.
5. Поместите элементы управления, показанные на рис. 20.1, на форму и введите код, приведенный в программе 20.1., в обработчики события Click обеих командных кнопок.
Кнопка Create File считывает текст из элемента управления TextBox и записывает его в файл C:\TEXTFILE.TXT текущего каталога. Для записи текста в файл создается объект TStream.
Программа 20.1. Код обработчика события Click кнопки Create File
Private Sub bttnCreateFile_Click()
Dim OutStream As TextStream
TestFile = App.Path & "\textfile.txt"
Set OutStream = FSys.CreateTextFile(TestFile, True, False)
OutStream.WriteLine Text1.Text
Set OutStream = Nothing
End Sub
Щелчок на второй кнопке позволяет считывать содержимое этого файла с помощью другого объекта TextStream. В дополнение к тексту из файла, она выводит строки для выделения считанного из файла текста.
Программа 20.2. Код обработчика события Click кнопки Read File
Private Sub bttnReadFile_Click()
Dim InStream As TextStream
TestFile = App.Path & "\textfile.txt"
Set InStream = FSys.OpenTextFile(TestFile, 1, False, False)
While InStream.AtEndOfStream = False
TLine = InStream.ReadLine
txt = txt & TLine & vbCrLf
Wend
Text1.Text = "The following text was read from the file" & vbCrLf
'(Следующий текст был считан из файла...)
Text1.Text = Text1.Text & vbCrLf & String(50, "*")
Text1.Text = Text1.Text & vbCrLf & txt
Text1.Text = Text1.Text & vbCrLf & String(50, "*")
Set InStream = Nothing
End Sub
Переменная
FSys представляет файловую систему. InStream
и OutStream - объекты TextStream, методы которого WriteLine и ReadLine использовались для записи и чтения отдельных строк файла. После записи строк в файл обе переменные устанавливаются в Nothing, чтобы освободить выделенные им ресурсы (по сути, эти операторы закрывают файл).
Строки файла читаются в цикле While...Wend, который проверяет значение свойства AtEndOfStream объекта TextStream, чтобы выяснить, сколько строк нужно прочитать из файла.
While InStream.AtEndOfStream = False
TLine = InStream.ReadLine
{обработка переменной TLine}
Wend
На каждой итерации цикла переменная TLine
получает из файла очередную строку текста.
Свойства объектов
Scripting
Window - объект верхнего уровня - является контейнером для всех других объектов. Объект Window задает окно просмотра броузера, в котором отображаются HTML-документы. Его свойства: имя и сообщение, отображаемое в его строке состояния. Чтобы обратиться к свойству Name объекта Window, используется следующий оператор.
win_new = Window.Name
Можно использовать переменную win_new в коде приложения для ссылки на окно. Например, можно выполнить отображение другого документа в окне win_new. Для отображения сообщение в строке состояния броузера используют следующий оператор.
Window.Status = "Welcome to our Fabulous Site"
' (Добро пожаловать на наш прославленный сайт)
Можно использовать функции VBScript при выводе строки состояния, например, функции даты и времени.
Window. Status = "Welcome to our Fabulous Site" & "It is " & _
date & " and the time is " & time
' (Добро пожаловать на наш прославленный сайт... ' дата: ... время: ...)
Объект Document позволяет обратиться к свойствам и методам документа, отображаемого в окне броузера. Два наиболее часто используемых свойства объекта Document — цвет фона (свойство bgColor) и цвет символа (fgColor). Чтобы заменить цвет фона документа белым, используйте следующий оператор.
Window.Document.bgColor = white
Объект Document имеет свойства, которые сами являются объектами. Один из них - Location - предоставляет доступ к свойству, определяющему место расположения документа. URL документа в окне броузера задан свойством hRef объекта Location. Можно узнать URL активного документа или установить это свойство на URL другого документа. К свойству hRef объекта Location обращаются посредством следующего выражения.
Location.href
Объект Location является свойством объекта Document. К нему нужно обращаться следующим образом.
Document.Location.href
Поскольку объект Document является свойством объекта Window, то полное выражение для доступа к URL документа следующее.
Window.Document.Location.href
Это выражение длинное, но простое. Первый объект уровня - Window. Следующие объекты расположены ниже в иерархии. Организация объектов Scripting в иерархию упрощает синтаксис методов и свойств.
Окно также может содержать фреймы. К фреймам обращаются через объект Frames, являющийся массивом объектов. Первый фрейм - Frame(O), второй -Frames(l) и т.д. Чтобы обратиться к документу в нужном фрейме, начинают с объекта Window и определяют фрейм, содержащий документ. Обращение ко второму фрейму имеет вид:
Window.Frames(1)
Каждый фрейм воспроизводит иной документ, следовательно, имеет собственное свойство Document. Чтобы обратиться к свойствам документа второго фрейма, используют следующее выражение.
Window.Frames(1).Document
Как установить цвет фона документа? Добавьте имя свойства bgColor в конце предыдущего выражения.
Window.Frames(1).Document.bgColor
Как видим, многие объекты и1иеют одноименные свойства. Окно имеет собственный объект Document и свойство Location. Но если окно содержит фреймы, то каждый фрейм в окне имеет собственное свойство Location.
Свойство экземпляра класса
Как можно заметить, классы имеют несколько свойств. В этой главе обсуждаются только два из них: свойство Name (Имя) и свойство Instancing (Экземпляр). Свойство Instancing определяет, где и как приложения могут использовать класс. Здесь обсуждаются его шесть возможных значений.
Private
Закрытые объекты доступны только компонентам из этого же приложения. При разработке класса, который не будет использоваться в других проектах или не нужно делать его доступным для других разработчиков, установите свойство Instancing в Private
SingleUse
Эта установка применима только к программным компонентам ActiveX EXE. Сервер ActiveX EXE — это исполняемый файл (приложение), который может обслуживать одного или более клиентов. Если свойство Instancing проекта сервера установлено в SingleUse, то для каждого клиента, который вызывает объекты класса, запускается новый экземпляр сервера. Такая установка является неэффективным методом создания и использования объектов, и ее обычно избегают. Если для каждого клиента нужен новый экземпляр сервера, то используется сервер, организованный в виде компонента ActiveX DLL.
MultiUse
Эта установка противоположна Private и может использоваться только с программными компонентами. Это позволяет одному экземпляру сервера обеспечивать столько объектов, сколько их требуется клиентским приложениям. По умолчанию в каждом вновь создаваемом проекте ActiveX EXE или ActiveX DLL свойство Instancing установлено в MultiUse.
GlobalSingleUse
Это значение создает глобальный объект со свойством SingleUse. Если вы собираетесь использовать глобальный объект, создайте его со значением SingleUse свойства Instancing, чтобы все клиенты, вызывающие его, могли быть обслужены одним сервером. Это свойство доступно как в компонентах ActiveX EXE, так и ActiveX DLL.
GlobalMultiUse
Эта установка доступна как в проектах ActiveX EXE так и ActiveX DLL, но ее следует использовать как можно реже. Объекты представленные компонентом со свойством GlobalMultiUse, доступны всей системе и могут использоваться любым приложением так, как если бы это были системные компоненты. Visual Basic предусматривает общесистемные объекты, называемые глобальными объектами. Например, объекты Screen (Экран) и Printer (Принтер) являются глобальными, поскольку не нужно добавлять на них ссылки в приложениях, которые их используют. Если имеется объект, о котором важно знать остальной части системы (а не только приложениям, которые его используют) то установите свойство Instancing в GlobalMultiUse.
PublicNotCreatable
Объекты класса с этим значением свойства Instancing могут быть доступны из других приложений, но не могут быть созданы. Что это значит? Объекты класса PublicNotCieatable должны быть вначале созданы другим компонентом в этом же объекте а затем могут быть доступны через объекты этого компонента. Например, если есть класс, который реализует операции с базой данных, один из объектов, предоставляемых классом представляет собой базу данных. Другой объект в проекте представляет собой таблицу в базе данных. Если разрешить разработчику непо средственныи доступ ко второму объекту, то он может попытаться открыть таблицу минуя открытие базы данных. Но если создать класс, который предоставляет объект Database (База данных) как MultiUse, и класс который выставляет объект Table (Таблица) как PublicNotCreatable, то тогда, сделав ссылку на объект, который представляет таблицу, как только открывается база данных, разработчик получит прямой доступ к объекту Table, но только после его создания.
Остальные свойства объекта класс описаны коротко и не используются в этой книге.
• DataBindingBehavior. Определяет, будет ли класс работать как потребитель данных (класс, который соединяется с базами данных и поставляет записи и/или поля записей ведущему приложению).
• DataSourceBehavior. Определяет, будет ли класс работать как источник данных (т е. другие классы из элементов управления могут быть привязаны к этому классу).
• MTSTranslationMode. Позволяет определить, будет ли класс поддерживать Microsoft Transaction Server. Эта установка используется для классов, которые предполагается выполнять на сервере и которые будут одновременного выполнять несколько транзакций. Если одна из транзакций не отрабатывается, то все они отменяются.
Таблицы
Таблицы являются незаменимым инструментом организации и представления данных. В HTML-документах таблицы используются по тем же причинам, что и в любых других документах. Возможно, имеется еще одна причина, по которой таблицы используются в HTML-документах — это выравнивание элементов на странице. Ячейки таблицы могут содержать текст, гиперссылки или изображения, и можно использовать ячейку для выравнивания содержимого на странице способом, который невозможен непосредственно в HTML или другой таблице. Можно использовать таблицы без обрамления: никто не поймет, как достигнут такой удивительный результат в искусстве графического оформления.
Основные табличные теги
Каждая таблица начинается тегом <TABLE> и заканчивается тегом </TABLE>. Атрибуты тега <TABLE> позволяют задать обрамление таблицы, ширину, расстояние между ячейками, между содержимым ячейки и ее границей. Можно задать ширину и высоту таблицы в пикселях или в процентном соотношении к размеру полного экрана.
Внутри тега <TABLE> каждая строка таблицы отмечается тегом <TR>. Отключающий тег </TR> не обязателен. Каждая ячейка строки отмечается тегом <TD>, а комплементарный ему тег </TD> также необязателен. Ниже приводится структура простой таблицы. Если создать HTML-файл со следующими строками и открыть его броузером, то можно увидеть элементы в таблице без каких-либо линий вокруг них.
<HTML>
<TABLE>
<TR>
<TD> Row 1, Column 1 </TD>
<TD> Row 1, Column 2 </TD>
<TD> Row 1, Column 3 </TD>
</TR>
<TR>
<TD> Row 2, Column 1 </TD>
<TD> Row 2, Column 2 </TD>
<TD> Row 2, Column 3 </TD>
</TR>
<TR>
<TD> Row 3, Column 1 </TD>
<TD> Row 3, Column 2 </TD>
<TD> Row 3, Column 3 </TD>
</TR>
</TABLE>
</HTML>
Строки заголовка и данных
Можно использовать тег <ТН> вместо тега
<TR> для обозначения строки, являющейся заголовком таблицы. Следующий код HTML создает простую таблицу из двух строк, одна из которых отформатирована в виде заголовка.
<TABLE BORDER=1 CELLSPACING=1 CELLPADDING=1>
<TR>
<TH> Heading 1
</TH>
<ТН> Heading 2
</ТН>
</TR>
<TR>
<TD>Cell 1
</TD>
<TD>Cell 2
</TD>
</TR>
</TABLE>
Атрибуты CELLSPACING и CELLPADDING тега <TABLE> определяют расстояние между ячейками, следующими одна за другой, и пространство между содержимым каждой ячейки и ее границами. По умолчанию каждая ячейка создается достаточно большой для размещения ее содержимого. Использование атрибута CELLPADDING задает дополнительное пространство вокруг содержимого ячейки.
Выравнивание содержимого ячейки
Атрибуты ALIGN и VALIGN задают выравнивание содержимого ячейки. Атрибут ALIGN используется для горизонтального выравнивания. Он принимает значения LEFT (Влево), CENTER (По центру) или RIGHT (Вправо). Атрибут VALIGN задает вертикальное выравнивание и может принимать значения ТОР (Вверх), MIDDLE (По середине) и BOTTOM (Вниз). По умолчанию принимается выравнивание LEFT (по горизонтали) и MIDDLE (по вертикали).
Большинство средств выравнивания, вставки пробелов и размещения содержимого внутри ячеек таблицы представляют прекрасные возможности форматирования документов, которые, обычно, не создаются в виде таблиц. В HTML есть несколько эффектов, которые нельзя получить без использования таблиц.
Ширина таблицы
Во всех рассмотренных примерах ширина таблицы устанавливалась по умолчанию и определялась индивидуальным содержимым ячеек. Если колонка очень широкая, то броузер размещает ее содержимое в нескольких строках, чтобы все колонки были видны. Можно задать ширину таблицы атрибутом
WIDTH тега <TABLE>. Таблица, определенная следующим образом
<TABLE WIDTH=50%>
занимает половину ширины окна. Если не отцентрировать таблицу атрибутом CENTER, она будет выравниваться по левому краю окна броузера. Таблица, определенная следующим образом
<TABLE WIDTH=200>
имеет ширину 200 пикселей независимо от ее содержимого и/или размера окна. Если ширина окна менее 200 пикселей, то часть таблицы будет невидима. Чтобы отобразить на экране часть таблицы, находящуюся за пределами окна, необходимо использовать горизонтальную прокрутку.
Ячейки с несколькими строками и столбцами
Как правило, таблицы не содержат строки и столбцы одинакового размера. Некоторые строки содержат ячейки, которые несколько выше и шире других, а некоторые столбцы — несколько строк (рис. 19.4). Эти ячейки используют атрибуты ROWSPAN и COLSPAN, позволяющие создавать действительно сложные таблицы. Атрибуты ROWSPAN и COLSPAN появляются между тегами <TD> и </TD> и объединяют текущую ячейку с одной или более смежными ячейками той же строки (атрибут COLSPAN) или столбца (атрибут ROWSPAN). Количество смежных ячеек, соединенных с текущей, является значением атрибутов ROWSPAN и COLSPAN.
Рис. 19.4. Ячейки таблицы могут включать несколько строк и столбцов
Таблица (см. рис. 19.4) была создана приведенным ниже HTML-кодом. В него добавлен атрибут COLSPAN в соответствующий тег <TD> — распространение некоторых ячеек первой строки на два столбца, и атрибут ROWSPAN — распространение некоторых ячеек первого столбца на несколько строк. В остальном — эта таблица проста.
<HTML>
<HEAD>
<TITLE>ROWSPAN - COLSPAN Examples</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE BORDER>
<CAPTIONXB>ROWSPAN & COLSPAN Demo</BX/CAPTION>
<TR>
<TD COLSPAN=2 ROWSPAN=2 >Source:<BR>1991 Census</TD>
<TH COLSPAN=2>Average</TH>
</TR>
<TR>
<TH>Height</TH>
<TH>Weight</TH>
</TR>
<TR>
<TH ROWSPAN=2>Gender</TH>
<TH>Males</TH>
<TD>5.83</TD>
<TD>195.5</TD>
</TR>
<TR>
<TH>Females</TH>
<TD>5.22</TD>
<TD>167.8</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
Тег
<DIV>
Internet Explorer воспроизводит HTML-документы за один проход с начала документа до конца. В результате броузер не может переместиться назад и разместить один элемент поверх другого. Например, в HTML нельзя поместить заголовок поверх изображения. После того как изображение воспроизведено в окне броузера, нельзя вернуться на шаг назад и поместить текст поверх него.
Это ограничение можно устранить при помощи тега
<DIV>, который позволяет разбивать документ на отдельные части, размещаемые на странице. Тег <DIV> в DHTML достаточно значителен он позволяет прерывать документ на элементах (или объектах) и управлять каждым из них по отдельности. Рассмотрим обманчиво простой пример. Страница STYLES HTM (рис. 19.10) выглядит так, как будто текст был помещен поверх фонового изображения.
Рис. 19.10. Страница STYLES.HTM
Если открыть этот документ в текстовом редакторе, то можно увидеть, что он содержит две части, каждая из которых ограничена тегом
<DIV>. Первый тег <DIV> содержит строку, которая накрывает мозаикой фон документа. Второй тег <DIV> - это текст, который отображается поверх фона. Две части документа накладываются друг на друга, потому что тег <DIV> позволяет задавать их абсолютную позицию.
Документ содержит следующие описания стилей.
<STYLE>
Hl.LargeText (color: '#DODODO'; font-family: "Verdana"; font-size: 500%)
</STYLE>
Этот стиль является вариантом заголовка <Н1>. Он использует очень большой шрифт и светло-серый цвет (немного светлее, чем серебристый цвет фона). Фоновый узор на печатной странице почти незаметен. Чтобы его увидеть, нужно открыть страницу STYLES.HTM. Вообще, фон не должен быть сложным. В противном случае текст поверх фона буден трудно читаемым.
Первый тег <DIV>, который создает фон, определяется таким образом.
<DIV STYLE = "position: absolute; left: 20">
<H1 CLASS = LargeText>VB6 VB6 VB6 VB6 VB6 VB6
</DIV>
Позиция этой части документа задается в абсолютных координатах и размещается на расстоянии 20 пикселей от левого края окна
Internet Explorer. Для размещения текста поверх первой части надо использовать другой тег <DIV> с такой же привязкой Зададим ей следующее определение.
<DIV STYLE = "position: absolute; left: 20">
</DIV>
Здесь пропущено реальное содержание этой части. Все, появившееся между тегами <DIV>. воспроизводится поверх текущего содержимого окна Internet Explorer. Можно открыть документ STYLES.HTM и изучить его код.
Теги <STYLE> и <CLASS> расширяют HTML и позволяют Web-разработчику управлять свойствами HTML-элементов и задавать их положение на странице. Эти два тега первыми ознаменовали отход от прямолинейной (и статической) HTML-модели. DHTML предоставляет возможности для программного управления стилями. Тогда как тег <CLASS> позволяет переопределять существующий тег, тег <DIV> позволяет применять атрибуты части документа целиком DHTML улучшает эту возможность: он позволяет управлять цветом фона из сценария, даже после того, как документ воспроизведен броузером.
Терминология
OLE
Обычно в этом месте книги приводится несколько примеров, в которых рассматривается применение изученных ранее объектов. Мы же прежде рассмотрим некоторые термины OLE, использующиеся в этой главе. В OLE существует собственная терминология. Вы можете сразу не понять все описанные ниже термины, но они будут пояснены позже с помощью примеров.
OLE-объект
OLE-объект - это объект, который делается доступным для других приложений с помощью приложения-сервера OLE. Приложение-сервер OLE делает доступными объекты различных типов (или классов). OLE-объекты используются в приложениях-контейнерах (container applications). На рис. 14.1 показано, как приложение Excel (в данном случае оно является приложением-сервером) делает доступной электронную таблицу (OLE-объект), которую можно вставить в документ Word (приложение-контейнер).
Рис. 14.1. Таблица Excel, встроенная в документ Word
Приложение-сервер
Это приложение, функциональные возможности которого доступны для приложения, разработанного в Visual Basic. Когда вашей программе требуется отредактировать документ, созданный приложением-сервером, она просто устанавливает связь, и приложение-сервер используется для редактирования.
Приложение-контейнер
Это приложение, которое содержит OLE-объекты. Объекты могут быть связаны (linked) или встроены (embedded). Сам по себе, контейнер также является объектом. Примером контейнера может служить форма (FRM) - объект, содержащий элементы управления. О контейнере говорят как о клиенте (client), потому что он использует средства OLE-сервера для получения доступа к объектам. В примере, показанном на рис 14.1, Excel является приложением-сервером, a Word — приложением-контейнером.
Встраивание объекта
Используя встраивание (часто называют внедрение),
можно вставить объект из одного приложения (приложения-сервера) в другое (приложение-контейнер). Встроенный объект является копией оригинала, им можно манипулировать независимо от оригинала. Например, можно внедрить блок ячеек из таблицы Excel в документ Word. Для редактирования содержимого ячеек достаточно выполнить на них двойной щелчок, что приведет к вызову самой программы Excel. Если приложение-контейнер позволяет выполнять редактирование на месте (in-place editing), то меню Excel появится прямо в нем (см. параграф "Оперативное редактирование").
Связывание объекта
Этот метод напоминает встраивание, за исключением того, что данные связаны с документом, из которого они переданы. Изменения объекта в приложении-сервере автоматически отражаются в приложении-контейнере. При связывании происходит встраивание ссылки на объект, открытый приложением-сервером. Каждый раз, когда открывается документ, содержащий связанный объект, приложение-контейнер связывается с приложением-сервером, которое и открывает последнюю версию связанного объекта. Связываемые объекты не являются копиями. Это оригиналы, которые можно просматривать из различных контейнеров.
Оперативное редактирование
Оперативное редактирование (in-place editing) также известно под названием оперативной активации. При этом функциональные возможности приложения-сервера встраиваются в приложение-контейнер, позволяя редактировать объект, с помощью меню и инструментальных средств сервера приложения. Например, если документ Word содержит блок ячеек из таблицы Excel, то двойной щелчок на любой ячейке этого блока приведет к замене меню Word на меню Excel. Это позволяет редактировать содержимое ячеек без переключения в другую прикладную программу.
Оперативное редактирование — это наиболее очевидное проявление того, что раньше называлось "заимствованием функциональных возможностей другой прикладной программы". Чтобы можио было выполнять оперативное редактирование, контейнер и сервер должны поддерживать автоматизацию OLE (рассматривается ниже).
Автоматизация OLE
Этот метод позволяет программно управлять объектами, предоставляемыми другими приложениями, непосредственно из приложений, созданных в Visual Basic. Он является стандартом, определяющим способ распределения программного кода между приложениями и способ управления одними приложениями из других. Например, если блок ячеек из таблицы Excel копируется в документ Word, то происходит встраивание этого блока. Используя автоматизацию OLE, приложение может потребовать, чтобы Excel выполнил определенные вычисления и передал результаты в Word. Можно передать таблицу в Excel, чтобы выполнить обработку данных, которую нельзя сделать средствами Word, а затем возвратить таблицу в Word. Далее в главе рассмотрены примеры приложений Visual Basic, которые управляют объектами, созданными в Word и Excel.
Применение метода "перетащить-и-опустить" в OLE
Используя этот метод можно брать объекты, предоставляемые приложением-сервером и помещать их в приложение-контейнер. Например, можно встроить объект в документ Word, перетащив в него блок ячеек из таблицы Excel. В гл. 4 рассматривались способы программирования метода "перетащить и-опустить" Далее в этой главе будет рассмотрено, как выделить часть документа (или весь документ) и перенести его в окно элемента управления, который распознает перетаскиваемые данные и элемент управления, от которого они поступили.
Тестирование класса
CTimer
Компонент ActiveX (типа DLL) CTimer не может быть проверен сам по себе. Модуль класса предоставляет свои объекты другим приложениям, но он не может выполняться сам. Обычно, компилируется модуль класса, а затем открывается новый проект, который будет ссылаться на только что созданный класс. Для упрощения тестирования компонента ActiveX Visual Basic позволяет создавать группы проектов. Другими словами, можно расположить компонент ActiveX и проект, который его тестирует, в одной группе проектов. Для добавления тестового проекта к проекту CTimer следуйте следующим рекомендациям.
1. Добавьте новый проект командой Add Project меню File. Visual Basic добавит новую папку Project 1 в окно проводника проекта и поместит в нее форму Project I - обычный проект Visual Basic.
2. Измените имя нового проекта на TestProject, а имя его формы — на TestForm.
3. Расположите элементы управления, изображенные на рис. 15.1, на форму TestForm.
4. Для правильного использования класса CTimer в проекте тестирования необходимо сначала добавить ссылку на класс. Откройте меню Project и выберите команду References (Ссылки). В диалоговом окне References выберите пункт TimerProject, как показано на рис. 15.2. Диалоговое окно References отображает имя проекта, а не имя класса.
Рис. 15.2. Добавление класса CTimer к проекту с использованием диалогового окна References
Совет
Если проект еще не сохранен, то, вероятнее всего, отображается имя Project 1 (которое является именем проекта по умолчанию). Не добавляйте ссылку на это имя в проект. Переименуйте компоненты проекта, запишите их в новую папку, затем добавьте ссылку. Это не означает, что нельзя добавить ссылку на Project 1. Однако позже, открывая в очередной раз диалоговое окно Reference, тяжело будет вспомнить, что собой представляет класс Project 1.
5. Затем откройте окно Code формы и введите строки программы 15.4.
Программа 15.4. Код формы CTimer
Dim TMR As New CTimer
Private Sub Coirimandl_Click ()
If Command1.Caption - "Start Timing" Then
' (Запустить таймер)
TMR.StartCounting
Command1.Caption = "Stop Timing" ' (Остановить таймер)
Else
TMR.StopCounting
Commandl.Caption = "Start Timing" ' (Запустить таймер)
End If
End Sub
Private Sub Command2_Click()
ETime =
TMR.ElapsedTime
MsgBox "I've been counting for " & vbCrLf & _
Hour(TMR.ETime) & " hours" & vbCrLf & _
Minute(TMR.ETime) & " minutes and" & vbCrLf & _
Second(TMR.ETime) & " seconds" & bCrLf
' (С начала отсчета прошло... часов... минут и... секунд)
End Sub
Private Sub Commands Click()
End
End Sub
6. Щелкните правой кнопкой мыши на имени TestProject в окне проводника проекта и выберите команду Set as StartUp. В результате TestForm будет отображаться при нажатии клавиши F5.
Запустите проект на выполнение и изучите класс CTimer. Нажмите кнопку StartTimer для запуска таймера. Заголовок кнопки изменится на StopTimer, и если нажать ее снова, то отсчет времени остановится. Остановите таймер и запустите его снова В любой момент можно получить затраченное время, но его считывание будет корректным только тогда, когда таймер остановлен. Если исследовать код класса, то можно увидеть, что значение переменной totallnterval обновляется каждый раз, когда таймер останавливается.
Код проекта TestProject
Давайте рассмотрим программный код проекта TestProject. Первая строка — это объявление объектной переменной:
Dim TMR As New CTimer
TMR это переменная объектного типа CTimer. CTimer — это новый класс, который был только что реализован. Объектная переменная нужна для доступа к методам класса CTimer точно так же, как и для доступа к методам и свойствам Wold. Ключевое слово New указывает Visual Basic создавать новый экземпляр объекта CTimer (взамен можно использовать функцию Create0bject(), но об этом позднее). Теперь код имеет доступ к свойствам и методам, которые предоставляет класс CTimer посредством объектной переменной TMR. После ввода имени объектной переменной с точкой в конце, в окне кода появится список ее членов. Эта возможность предоставляется тогда, когда установлено свойство AutoList Members редактора программного кода. Новый класс зарегистрирован, и Visual Basic обращается с ним как с любым другим классом.
Программный код, обрабатывающий кнопки приложения, тривиален. Кнопка Start/Stop вызывает методы StartCounting и StopCounting класса для запуска и остановки процесса отсчета времени. Кнопка Show Interval считывает значение свойства ElapsedTime, форматирует его в часы, минуты и секунды и отображает в окне сообщения.
Тестирование нового элемента управления
ActiveX
Для проверки нового элемента управления сначала нужно создать ОСХ-файл. Откроите новый проект, а затем вставьте новый элемент управления в форму.
Для упрощения разработки Visual Basic позволяет добавлять новый проект к уже существующему. Таким образом можно проверить и изменить элемент управления без загрузки нового проекта.
Следующие шаги являются стандартными — им нужно следовать каждый раз при конструировании элемента управления ActiveX.
1. Выберите команду Add Project меню File, чтобы открыть новое окно проекта.
2. Выберите тип проекта Standard EXE. Новый проект добавится в окно проекта, с заданным по умолчанию именем формы Forml. Измените имя формы на TestForm, а имя нового проекта на TestProject.
3. Закройте окно конструирования UserControl нажатием кнопки Close. Закройте окно с кодом элемента управления, если оно открыто.
Когда выбрана форма TestForm, значок на панели элементов управления становится доступным. С этого момента можно использовать элемент управления FLEXLabel, как любой другой элемент управления VB.
Чтобы поместить экземпляр элемента управления
FLEXLabel на тестовой форме, выполните следующие действия.
1. Выберите значок элемента FLEXLabel на панели элементов управления и поместите на форму проекта. Элемент управления автоматически получит имя Label3Dl (согласно соглашению об именах в VB).
2. Найдите свойство Effect на странице свойств элемента управления ActiveX и установите другое значение (целое в диапазоне от 0 до 6).
Можно, конечно, присваивать значениям свойств Effect и TextAlignment любые целые числа, и все они будут приняты VB. Позднее мы увидим, как выйти из этой ситуации.
Как вы уже заметили, элементы управления ActiveX имеют свойство Appearance (Внешний вид), которое по умолчанию задает трехмерное отображение внешних краев элемента управления. Но свойство Appearance не задействуется, если свойство BorderStyle не установлено в 1 — Fixed Single (Фиксированная одиночная). Значение BorderStyle по умолчанию равно 0 - Flat (Плоская) (довольно своеобразный выбор, учитывая его действие на свойство Appearance). Откройте свойство BorderStyle и установите его в 1 — Fixed Single.
Теперь выполните двойной щелчок на элементе управления
FLEXLabel на форме, чтобы увидеть события, обрабатываемые элементом. Новый элемент управления имеет свои собственные события, которые можно программировать, как и события обычных объектов VB. Введите следующий код для события Click:
Private Sub Label3Dl_Click()
MsgBox "My properties are" & vbCrLf & _
"Caption = " & Label3Dl.Caption & Chr$(13) & _
"TextAlignment = " & Label3Dl.TextAlignment & Chr$(13) & _
"Effect = " & Label3Dl.Effect
End Sub
Нажмите клавишу F5, чтобы запустить приложение, и щелкните на элементе управления. Появится окно сообщения с отображенными в нем свойствами элемента управления, как показано на рис. 16.5. (На данный момент код, отображающий надпись, еще не введен.).
Рис. 16.5. Некоторые свойства элемента управления, отображенные им самим
Можно программировать также и другие события. Ничего специфического в программировании элемента управления нет. Для разработчика — это обыкновенный элемент управления VB сделал довольно много. Он сгенерировал работающий элемент управления ActiveX. Конечно, нужно все еще добавить код, который сделает элемент полезным в использовании. Создание чего-то, что выглядит и ведет себя подобно элементам с управлением типа "указать и щелкнуть" — немалое достижение, но конечная цель состоит в том, чтобы разработать кое-что практическое и полезное.
Типы курсоров и механизмы блокировки
Курсор (cursor) - это совокупность данных, на которых основан объект RecordSet. Объект RecordSet — набор отобранных записей. Программист видит базу данных в терминах таблиц, состоящих из записей, где каждая строка образована полями. Однако ADO не видят таблицу, а только курсор, который содержит информацию, позволяющую представить записи для приложения в виде строк с полями. Существует четыре типа курсоров: Dynamic, Keyset, Static и Forward-Only.
Чтобы задать, какой тип курсора больше всего подходит для приложения, используйте свойство CursorType.
Его значения приведены в табл. 18.1.
Свойство CursorType задается перед открытием объекта RecordSet. Если тип курсора не задан, то по умолчанию ADO откроет Forward-Only курсор.
Свойство CursorLocation (Место расположения курсора).
В дополнение к типу курсора можно устанавливать и его место расположения, используя свойство CursorLocation. Обычно курсор открывается на сервере, но можно его открыть и на машине-клиенте. Клиентский курсор ускоряет работу приложения при условии, что нет необходимости сразу вносить изменения в базу данных. Клиентский курсор — Static, и может изменять базу данных только через пакетные изменения (приложение модифицирует RecordSet, а затем передает его на сервер).
Примечание
Пакетные изменения — это довольно сложная тема, и она не рассматривается в этой книге. Более подробную информацию о пакетных изменениях можно получить из документации по методу UpdateBatch объекта RecordSet.
Свойство LockType (Тип блокировки). Другое важное свойство объекта RecordSet -это свойство LockType, которое определяет тип блокировки записей при их редактировании. Устанавливать свойство LockType следует перед открытием объекта RecordSet. Свойство LockType может принимать одно из значений, перечисленных в табл. 18.2.
Примечание
С клиентским объектом RecordSet свойство LockType может быть установлено только в LockOptimisticBatch.
Таблица 18.1. Значения свойства CursorType
Тип курсора | Константа | Описание | |||
Dynamic | adOpenDynamic | RecordSet синхронизируется с записями в базе данных. Позволяет просматривать добавления, изменения и удаления, сделанные другими пользователями, и поддерживает все методы перемещения | |||
Keyset | adOpenKeySet | Ведет себя так же, как и курсор типа Dynamic, но не позволяет видеть записи, которые другие пользователи добавили или удалили. Видны только изменения, внесенные другими пользователями в отобранные записи. Поддерживает все методы перемещения | |||
Static | adOpenStatic | Предоставляет статическую копию отобранных записей. Поддерживает все методы перемещения, но не позволяет увидеть изменения, сделанные другими пользователями. | |||
Forward-only | adOpenForwardOnly | Аналогичен курсору типа Dynamic, с той лишь разницей, что позволяет просматривать записи только в направлении вперед. Это улучшает производительность, если нужно сделать только один проход по RecordSet |
Таблица 18.2. Значение свойства LockType
Значение |
Константа |
Описание |
Read-only |
adLockReadOnly |
RecordSet открывается только для чтения. Используйте этот тип блокировки, чтобы предотвратить изменения данных |
Pessimistic locking |
adLockPessimistic |
Предоставляет возможности, необходимые для успешного редактирования данных. Блокировка записи источника данных устанавливается немедленно после начала редактирования (т.е. вызова метода Edit — прим. ред.) |
Optimistic locking |
adLockOptimistic |
Блокировка включается только после вызова метода Update |
Optimistic batch updates |
adLockBatchOptimistic |
Используется для режима пакетных изменений |
Пессимистическая блокировка.
Пессимистическая блокировка - это надежный метод упорядочивания доступа к базе данных, имеющий серьезные ограничения. При пессимистической блокировке закрыты все страницы, содержащие отобранные записи. Другие пользователи могут в это время только читать записи, принадлежащие блокированным страницам. Достоинством пессимистической блокировки является то, что ее использование упрощает код. Однако, если пользователь откроет RecordSet, а затем отлучится с рабочего места, то соответствующие станицы могут оставаться заблокированными очень долгое время. Использовать пессимистическую блокировку лучше для небольших RecordSet, содержащих единственную страницу.
Оптимистическая блокировка. Блокируются только страницы, содержащие редактируемые записи, причем только на время записи изменений. Этот метод блокировки выглядит весьма привлекательно, но не решает проблем, возникающих при одновременном доступе. Два пользователя открывают для редактирования одни и те же записи. Один из них заносит изменения в базу данных. После этого второй пользователь имеет устаревшую версию записей. ADO не извещает пользователя о том, что записи изменились. Так что же должно делать приложение: записать изменения поверх, известить пользователя или что-то еще?
Ответ на этот вопрос зависит от требований приложения. Необходимо написать код, который определит, были ли записи изменены с момента прочтения (для этого можно использовать специальные поля или прочесть вновь оригинальные записи из базы данных, закрыть их и сравнить с записями, которые были прочитаны вначале), и обновить, если они были изменены. Кроме того, следует известить пользователя об изменениях в базе данных и предоставить ему список команд для выбора последующих действий (записать поверх, прервать или начать редактирование заново).
Учебник по
HTML (для начинаюицих)
HTML — язык, использующийся при подготовке документов для интерактивного отображения. HTML-документы также называют Web-документами. Страница — это то, что видно в броузере в определенный момент времени. Каждый Web-узел в Internet или Intranet состоит из множества страниц. Можно переключаться между ними по соответствующим гиперссылкам.
Совокупность HTML-страниц и составляет Word Wide Web (Всемирная паутина — всемирная компьютерная сеть).
Web-страница — это файл с текстом, отображаемым на экране, и ссылками на такие элементы, как изображения, звуки и гиперссылки на другие документы. Можно создавать HTML-страницы с помощью текстового редактора, например, Notepad или приложения WYSIWYG, к которым относится Microsoft Frontpage. В любом случае результатом является простой текстовый файл, который легко можно изменять. Броузер отображает этот файл на компьютере клиента.
Web-страницы хранятся на компьютерах, работающих по принципу сервера:
они предоставляют страницу любому клиентскому компьютеру, который ее запрашивает. Каждый сервер-компьютер имеет адрес или URL, который имеет вид, подобный следующей строке:
http://www.my computer.com
где http — протокол доступа к серверу, a www.mycomputer.com — имя сервера в Internet. Как уже упоминалось, все компьютеры в Internet, имеют свой уникальный адрес, например, 193.22.103.18. Этот цифровой адрес известен как IP-адрес (Internet Protocol), который человеку запомнить труднее, чем имя. Сервер находит мнемонические имена в таблице и переводит их в адреса.
Чтобы сделать свой HTML-документ доступным для пользователей, компьютер, содержащий документ, запускает специальное приложение, называемое Web-сервером. Web-сервер распознает запросы от других компьютеров и предоставляет запрашиваемый документ. Броузер, запускаемый на компьютере клиента, получает документ и отображает его на экране.
Управление стилями
Уже понятно, как модифицировать HTML-теги с помощью тега <STYLE>. Этот параграф посвящен управлению стилями из сценариев и разработке DHTML-документов (которые изменяют свой вид в броузере). Поскольку VBScript запускается на выполнение на компьютере-клиенте, можно подключить механизм динамического изменения содержимого HTML-документов и их активизирования на компьютере-клиенте.
На рис. 19.11 показана простая Web-страница со списком книг издательства SYBEX. Названия книг сгруппированы по сериям, которым они принадлежат, и образуют список с отступами. Этот документ отображает всю информацию в одном окне, содержащем длинный список серий и названий книг.
Рис. 19.11. Простой HTML-список
Если просматривать аналогичную информацию приложением
Visual Basic, можно рассчитывать на другую организацию — древовидную структуру, в которой можно раскрывать и сворачивать отдельные серии и просматривать только интересующие вас названия книг. Нечто подобное можно делать и в HTML, используя названия серий в качестве гиперссылок на отдельные документы, каждый из которых содержит названия книг из одной серии. Таким образом организованы названия книг на Web-узле Sybex в World Wide Web.
Используя DHTML, можно организовать серии и названия книг в виде расширяющегося списка, чтобы избежать дополнительных обращений к Web-серверу. Каждое название серии может действовать как раздел, который при нажатии открывает следующий список. Можно открыть документ SBXHTML.НТМ (папка этой главы на компакт-диске) и поэкспериментировать с ним. Чтобы получить список первого уровня (названия серий), щелкните на названии документа, а затем — на имени серии, чтобы увидеть список книг. Если вновь щелкнуть на названии серии, список будет свернут и предоставит место для других списков (рис. 19.12 и 19.13).
Даже заголовок документа на странице SBXHTML НТМ является активным элементом. При первом открытии документа можно увидеть только его. Чтобы увидеть имена серий, щелкните на заголовке. Чтобы свернуть список, щелкните на заголовке вновь.
Рис. 19.12. DHTML позволяет создавать Web-страницы, которые изменяют свой вид и содержимое в зависимости от действий пользователя. Название серии Developers Handbooks становится красным, когда на него помещается указатель мыши
Рис. 19.13. Эта страница показывает несколько заголовков из серии Developers Handbooks. Если пользователь щелкнет опять на элементе Developers Handbooks, то список серий примет вид, отображенный на рис. 19.12
URL и гиперссылки
Ключевым элементом в Web-странице является гиперссылка — специальная команда в тексте, выполнение которой приводит к тому, что броузер загружает другую страницу. Чтобы установить связь с другим компьютером и запросить документ, гиперссылка должна содержать имя компьютера, на котором находится документ, и имя самого документа. Так же, как каждый компьютер в Internet имеет уникальное имя, так и каждый документ на компьютере имеет уникальное имя. Следовательно, каждый документ в WWW имеет уникальный адрес, который называется URL (Uniform Resource Locator - унифицированный указатель ресурса). URL для Web-документа выглядит следующим образом.
http://www.someserver.com/docName.htm
Примечание
Некоторые URL имеют расширение htm, а некоторые — html. Они идентичны с тем небольшим исключением, что страницы с расширением htm разработаны в операционной системе, не поддерживающей длинные имена файлов, или разработчик следовал DOS-соглашениям об именах файлов. Примеры страниц на компакт-диске имеют расширение htm. Это обусловлено особенностями изготовления компакт-диска и не имеет отношения к системе, в которой эти страницы создавались.
Любой отдельный фрагмент информации в WWW имеет уникальный адрес, и доступ к нему может быть получен посредством его URL. Что именно будет выполнять броузер, зависит от природы отдельного сообщения. Если это Web-страница или изображение, то броузер отобразит их на экране. Если это звук, то броузер воспроизведет его. Современные броузеры (например, Internet Explorer) обрабатывают документы многих типов. Когда встречается документ, который броузер не может обработать, то последний спрашивает, что требуется пользователю — принять документ, сохранив его в файле на диске, или открыть его с помощью приложения, указанного пользователем.
Ускорения операций вывода графических изображений
Операции вывода пикселей с помощью функций SetPixelV() и GetPixelV() занимают гораздо меньше времени, чем при использовании их аналогов в Visual Basic, но все же они выполняются не очень быстро. Для значительного увеличения быстродействия требуется использовать дополнительные API-функции.
Если вывод изображения в окно формы выполняется с помощью методов Visual Basic, то изображение, фактически, записывается в область памяти, содержимое которой затем отображается в окно формы. Visual Basic работает с этой областью памяти, в результате чего появляются несколько уровней обработки, которые лежат между программой и реальным окном на экране. API-функции, рассмотренные в предыдущем параграфе, позволяют выполнить те же операции, но они работают гораздо быстрее, чем программа Visual Basic. (На самом деле Visual Basic выполняет вызов этих же функций, однако, этот процесс скрыт от программиста VB. За счет этого использование функций упрощается, а время выполнения - увеличивается.)
Windows не позволяет приложению выполнять вывод графики непосредственно на экран. Следует помнить о том, что в Windows можно запускать одновременно несколько приложений, переключаться между ними и при этом не беспокоиться о том, как будут происходить перерисовка окон и переключение между палитрами -это делает Windows. Но Windows была бы не в состоянии уследить за всеми подробностями, если бы приложениям был предоставлен прямой доступ к растровым изображениям окон на экране. Именно поэтому процедуры рисования в Windows выполняются медленно.
Независимо от того, как Windows выполняет вывод объектов и их заливку, в конечном счете, растровое изображение должно быть сохранено где-нибудь в памяти. Имеются соответствующие API-функции, которые позволяют приложениям обращаться к этой области памяти и осуществлять вывод изображения, устанавливая значения битов и байтов. Вывод изображения непосредственно в область памяти выполняется значительно быстрее, чем в контекст устройства, но его организация сложнее. Кроме того. когда вывод изображения выполняется в область памяти, на экране ничего не появляется. Необходимо написать программу, которая передает изображение из области памяти в окно на экране. Но даже с учетом этих дополнительных шагов вывод изображения в область памяти выполняется значительно быстрее, чем вывод в контекст устройства.
Чтобы вывести изображение в область памяти, необходимо выделить в памяти место для растрового изображения. Такая структура должна быть совместимой с контекстом устройства, в которое выполняется вывод изображения. Иными словами, для организации вывода изображения на принтер и на монитор требуется определять различные структуры. Чтобы создать в памяти растровую структуру для хранения изображения, требуется вызвать функцию
CreateCompatibleBitmap().
Public Declare Function CreateCompatibleBitmap Lib "gdi32" _
Alias "CreateCompatibleBitmap" (ByVal hdc As Long, _
ByVal nWidth As Long, ByVal nHeight As Long) As Long
Первый параметр функции — это контекст устройства, с которым совместимо растровое изображение. С другой стороны, это — контекст устройства, в который помещается растровое изображение, чтобы его можно было вывести на экран. Два оставшихся параметра определяют размер растрового изображения в пикселях.
Так как изображение будет выводиться на экран, необходимо создать контекст устройства с помощью функции
CreateCompatibleDC(), а затем выбрать растровую структуру в контекст устройства с помощью функции SelectObject(). Функция CreateCompatibleDCO объявляется так:
Public Declare Function CreateCompatibleDC Lib "gdi32" _
Alias "CreateCompatibleDC" (ByVal hdc As Long) As Long
Ее параметром является контекст элемента управления (или формы), в которую выводится изображение. Если требуется сначала подготовить растровое изображение в памяти, а затем вывести его в окно элемента управления PictureBoxl, то можно воспользоваться следующими операторами.
hBMPSource = CreateCompatibleBitmap(Picturel.hdc,
_
Picturel.ScaleWidth, Picturel.ScaleHeight)
hSourceDC = CreateCompatibleDC(Picturel.hdc)
SelectObject hSourceDC, hBMPSource
После того как эти операторы выполнены, можно выполнить вывод изображения в контекст устройства hSourceDC, используя рассмотренные выше функции. Обратите внимание: содержимое контекста устройства hSourceDC не выводится на монитор непосредственно. Это изображение остается в памяти и может быть изменено очень быстро. А вот чтобы вывести его на монитор (т.е. передать его содержимое в окно элемента управления PictureBox2), следует воспользоваться функцией BitBlt().
Для обработки команды Сору Fast (третья кнопка на форме проекта CopyPix) используется именно такой прием при чтении значений цвета пикселей из окна левого элемента управления PictureBox и записи в правый PictureBox. Текст программы обработчика команды Сору Fast приведен ниже.
Программа 13.15. Обработчик команды Сору
Fast
Private Sub Command3_Click()
Picture2.CIs
' Задание области-источника растрового изображения
hBMPSource = CreateCompatibleBitmap(Picurel.hdc, _
Picturel.ScaleWidth, Picturel.ScaleHeight)
hSourceDC = CreateCompatibleDC(Picturel.hdc)
SelectObject hSourceDC, hBMPSource
' Задание области-получателя растрового изображения
hBMPDest = CreateCompatibleBitmap(Picture2.hdc, _
Picture2.ScaleWidth, Picture2.ScaleHeight)
hDestDC = CreateCompatibleDC(Picture2.hdc)
SelectObject hDestDC, hBMPDest
' Копирование растрового изображения в область-источник
BitBIt hSourceDC, 0, 0, Picturel.ScaleWidth - 1, _
Picturel.ScaleHeight - 1, Picturel.hdc, 0, 0, &НСС0020
' Копирование пикселей из одной области в другую
For 1 = 0 То Picturel.ScaleWidth - 1
For j = 0 To Picturel.ScaleHeight - 1
clr = GetPixel(hSourceDC, i, j)
SetPixel hDestDC, i, j, clr
Next
Next
' Передача скопированных пикселей в другое окно PictureBox
BitBIt Picture2.hdc. О, О, Picturel.ScaleWidth - 1, _
Picture1.ScaleHeight - 1, hDestDC, 0, 0, &НСС0020
' Picture2.Refresh
' Заключительная очистка области памяти
Call DeleteDC(hSourceDC)
Call DeleteObject(hBMPSource)
Call DeleteDC(hDestDC)
Call DeleteObject(hBMPDest)
End Sub
Программа начинается с создания в памяти двух контекстов устройств, hSourceDC (соответствующего растровому изображению в окне левого элемента управления PictureBox) и hDestDC (соответствующего растровому изображению в правом элементе управления
PictureBox). Затем выполняется копирование пикселей из окна элемента управления PictureBox 1 в соответствующий контекст устройства (при создании контекст устройства содержит произвольные данные). Затем в двойном цикле выполняется копирование пикселей из контекста hSourceDC в контекст hDestDC с помощью API-функций GetPixelV() и SetPixelV(). Нетрудно заметить, что методы для вывода изображения в контекст устройства и в контекст области памяти одинаковы.
Во время копирования пикселей содержимое экрана не изменяется. Если создание изображения выполняется в памяти, то Windows неизвестно о том, что предполагается делать с этим изображением в дальнейшем, поэтому никаких изменений на экране не происходит. В конце концов, когда пиксели будут скопированы, следует переместить растровое изображение из памяти (контекст hDestDC) в окно элемента-получателя (окно элемента управления PictureBox2). Это выполняется с помощью функции BitBlt(). В заключение программа освобождает
все ресурсы, созданные во время выполнения операции, с помощью функций DeleteDC() и Delete Object().
Запустите проект CopyPix и щелкните на кнопке Сору Fast, чтобы увидеть, насколько быстрее он работает по сравнению с двумя другими методами. Недостаток этого метода состоит в том, что невозможно наблюдать за скоростью выполнения операции копирования пикселя. Второе изображение появится на экране только тогда, когда все пиксели буду скопированы. Если обрабатываются большие изображения, то функцию BitBlt() придется вызывать чаще (например, при копировании каждого столбца пикселей). Это приводит к появлению некоторой задержки, но метод, описанный в этом параграфе, все равно быстрее двух других. Можно добавить в программу индикатор, позволяющий пользователю получить представление о скорости выполнения программы и времени, оставшемся до ее завершения.
Этим примером заканчивается рассмотрение API-функций. В следующей главе рассмотрены организация взаимодействия программ Visual Basic с внешними приложениями (такими, как Excel и Word) и управление их объектами с помощью VBA. Офисные приложения предоставляют много возможностей, которые можно использовать в VB-приложениях, поэтому не имеет смысла заново их разрабатывать в Visual Basic.
Глава 14 Автоматизация OLE и VBA
• Расширение возможностей Visual Basic с помощью OLE
• OLE-терминология
• Связывание и встраивание
• Применение элемента управления OLE Container
• Автоматизация OLE и VBA
• Программирование объектов Word
• Программирование объектов Excel
• Программирование объектов Outlook
Visual Basic — весьма эффективный объектно-ориентированный язык, позво ляющий скрывать от пользователя многие подробности использования объектов и управления ими. Элементы, используемые для организации интерфейса пользователя, являются объектами, и управление ими осуществляется с использованием соответствующих свойств и методов. Предполагается, что в данный момент пользователь уже хорошо знаком со свойствами объектов Visual Basic.
В этой главе рассматриваются два достаточно сложных аспекта применения объектов Visual Basic: OLE и автоматизация OLE Automation. Средства OLE
позволяют организовать взаимодействие приложений, созданных с помощью Visual Basic, с приложениями, работающими в среде Windows. Средства управления, использовавшиеся до сих пор, были встроенными средствами Visual Basic. Они находятся на панели элементов управления (Tool-box), и их можно поместить в окно формы с помощью мыши. Однако некоторые объекты Windows не входят в состав встроенных средств Visual Basic. Они поставляются вместе с другими приложениями, но их можно использовать и в прикладных программах.
К таким объектам относятся документы, созданные в текстовом процессоре Word, поэтому DOC-файлы можно встраивать в собственные приложения. При этом нет необходимости выяснять детали организации этих файлов или способ записи их на диск. Если нужно редактировать файлы, встроенные в приложение, то можно почти мгновенно вызвать на экран меню Word и соответствующие панели инструментов и отобразить их непосредственно в прикладной программе. После этого можно редактировать документ так, как если бы он находился в Word.
Можно организовать управление приложением, например.
Word, манипулируя его объектами с помощью средств, предоставляемых VBA (Visual Basic for Applications). VBA — популярный и мощный язык, позволяющий программистам быстро приспосабливать популярные прикладные программы (подобные Word и Excel) под выполнение определенных задач, а не разрабатывать новые прикладные программы, удовлетворяющие специфическим требованиям решаемых задач как в мелком бизнесе, так и в крупном. Знания, полученные при изучении Visual Basic, легко применимы при работе с VBA, но прежде следует ознакомиться со структурой и основными принципами функционирования VBA.
В первой части главы рассмотрено, как можно расширить возможности Visual Basic за счет использования OLE, позволяющего включать в ваши программы объекты, предоставляемые другими прикладными программами. Вторая часть главы является введением в VBA. В ней рассмотрены возможности использования всех средств Word, Excel и Outlook непосредственно из VB-приложений с помощью автоматизации OLE и VBA.
Усовершенствованные элементы управления, связанные с данными
В этом параграфе рассмотрены три элемента управления, связанные с данными, которые совершенно отличаются от использовавшихся до сих пор:
• связанный с данными элемент управления List;
• связанный с данными элемент управления ComboBox;
• связанный с данными элемент управления Grid.
В отличие от других элементов управления связанных с данными, эти элементы управления могут отображать поля из нескольких строк. Элемент управления List напоминает обычный элемент управления ListBox, но заполняется он всем столбцом из набора RecordSet. Элемент управления List обладает всеми функциональными возможностями обычного элемента управления ListBox и позволяет вводить новые значения (записи). Связанный с данными элемент управления Grid подобен обычному элементу управления Grid, но может отображать весь набор записей RecordSet. Каждая строка сетки содержит строку (запись) RecordSet, а столбцы соответствуют столбцам (полям) RecordSet.
Эти два связанные с данными элемента управления по умолчанию не установлены. Чтобы использовать их в проектах, необходимо добавить их на панель элементов управления Toolbox. Для этого выполните следующие действия.
1. Чтобы открыть диалоговое окно Components (Компоненты), щелкните правой кнопкой мыши на Toolbox и выберите пункт Components.
2. Установите флажки Microsoft Data Bound Grid Control и Microsoft Data Bound List Control
3. Нажмите кнопку Close, чтобы закрыть диалоговое окно Components.
Установка источника данных
ODBC
Для доступа к базам данных с помощью компонента
Database сначала необходимо установить источник данных System ODBC, воспользовавшись администратором ODBC. Для этого выполните следующее.
1. В меню Пуск выберите команду Настройки, а затем - Панель управления.
2. Выполните двойной щелчок на значке 32bit ODBC (администратор ODBC), чтобы открыть диалоговое окно, показанное ниже.
3. Выберите закладку System DNS, чтобы отобразить уже инсталированные источники данных. В примерах этой главы используется база данных NWIND, поэтому сейчас мы создадим для нее источник данных.
4. Щелкните на кнопке Add, чтобы открыть мастер Create New Data Source (Создание нового источника данных). В этом окне появится список всех драйверов ODBC. Выберите драйвер Microsoft Access и щелкните на кнопке Finish, чтобы открыть диалоговое окно ODBC Microsft Access 97 Setup.
5. В поле Data Source Name (Имя источника данных) введите
NWINDDB (это имя будет использоваться для доступа к базе данных). В поле Description (Описание) введите описание и щелкните на кнопке Select, чтобы выбрать файл NWIND.MDB в папке, где установлен Visual Basic.
6. Щелкните на кнопке ОК, чтобы вернуться в окно администратора ODBC. Теперь в нем появился новый источник данных.
Установка связи с сервером
OLE
Чтобы получить доступ к возможностям, предоставляемым приложением-сервером OLE, сначала необходимо создать переменную, на которую мог бы сослаться Excel. Эта переменная называется объектной переменной (object variable), поскольку она описывает объект, а не целое число и не иные (относительно про стые) типы данных. Характерной особенностью объектных переменных является то, что они выступают в качестве компонентов членов приложения или класса (Class), который они представляют. Например, Excel предоставляет метод Evaluate с помощью которого можно вычислять любые математические выражения. К этому методу нельзя обращаться непосредственно, к нему необходимо обратиться через объектную переменную, которая представляет приложение Excel. Иными словами, нельзя использовать оператор:
Excel.Evaluate "Log(499/0 785)" 'WRONG! (Ошибка!)
Сначала необходимо создать объектную переменную например ExcelObj, а затем вызвать метод Evaluate для переменной ExcelObf
ЕхсеlObj.Evaluate "Log (499/0 785)"
Существует две функции позволяющие создавать объектные переменные. Это функция CreateObject(),
позволяющая создать новый экземпляр приложения, на который можно сослаться и функция Get0bject(), с помощью которой можно связаться с экземпляром приложения, уже запущенного на компьютере. Эти функции будут рассмотрены позже.
Примечание
Чтобы предоставить VB-приложению возможность обращаться к серверам автоматизации OLE, необходимо добавить соответствующую ссылку к проекту с помощью диалогового окна Reference, вызываемого по команде References (Ссылки) меню Project (Проект). Чтобы приложение могло воспринимать ссылки на объекты Excel, необходимо в проект добавить элемент "Microsoft Excel 8.0 Object Library", на объекты Word — элемент "Microsoft Word 8.0 Object Library", и на объекты Outlook 98 — элемент "Microsoft Outlook 98 Object Model"
Создание нового экземпляра
Первый метод установления связи с приложением-сервером
OLE состоит в том, чтобы организовать новый экземпляр приложения, воспользовавшись функцией Create0bject():
Set AppObject = CreateObject(Class, ServerName)
Аргумент
Class — это имя класса приложения-сервера, зарегистрированного в реестре (Registry). Имя класса Word - это строка "Word.Application", а имя класса Excel - "Excel.Application".
Второй параметр (необязательный) является именем сетевого сервера, на котором будет создан объект. Если приложение-сервер постоянно находится на другой машине, следует также указать имя машины, на которой будет создано приложение-сервер с именем Class. Если приложение-сервер было установлено на машине с именем "Toolkit", то для создания нового "экземпляра приложения Excel следует воспользоваться следующим оператором:
Set EXLApp = Create0bject ("Excel.Application", "Toolkit")
Установление связи с уже существующим экземпляром приложения
Если приложение, с которым следует установить связь, уже запущено, нет потребности создавать его новый экземпляр. Можно "войти в контакт" с уже запущенным экземпляром приложения и открыть новый документ. Чтобы установить связь с уже выполняющимся экземпляром приложения-сервера, следует воспользоваться функцией Get0bject():
Set AppObject =
GetObject(pathname, class)
Оба параметра являются необязательными, но хотя бы один из них должен быть определен. Параметр pathname — это полный путь и имя файла документа, который будет открыт с помощью приложения-сервера. Второй параметр, class, является именем класса приложения, зарегистрированного в системном реестре (Registry).
Если указывается документ, который необходимо открыть данным приложением, то не следует указывать имя класса (Class) приложения. Например, разработчику не надо дополнительно указывать, что рабочий лист будет обрабатываться приложением Excel: Системе известно, что файлы с расширением XLS обрабатываются Excel, например:
Set EXLApp = Get0b]ect ("С:\sample files\Sales98.xls")
Вызов этой функции приведет к запуску Excel ( если до этого не был запущен ни один экземпляр). А чтобы установить связь с уже запущенным экземпляром Excel, следует следующим оператором вызвать функцию Get0bject():
Set EXLApp = Get0bject(, "Excel.Application")
Во многих ситуациях нет разницы, будет ли запущен новый экземпляр приложения-сервера, или будет установлена связь с уже запущенным экземпляром. Например, чтобы вызывать метод Evaluate нет необходимости запускать новый экземпляр Excel. Если он уже запущен, следует связаться с ним и выполнить с его помощью вычисление математического выражения. После того как это действие будет выполнено, работающий экземпляр Excel вернется в то же состояние, что и прежде. Поэтому, предпочтительнее (с точки зрения эффективности) пытаться устанавливать связь с существующим экземпляром приложения-сервера. И только в том случае, если нет ни одного запущенного экземпляра сервера, следует его запустить В следующем фрагменте программы применяется именно этот способ. Сначала делается попытка установления связи с уже запущенным экземпляром Word. Если Word не работает, то генерируется сообщение об ошибке. Оператор On Error Resume Next предписывает Visual Basic подавлять сообщение об ошибках и продолжать выполнение программы с оператора, следующего за вызвавшим ошибку. Если происходит ошибка, значит, при вызове функции Get0bject() произошел сбой и следует вызвать функцию CreateObject(), чтобы запустить новый экземпляр Word.
Программа 14.8.
Установление связи или запуск Word
On Error Resume Next
Set AppWord = Get0bject ("Word.Application")
If AppWord Is Nothing Then
Set AppWord - CreateObject ("Word.Application")
If AppWord Is Nothing Then
MsgBox "Could not start Word.Application will quit"
'(Word не был запущен. Программа прекращает работу)"
End
End If
End If
Объявление объектных переменных
Объектная переменная, которая описывает приложение-сервер
OLE, может быть объявлена либо как переменная типа Object (Объект), либо как переменная специального типа (например, Excel.Application или Word.Application). Если переменная EXLApp
объявлена как переменная типа Object (Объект), то каждый раз перед вызовом соответствующих свойств или методов Visual Basic должен сначала удостовериться, что вызываемые элементы существуют. Поскольку Object (Объект) — обобщенный тип переменной, который может включать все типы объектов. Visual Basic не знает, какой именно объект описывает объектная переменная во время разработки, и это не позволяет обнаружить синтаксические ошибки во время ввода программы. Например, если было неправильно набрано имя компонента-члена, Visual Basic не сможет обнаружить эту ошибку во время разработки приложения. Так, например, Excel поддерживает метод Evaluate, который позволяет вычислять
математические выражения. Если объявить переменную EXLApp как Object (Объект), а затем попытаться обратиться к ней, чтобы получить доступ к методу Calculate, Visual Basic не сможет определить наличие ошибки.
Если же объявить переменную EXLApp, как Excel Application, Visual Basic не только не будет захватывать никакие ссылки на несуществующие элементы, но также выведет список компонентов-членов в списке, как только будет поставлена точка после имени переменной EXLApp.
Иными словами если объявлять переменные, правильно указывая их тип, то синтаксические ошибки будут определены еще на этапе ввода программы. При этом приложение не будет работать неправильно только лишь из за того, что в имени члена допущена орфографическая ошибка. Даже если опция Member AutoList выключена эти ошибки будут определены во время трансляции.
Другое, гораздо более серьезное, последствие правильного объявления типа объекта — эффективность. Когда Visual Basic обнаруживает выражение, подобное EXLApp Property, он должен сначала удостовериться что указанное свойство существует, затем связаться с приложением сервером, предоставившим объект EXLApp, и активизировать его компонент Property. Компилятор вставит дополнительные операторы, которые организуют связь с приложением, предоставившим объектную переменную, чтобы удостовериться, что предоставляется запрошенный элемент. Неприятной особенностью является то, что эти операторы будут выполняться каждый раз, когда приложение запрашивает компонент объекта EXLApp. Чтобы избежать этой ненужной задержки, следует просто объявить объектную переменную EXLApp, указав соответствующий тип.
Объявление объектных переменных с указанием типа называется ранним связи ванием (early hounding), поскольку Visual Basic может связывать их с объектами, которые они представляют во время проектирования. Объявление объектных переменных без указания типа (просто переменные типа Object) приводит к позднему связыванию (late-bounding) Visual Basic не может связать их со специфическими объектами во время проектирования, что может привести к появлению любых ошибок уже во время выполнения.
Чтобы воспользоваться преимуществом раннего связывания объектных пере менных следует объявить их, указав соответствующий тип. Однако и применение позднего связывания имеет свои достоинства. Иногда тип объекта, описываемого переменной, заранее неизвестен и выход из такой ситуации заключается в объявлении переменной как Object. Например, требуется организовать программное переключение между объектами Form и Printer. Удобный способ организации вывода на любое из устройств (монитор или принтер) заключается в объявлении переменной OutputObject и последующей установки требуемого значения с помощью одного из операторов
Set OutputObject = Printer
Set OutputObject = Screen
Если вызвать метод Print переменной Output Object, то он будет применен к объекту, который был в последний раз присвоен к объектной переменной OutputObject. В ситуациях такого рода переменная OutputObject не может быть ранне связанной.
Доступ к объектам Excel с помощью объектных переменных
Переменная
EXLObject является объектной переменной, которая предоставляет доступ к объектам Excel. Например, для обращения к текущей рабочей книге следует использовать выражение:
EXLObject.ActiveWorkbook
Чтобы обратиться к активному рабочему листу в активной книге, следует воспользоваться выражением:
EXLObject.ActiveWorkbook.ActiveSheet
Объекты, к которым обычно требуется получить доступ на рабочем листе — это ячейки, которые могут быть представлены семейством ячеек
Cells. Чтобы обратиться к первой ячейке второй строки и присвоить ей значение 99, следует воспользоваться следующим выражением:
EXLObject.ActiveWorkbook.ActiveSheet.Cells(2, 1).Value = 99
Свойства и методы, предоставляемые Excel для организации доступа к ячейкам и изменения их содержимого, рассматриваются далее в этой же главе. Следует учесть, что доступ к ним организуется через переменную, возвращаемую функцией Create0b)ect(). Функция Create0bject() так же, как и функция Get0bject(), возвращает ссылку на OLE-сервер. Эта переменная является шлюзом (gateway) к объектной модели (object model), предоставляемой приложением-сервером. Объектная модель представляет иерархию объектов, соответствующих объектам приложение-сервера (например, ячейки и макросы Excel или предложения и словари Word).
В оставшихся параграфах этой главы будут рассматриваться самые основные объекты Word 97, Excel 97 и Outlook 98 (его бета-версия, появившаяся перед выпуском Visual Basic 6). К моменту выхода этой книги, вероятно, станут доступны версии Word и Excel для Windows 98. Впрочем, приводимые примеры должны работать без изменений. Если у читателя возникнут проблемы, то обновленные версии файлов можно найти на сайте издательства Sybex.
Рассмотрение всех объектов, предоставляемых указанными приложениями, вероятно, потребовало бы трех отдельных книг. Поэтому знакомство с ними ограничивается только основными объектами, предоставляемыми приложениями; приводятся примеры, с которыми можно поэкспериментировать. Ознакомившись с этими объектами и используя справку Object Browser, которая содержит список объектов, предоставляемых каждым приложением, разработчик сможет разрабатывать приложения, которые используют услуги приложения-сервера OLE.
Установка свойств проекта
А теперь немного прервемся, чтобы обсудить диалоговое окно Project Properties (Свойства проекта). Большая часть полей в этом окно очевидны, но не все. Кроме того, некоторые, казалось бы, очевидные опции, имеют разветвления, о которых следует знать. При желании, этот раздел можно пропустить и вернуться к нему, когда потребуется дополнительная информация. Диалоговое окно Project Properties, показанное на рис. 155, позволяет выбрать тип проекта и установить различные опции. Вкладки окна объяснены ниже.
Рис. 15.5. Вкладка General окна Project Properties
Вкладка General
Project Type (Тип проекта).
Этот список содержит те же типы проектов, что и в диалоговом окне File Open (Открыть файл). В этом списке доступны следующие типы проектов Standard EXE, ActiveX DLL, ActiveX EXE и ActiveX control (элемент управления ActiveX). Изменение типа проекта всякий раз, когда вам это кажется необходимым, не всегда возможно или просто. Переключение между ActiveX DLL и Standard EXE проектами допустимо и легко осуществимо. Пусть нужно создать компонент ActiveX DLL. Для упрощения процесса тестирования и отладки можно запустить Standard EXE проект и добавить модуль класса. Когда этот модуль работает в контексте текущего проекта, можно удалить формы из проекта и изменить тип проекта со Standard EXE на ActiveX DLL.
После создания и регистрации (как описано в разделе "Регистрация компонентов ActiveX" этой главы) можно использовать этот класс в любом проекте.
• Startup Object (Стартовый объект). Это поле позволит определить, что происходит при запуске проекта. Проекты ActiveX DLL и ActiveX EXE нельзя выполнять. Компонент ActiveX должен вызываться из кода проекта Standard EXE. Для проекта Standard EXE стартовым объектом может быть форма или подпрограмма Main. Подпрограмма Main должна располагаться в стандартном модуле проекта и создавать первую видимую форму приложения. Программные компоненты не могут иметь в качестве стартового объекта форму. Стартовым объектом компонентов ActiveX EXE или ActiveX DLL должна быть либо подпрограмма Main, либо None. Если изменять тип проекта во время его реализации, то нужно также изменить стартовый объект.
Для групп проектов можно устанавливать различные стартовые объекты для каждого проекта в группе. Для определения стартового проекта щелкните правой кнопкой на названии проекта в окне проекта и выберите команду Set as Start-up.
• Project Name (Имя Проекта). Это свойство является именем компонента и отображается в броузере объектов (Object Browser). Очень важно задать содержательное имя проекта, иначе придется искать различия среди различных компонентов с одинаковым названием Project 1 на диске. Если компонент имеет имя MyComponent и определяет класс, который называется MyClass, то нужно создать объектную переменную для ссылки на этот класс внутри другого приложения с помощью оператора:
Set Object1 = CreateObjectC("MyObject.MyClass")
Изменение имени проекта (или, например, имени класса) после его реализации требует и пересмотра исходного кода программы. Используйте содержательные имена проектов и избегайте таких имен, как Test, Example или Server. Компоненты ActiveX регистрируются в системе - это не просто файлы, лежащие в папке.
• Help File Name (Имя файла подсказки), Project Help Context ID (Идентификатор подсказки). Эти два поля позволяют задать файл справки проекта и идентификатор подсказки. Хотя файлы подсказки не обсуждаются в этой книге, любой компонент, который реализуется (в особенности, компонент ActiveX), должен иметь такой файл.
• Project Description (Описание проекта). Это описание проекта и оно появляется в броузере объектов, когда пользователь выбирает компонент.
• Upgrade ActiveX Controls (Обновление элементов управления ActiveX). Установите эту опцию, чтобы Visual Basic автоматически заменял элементы управления ActiveX их новыми версиями, если желаете обновить один или несколько элементов управления, используемых в проекте.
• Require License Key (Требуется номер лицензии). Это поле позволит защитить компоненты с помощью лицензии. Компоненты ActiveX, созданные с помощью действий, описанных в этой главе, будут работать в любой системе, где они инсталлированы. Предположим, разработана новая ActiveX DLL, которая используется в ваших приложениях. Конечные пользователи должны иметь возможность использовать эти компоненты только во время выполнения соответствующих приложений. Это достигается применением лицензий. Когда вы выйдете на этот уровень разработки компонентов, следует обратиться к документации, чтобы узнать, как создавать лицензии на компоненты.
• Unattended Execution (Фоновое выполнение). Опции в этой секции относятся к многопотоковым ЕХЕ-серверам и не будут обсуждаться в этой книге. Эта опция указывает Visual Basic пропускать все окна сообщений и других форм ввода или вывода, чтобы компонент выполнялся без привлечения внимания пользователя. Если вызван компонент ActiveX EXE, который выполняется на сервере, он не должен выдавать сообщения (которые, возможно, были вставлены в целях отладки) на сервер, а потом ждать реакции пользователя.
Вкладка Component
• Start Mode (Режим запуска). В этой секции можно определить, будет ли ActiveX ЕХЕ-сервер выполняться как отдельное приложение или как компонент ActiveX. Эта опция применима только к компонентам ActiveX EXE, а по умолчанию выбран компонент ActiveX.
• Remote Server (Удаленный сервер). Если установлена эта опция. Visual Basic создает файлы с расширением .vbr и с именем, как у dll-файла. Этот vbr-файл содержит информацию, которая требуется системному реестру Windows для выполнения ActiveX-сервера на удаленном компьютере.
• Version Compatibility (Совместимость версий). Опции в этой секции позволяют установить уровень совместимости версии, которая может быть следующей
• No Compatibility (He требуется). Если эта опция выбрана, совместимость не требуется
• Project Compatibility (На уровне проекта). Если опция выбрана, то активизируется окно Location (место расположения), что позволит искать файл, совместимый с проектом Если опция не выбрана, то окно Location недоступно. При разработке элементов управления ActiveX или программных компонентов, используемых с определенным проектом, щелкните на этой опции и выберите имя проекта в последнем поле вкладки По умолчанию эта опция отмечена для всех ActiveX-проектов, так что каждый раз при изменении элемента управления или кода компонента проект также будет обновляться.
• Binary Compatibility (На уровне кода). Эта опция должна быть выбрана для поддержки совместимости среди проектов, откомпилированных с использованием вашего компонента.
Установление связи с приложением на сервере
Пришла пора использовать полученные знания и посмотреть, как на самом деле выглядит процесс взаимодействия клиент-сервер. Предполагается, что созданные вами страницы обрабатываются сервером. Можете открыть страницу
FORM.HTM (при условии, что ваш компьютер подключен к Web-серверу).
Если окажется, что на компьютере установлен Internet Information Server, то, скорее всего, вы подсоединены к локальной сети и можете проконсультироваться с ее администратором. Если ваш компьютер не подключен к какой-либо сети, то найдите в этой главе сведения о том, как конфигурировать Personal Web Server, и протестируйте примеры этой главы. Personal Web Server является упрощенной версией Internet Information Server, которая работает под управлением Windows 95/98 и обслуживает до 10 пользователей одновременно. Он вполне подходит для создания Web-узла, способного взаимодействовать с клиентским компьютером с помощью серверных сценариев.
Personal Web Server (PWS) входит в состав Visual Studio 6 и Visual Basic. Для его инсталяции необходимо сначала установить Windows NT Option Pack. После инсталяции PWS запускается автоматически при включении компьютера.
Для тестирования сервера скопируйте HTML-файлы, созданные в предыдущих главах, в папку C:\INETPUB\WWWROOT. Это корневой каталог Web-сервера, если только вы не указали другой каталог в процессе инсталяции. Клиенты, которые подключаются к вашему компьютеру с помощью протокола HTML (через модем или с помощью локальной сети), автоматически попадают в этот каталог. Один из фалов, который автоматически копируется в эту папку, называется DEFAULT.HTM и открывается по умолчанию всякий раз, когда клиент подключается к серверу без указания имени документа.
Прежде чем экспериментировать с примерами этой главы, рекомендуется создать виртуальную папку и сохранить в ней файлы. Виртуальной называется обычная папка, например, ASPages, которая отображается Web-сервером на любую папку на жестком диске (т.е. ASPages является синонимом длинного имени папки, например C:\MasteringVB5\HTML\ActivePages\Samples). Для создания виртуальной папки необходимо выполнить следующее.
1. Выберите в меню Пуск строку Программы, затем - Microsoft Personal Web Server и Personal Web Manager. Откроется одноименное окно с разделом Main.
С помощью этой страницы можно запускать и закрывать Web-сервер.
2. Щелкните на значке Advanced на левой панели, чтобы просмотреть список виртуальных папок, установленных на компьютере программой инсталяции.
3. Чтобы добавить новую виртуальную папку, щелкните на кнопке Add, выберите папку и введите ее имя.
Обратите внимание: переключатель Scripts для новой папки уже установлен. Это значит, что вы можете сохранять в ней сценарии. Чтобы в папке можно было хранить сценарии сервера, должен быть установлен переключатель Scripts.
Включаемые файлы
Одну процедуру можно вызывать из многих сценариев. Чтобы избежать дублирования кода процедуры в каждом из сценариев, включите файл с определением одной или нескольких процедур в ASP-файл. Включаемые файлы могут содержать HTML-код. Их содержимое обрабатывается так же, как операторы сценария.
Для включения содержимого текстового файла в ASP-файл используется директива #INCLUDE. Директивой она называется потому, что не является исполняемым оператором — только предписанием для ASP выполнить обычное текстовое включение.
Синтаксис директивы #INCLUDE:
<!- #INCLUDE VIRTUAL|FILE="filename" ->
Теги комментария гарантируют, что эта строка не будет послана клиенту по ошибке. Если включаемый файл находится в виртуальной папке или вложенной в виртуальную, то используется ключевое слово VIRTUAL (Виртуальный). Если необходимо указать абсолютный путь к файлу, используйте ключевое слово FILE. В любом случае за ключевым словом следует путь к файлу. Никаких специальных требований к расширению включаемого файла не предъявляется, однако чаще всего используется расширение INC.
Для включения файла NumStrings.inc, находящегося в папке Support, вложенной в папку ASPages, используйте следующую строку.
<!- #INCLUDE VIRTUAL="/ASPages /Support /NumStrings.inc" ->
Если файл NumStrings.inc располагается в той же папке, что и ASP-файл, в который он включается, можно использовать директиву #INCLUDE с ключевым словом FILE:
<!- #INCLUDE FILE="NumString.inc" ->
Если файл NumString.inc находится в папке Support, вложенной в папку, в которой помещен ASP-файл, используется следующая строка.
<!- #INCLUDE FILE="Support/NumString.inc" ->
Относительный путь использует папку, в которой хранится ASP-файл, как отправную точку. Поэтому можно использовать символы ../ (две точки и косая черта) для указания родительской папки.
<!- #INCLUDE'FILE=". ./Support/NumStrings.inc" ->
Внешний ключ
Поле (столбец) в таблице, которое хранит значение, связанное со значением из другой таблицы, называется внешним ключом. Например, поле в таблице счетов с номером заказчика является внешним ключом. Это же значение в таблице заказчиков является первичным ключом. Внешний ключ должен имеет такой же тип, как и первичный ключ таблицы, с которым он связан.
Вставка графики
Графика играет важную роль в оформлении Web-страниц. Найти страницу не содержащую графику практически невозможно. Гораздо легче обнаружить страницу, которая не содержит текст. Непосредственно в HTML документ графика не вставляется. Документ содержит специальные теги со ссылками на изображения, которые вставляются броузером при открытии страницы. Поэтому графические файлы загружаются отдельно и помещаются на страницу броузером.
В Web (где на счету каждый байт) загрузка должна осуществляться быстро. Желательно поместить максимальное количество информации в минимальном количестве байтов. Несмотря на большое количество графических форматов, доступных сегодня, в Web преобладают два из них
• JPEG (Joint Photograph Expert Group)
• GIF (Graphics Interchange Format)
Эти форматы сжимают графические файлы до приемлемого размера. Файлы JPEG можно сжать в несколько раз (хотя с потерей некоторых деталей), но они обеспечивают хорошее качество изображения. Проблемы возникают при увеличении сжатого изображения, но графика на Web страницах предполагает просмотр в контексте собственной Web страницы GIF формат является одним из самых старых форматов, поддерживает изображения только в 256 цветах, но имеет несколько достоинств. Это единственный формат, поддерживающий прозрачность изображения, коэффициент его сжатия достаточно хорош.
Чтобы вставить изображение в текущий документ, используют тег <IMG> с атрибутом SRC, определяющим размещение изображения на экране. Страница с простым изображением, центрированным на странице, показана на рис. 19.3.
Рис. 19.3. Вставка простого графического файла
Исходный HTML-код для показанной страницы приведен ниже.
<HTML>
<HEAD>
<TITLE>Graphics on the Web pages</TITLE>
</HEAD>
<BODY>
<CENTER>
<Hl>Placing an Image on a Web page</Hl>
<IMG SRC="earthl.jpg"><BR>
Our small planet, centered on the page
</CENTER>
</BODY>
</HTML>
Тег <IMG> имеет следующий синтаксис:
<IMG SRC="picture.jpg">
Тег <IMG> распознает дополнительные атрибуты, но необходимо включить атрибут SRC, который задает место нахождения файла изображения на сервере или URL в Web. Большинство дизайнеров использует изображения из того же каталога, что и остальные файлы Web-узла, или из отдельной папки, предназначенной для хранения изображений. Если изображения находятся на том же сервере, что и документ, то используйте относительную ссылку так, чтобы перенести весь проект в другую папку или сервер без редактирования HTML-файла.
При использовании следующих атрибутов с тегом
<IMG> броузер может манипулировать изображением несколькими способами:
• ALIGN — выравнивает изображение по левому краю, по правому, по центру, верхнему и нижнему краям или середине экрана;
• WIDTH и HEIGHT — задают ширину и высоту изображения;
• BORDER — добавляет к изображению обрамление, видимое, если изображение является гиперссылкой,
• VSPACE и HSPACE — очищают место по вертикали или горизонтали: пустое пространство задается в пикселях;
• ALT — включает текстовое сообщение, отображающееся на экране, когда пользователь отключает графику;
• USEMAP — вставляет растровое изображение.
Броузер может распознавать размеры изображения, но только после того, как оно будет загружено. Задание высоты и ширины изображения ускоряет воспроизведение, поскольку броузеру нет необходимости переставлять элементы, уже размещенные на странице. Помимо основного назначения атрибутов
WIDTH и HEIGHT, их можно использовать для изящных трюков.
Если нужно изменить размер изображения, то можно задать его размер атрибутами WIDTH и HEIGHT, и броузер изменит размер изображения из существующего файла. Например, чтобы создать прямую вертикальную линию шириной в два пикселя, используется квадрат изображения со сторонами в два пикселя и устанавливаются значения <IMG WIDTH=2 and HEIGHT=200 SRC= "pictures.jpg">. Высота изображения будет 200 пикселей. Следует помнить существует опасность искажения изображения атрибутами WIDTH и HEIGHT.
Атрибут BORDER задает ширину рамки вокруг изображения. Рамки шириной в два пикселя автоматически обрамляют любое изображение, используемое для гиперсвязи. Можно исключить автоматическое обрамление атрибутом BORDER==none или задать размер обрамления изображения, включая атрибут BORDER со значением ширины в пикселях. Обрамление на экране не появится, пока изображение не станет гиперссылкой.
Один из аспектов, влияющих на вид изображения, особенно когда вокруг изображения размещается текст, - это наличие свободного пространства между изображением и текстом. Это пространство создается атрибутами
VSPACE и HSPACE. Задайте его размеры по вертикали и горизонтали в пикселях, например, VSPACE=20 или HSPACE=10.
Атрибут ALT отображает на экране альтернативный текст для пользователей, отключающих в броузере изображения (многие отключают вывод изображений на экран, чтобы ускорить загрузку страницы). Атрибут ALT= "Логотип компании" сообщает пользователю, что изображение не отображается на экране броузера, а его место занимает надпись "Логотип компании". Если по каким-то причинам изображение не передано, то пользователь может сам связаться с конкретным Web-узлом и получить рисунок.
Встраивание и связывание объектов во время разработки
В этом параграфе рассмотрено создание простого элемента управления OLE Container для демонстрации встраивания объектов во время проектирования. Встраивание во время разработки следует использовать тогда, если заранее известно, какие объекты понадобятся, или требуется ограничить пользователей приложения использованием только определенных объектов (например, документов Word). Этот метод позволяет выполнять и связывание объектов, но во время проектирования предпочтительнее организовывать встраивание. Встраивание объекта можно выполнить двумя способами:
• путем вставки существующего объекта методом "перетащить-и-опустить";
• путем вставки объекта с помощью диалогового окна
Insert Object (Вставка объекта).
Встраивание методом "перетащить-и-опустить"
Чтобы внедрить объект с помощью этого способа, необходимо выполнить следующие действия.
1. Открыть в Visual Basic новый проект и выполнить двойной щелчок на значке элемента OLE Container в панели элементов управления, чтобы поместить его экземпляр на форму. Visual Basic отобразит диалоговое окно Insert Object (Вставка объекта), в котором можно указать объект, внедряемый в элемент OLE Container.
2. В диалоговом окне Insert Object (Вставка объекта) (см. рис. 14.2) щелкните на кнопке Cancel. (Это означает, что в форму будет помещен пустой элемент управления OLE Container, и позднее можно будет перетащить туда OLE-объект).
3. В окне Properties (Свойства) элемента OLE Container необходимо задать значение свойства SizeMode равным 1 — Stretch (если объект — рисунок, размеры которого можно изменять) или 2 — AutoSize (если объект — текст или рисунок, размеры которого изменять не следует).
Возможные значения свойства SizeMode приведены в табл. 14.1.
Таблица 14.1. Значения свойства SizeMode
Значение | Описание | ||
Clip
Stretch AutoSize Zoom | Размеры отображаемого объекта равны исходным. Если его размеры превышают размеры окна элемента управления OLE Container, то часть изображения отсекается
Размеры изображения объекта подгоняются под размер окна элемента управления OLE Container. При этом изображение может исказиться Размеры окна элемента управления изменяются автоматически, чтобы объект целиком поместился в окно Размеры объекта изменяются так, чтобы он занял максимально возможную часть окна элемента управления OLE Container, сохранив при этом свои первоначальные пропорции |
4. Запустите приложение, которое поддерживает OLE, и откроите файл. В нашем примере документ Word встраивается в элемент управления OLE Container с помощью перетаскивания документа из приложения-источника (Word) на пустой элемент OLE Container.
5. Когда на экране появятся окна запущенных Visual Basic и Word, перетащите документ (или его часть) в пустой элемент управления OLE Container.
Совет
Чтобы в окно элемента управления OLE Container поместить часть документа Word, нужно выделить часть документа, а затем перетащить ее, нажав левую кнопку мыши в любом месте выделенной части. Если окно Visual Basic в данный момент невидимо, то для перехода в него нажмите клавиши Alt+Tab, не отпуская кнопку мыши. При появлении на рабочем столе формы Visual Basic перетащите выделенную часть документа в окно элемента управления OLE Container. Выделенный текст будет удален из исходного объекта (документа Word). Чтобы встроить копию выделенного текста (текст в исходном документе сохраняется), во время переноса фрагмента удерживайте нажатой клавишу Ctrl. При выполнении обычной операции перетащить-и-опустить объект из источника удаляется.
6. Во время перемещения объекта под указателем-стрелкой появляется небольшой прямоугольник. Опустите перетаскиваемый объект на пустой элемент OLE Container. Через некоторое время документ Word появится в окне элемента управления OLE Container (рис. 14.5).
Теперь форма содержит документ Word. При запуске приложения документ Word будет отображаться в окне элемента управления OLE Container. Для его редактирования можно использовать меню и инструментальные панели Word.
Рис. 14.5. Объект, перемещаемый из документа Word, появляется в окне элемента управления OLE Container
Свойства Class, SourceDoc и Sourceltem. Рассмотрим несколько свойств элемента управления OLE Container. При создании объекта в форме окно Properties (Свойства) будет содержать следующую информацию:
• имя прикладной программы, с помощью которой создан объект (свойство
Class);
• данные или ссылка на данные (свойство SourceDoc);
• образ данных (свойство Sourceltem),
данное значение устанавливается только при связывании объектов и определяет данные (в пределах исходного файла), связанные с управлением OLE.
Свойство OLETypeAllowed. Будет исходный документ внедрен или связан с элементом управления OLE Container, зависит от установки значения свойства OLETypeAllowed. Выберите элемент управления OLE Container в форме и найдите в окне Properties свойство OLETypeAllowed. В табл. 14.2 перечислены допустимые значения этого свойства. По умолчанию установлено значение 2 — Either.
Таблица 14.2. Значения свойства OLETypeAllowed
Константа |
Значение |
Описание |
vbOLELmked vbOLEEmbedded vbOLEEither |
0 1 2 |
Элемент управления OLE Container может содержать только связанный объект Элемент управления OLE Container может содержать только встроенный объект Элемент управления OLE Container может содержать либо встроенный, либо связанный объект (установлена по умолчанию) |
OLETypeAllowed в О (Связанный). Значение этого свойства по умолчанию не задает тип создаваемого OLE-объекта, а лишь позволяет определить тип объекта, который может быть создан. Реально используемый тип OLE-объекта указан в диалоговом окне Insert Object (Вставка объекта). Например, если значение свойства OLETypeAllowed равно 2 то в диалоговом окне Insert Object (Вставка объекта) переключатели Create New и Create from File, а также флажок Link становятся доступными. Если же значение свойства OLETypeAllowed равно 0 (Связанный), то переключатель Create New блокируется (нельзя связаться с несуществующим объектом). Если устанавливается значение 1 (Встроенный), то блокируется флажок Link (Связь).
Связывание с помощью диалогового окна Insert Object
Метод перетащить-и-опустить – не единственный способ внедрения или связывания объектов в OLE Container. Опишем, как это выполняется с помощью диалогового окна Insert Object (Вставка объекта).
1. Удалите элемент управления OLE Container из формы Form1 и создайте новый элемент управления OLE Container, воспользовавшись рассмотренными выше рекомендациями.
2. В диалоговом окне Insert Object установите переключатель Create from File (Создать из файла) и флажок Link (Связь) (рис. 14.6). Как уже упоминалось, флажок Link (Связь) иногда блокируется Это происходит, когда значение свойства OLETypeAllowed равно 1 (Встроенный). Чтобы разблокировать флажок Link (Связь), установите значение свойства OLETypeAllowed в 2 (Связанный).
3. Щелкните на кнопке Browse (Обзор), чтобы отыскать требуемый файл.
4. Выбранный файл появится в окне элемента управления OLE Container. При этом может быть видна только его часть. Чтобы увидеть весь объект, измените размеры окна элемента управления.
Рис 14.6 Чтобы связать объект, установите флажок Link (Связать) в диалоговом окне Insert Object
В зависимости от установленного свойства SizeMode изображение в связанном файле может быть искажено. Теперь в элементе управления содержится ссылка на объект, а не его копия. Всякий раз, когда приложение-сервер изменяет связанный объект, объект в контейнере также изменяется.
Примечание
Когда вставляемый объект связывается с оригиналом, приложение-контейнер не содержит никаких данных. После того, как объект вставлен, в приложении-контейнере вы уведете не его копию, как это происходит при внедрении, а изображение объекта, который был вставлен.
Если связанный объект является документом Word, то он появится в окне элемента управления OLE Container (см. рис. 14.5). В ячейке, содержащей значение свойства SourceDoc, содержится путь и имя файла связанного объекта.
5. Оставьте окно Visual Basic открытым, когда открыт документ Word. Внесите изменения в исходный документ и убедитесь, что связанный объект в окне Visual Basic изменяется в реальном масштабе времени. Чтобы это увидеть, запускать приложение не требуется. В режиме проектирования связанный документ модифицируется в реальном масштабе времени, как только редактируется оригинал.
Сохранение встроенных объектов и доступ к ним
Встроенные объекты создаются приложением-сервером, а сохраняются в приложении-контейнере. При встраивании объекта связь между содержимым элемента управления OLE Container и первоначальным объектом не устанавливается. Для редактирования встроенного объекта нужно обратиться к ресурсам программы, с помощью которой объект создан, но данные для нее предоставляет приложение-контейнер. Кроме того, данные во встроенном объекте не сохраняются автоматически. Для сохранения встроенного объекта и изменений, сделанных приложением-сервером, используется метод SaveToFile. Синтаксис этого метода:
OLEl.SaveToFile filenumber
Переменная
filenumber - это числовое значение, определяющее номер открытого файла. Номер передается в двоичном коде.
Ниже приведен фрагмент программы для ввода имени файла и сохранения встроенного документа с помощью метода SaveToFile.
Программа 14.1. Сохранение OLE-данных
Private Sub mnuFileSaveas Click()
Dim fnum As Integer
On Error GoTo Cancel
fnum = FreeFile
CommonDialogI.ShowSave
' Вывод на экран диалогового окна Save As
Open CommonDialogI.FileName For Binary As ftfnum
OLE1.SaveToFile (fnum)
Close ttfnum
Exit Sub
Cancel:
MsgBox "Could not save file" ' (Файл сохранен не был)
Close #fnum
End Sub
Для загрузки объекта, сохраненного как файл данных, предназначен метод ReadFromfile. Его синтаксис подобен синтаксису метода SaveToFile. Следующий
фрагмент программы реализует возможность чтения содержимого элемента управления OLE Container из файла (в котором содержимое было сохранено методом SaveToFile).
Программа 14.2. Чтение OLE-данных
Private Sub mnuFileOpen_Click()
Dim fnum As Integer
On Error GoTo Cancel
CommonDialogI.ShowOpen ' вывод на экран диалогового окна Open
Fnum = FreeFile
Open CommonDialogI.FileName For Binary As #fnum
OLE1.ReadFromFile (fnum)
Close #fnum
Exit Sub
Cancel:
MsgBox "Could not load file" ' (Файл загружен не был)
Close #fnum
End Sub
Примечание
Если значение свойства OLEType — 0 (vbOLELinked), то в указанном файле сохраняется только информация о
связи и о данных изображения. Если значение свойства OLEType — 1 (vbOLEEm), то данные из объекта сохраняются с помощью метода SaveToFile.
Если вы сохраняете файл с внедренным объектом, то с ним сохраняется следующая информация:
• имя прикладной программы, создавшей объект;
• данные объекта,
• метафайл изображения объекта;
Если вы сохраняете файл со связанным объектом, то с ним сохраняется следующая информация:
• имя прикладной программы, создавшей объект;
• имя файла-объекта;
• метафайл изображения объекта.
Данные, сохраненные методом SaveToFile, доступны только приложению-контейнеру и только с помощью метода ReadFromFile.
Названные методы являются методами Visual Basic. Они вызываются непосредственно из прикладных программ, при этом информация о формате представления исходных данных не требуется.
Использование оперативного редактирования
При запуске приложения связанный или встроенный объект отображается прямо в форме Visual Basic. Выполнив двойной щелчок на объекте, пользователь может начать его редактирование. Открыть встроенный объект для редактирования можно несколькими способами (см. параграфы " Общие свойства элемента управления OLE Container" и " Общие методы элемента управления OLE Container” далее в главе). Самый простой способ открыть приложение, предоставляющее объект для встраивания и средства редактирования (меню и панели инструментов) - выполнить двойной щелчок на объекте.
Оперативное редактирование (или оперативная активация) применяется для встроенных объектов. Пользуясь этой возможностью, можно редактировать встроенный объект внутри OLE контейнера. Функциональные возможности приложения-сервера инкорпорируются в контейнер. Оперативное редактирование доступно, если приложение-сервер поддерживает автоматизацию OLE. Если выбрать встроенный объект, то меню и панели инструментов заменят меню и панели инструментов VB-приложения (рис. 14.7). Оперативное редактирование позволяет приложению-контейнеру заимствовать функциональные возможности приложения-сервера встроенного объекта.
Рис. 14.7. Оперативное редактирование документа Word в окне элемента управления в приложении Visual Basic
Предупреждение
Некоторые приложения, использующие OLE, не могут отобразить собственные панели инструментов для оперативного редактирования объекта. Эта проблема связана с самой программой, и средствами VB-приложения не решается.
Встраивание сценария
Сценарий содержится в обработчике события различных элементов управления и процедурах, как обычное приложение Visual Basic. Размещаются сценарии в файле HTML в разделе SCRIPT, который ограничивается парой тегов <SCRIPT>. Поскольку существует несколько языков написания сценария, то в теге <SCRIPT> необходимо указать язык написания сценария. Пример типичного раздела SCRIPT приведен ниже.
<SCRIPT LANGUAGE = VBScript>
(код сценария)
</SCRIPT>
Когда броузер встречает тег <SCRIPT>. он вызывает VBScript-интерпретатор для трансляции и выполнения соответствующего кода. Код, как правило, находится в обработчике события, но можно вставить процедуры, которые вызываются из обработчика события. Если код появляется вне обработчика, как в следующем примере, то он выполняется сразу после загрузки страницы, но до воспроизведения документа броузером на экране. Следующий сценарий отображает текущую дату, как только загружается содержащая ее страница.
<SCRIPT LANGUAGE ="VBScript">
MsgBox "The date is " & Date
</SCRIPT>
Все встроенные элементы управления имеют свойство (или атрибут) Name, которое используется для их идентификации в сценарии. Поскольку встроенный элемент размешается на форме, его полное имя состоит из имени формы, за которым после точки следует имя элемента управления Элемент управления Button, размещенный на форме RegisterForm с помощью строки
<INPUT TYPE=BUTTON NAME="DateBttn" VALUE="Show Date">
доступен в пределах сценария с помощью следующее выражения.
AppForm.DateBttn
Можно изменить заголовок DateBttn, используя следующую ниже команду.
AppForm.DateBttn.Value = "DATE"
Встроенные элементы управления, кроме элемента управления
Select, имеют атрибут VALUE. Значением кнопки является ее заголовок, а значением элемента управления Text — текст, отображенный в элементе управления. Аналогично, значением элемента управления Select является свойство Selectlndex, являющееся индексом текущего выделенного элемента. Свойствами Value и Selectlndex различных элементов можно управлять в пределах сценария.
Наконец, наиболее употребляемым событием в сценариях Web-страниц является событие onClick. которое генерируется после щелчка на элементе управления. Элементы управления Text, TextArea и Select не распознают это событие. Наиболее употребляемым событием для этих элементов управления является onChange — событие, происходящее при изменении текста в элементах управления Text и TextArea или при новом выборе в элементе управления Select.
Вот и все необходимое — начнем написание сценария для Web-страниц. VBScript похож на Visual Basic, поэтому сразу перейдем к примерам.
Встроенные объекты
ASP содержат ряд встроенных объектов, которые освобождают разработчика от тяжелого и неблагодарного кодирования доступа к деталям запроса (например, к его параметрам), поступающего вместе с URL, и переадресации вывода на компьютер клиента.
Request.
Обеспечивает доступ к параметрам запроса, поступившего на сервер вместе с URL. Эти параметры — значения элементов управления на форме — могут быть любой строкой, заданной клиентом из локального сценария. С помощью этого объекта можно получить значения существующих на компьютере клиента cookie (заготовка) (cookie - доел. "пирожок" - строка с данными о пользователе, возвращаемая Web-сервером при регистрации пользователя - прим. ред.) или создать новые.
Response.
Используется для ответа на запрос клиента. Ответ — это выходной поток, переданный на компьютер клиента в виде HTML-документа.
Application.
Предоставляет события для установки значений переменных, используемых пользователями ASP-приложения.
Session.
Предоставляет информацию, касающуюся одного пользователя во время его взаимодействия с приложением. Каждому пользователю назначается отдельный объект Session для хранения значений при переходе от одной страницы к другой. Значения переменных объекта Session после сеанса связи удаляются.
Server. Позволяет серверному сценарию создавать экземпляры компонентов ActiveX и размещать их на сервере. Метод CreateObject объекта Server практически идентичен одноименной функции Visual Basic. С помощью объекта Server создаются объектные переменные, позволяющие расширить возможности приложения по сравнению с HTML.
Введение в
SQL
SQL (Structured Query Language — язык структурированных запросов) — универсальный язык, используемый для управления базами данных. SQL - декларативный язык, в отличие от процедурного языка типа Visual Basic. На декларативном языке определяется, что надо сделать, а не как это сделать. Нет необходимости объяснять SQL, как обратиться к базе данных. Нужно только сообщить ему, что
необходимо извлечь из базы данных. На процедурном языке необходимо подробно описать, как выполнить данную задачу.
Принадлежность языка к процедурному или декларативному типу — это основное отличие между языками третьего поколения, типа Visual Basic, и четвертого, типа SQL. Является ли SQL языком четвертого поколения — сложный вопрос. Он был разработан в 1970-ых годах доктором Коддом (E.F.Codd) в компании IBM. В то время языки не классифицировались по поколениям.
Начнем с рассмотрения структуры SQL-операторов и ключевых слов, используемых в них. Затем приведем примеры SQL-операторов и разработаем средство для выборки данных из базы данных с их помощью.
Для экспериментов с SQL-операторами используется приложение SQLExec, рассмотренное далее в этой главе. Приложение SQLExec позволяет выбрать базу данных, выполнить SQL-операторы и просмотреть результаты их работы (RecordSet).
Ввод данных
Элемент управления Data — мощный инструмент просмотра таблиц и редактирования их содержимого, но как быть с вводом новой информации или удалением существующих записей? Эти действия требуют нескольких строк кода. Ничего сложного в этом нет, просто нельзя полагаться на бескодовый подход к работе с элементом управления Data при вводе данных. Для записи введенных данных используются следующие методы.
• AddNew. Добавляет запись в таблицу.
• Delete. Удаляет текущую запись.
• Update. Записывает текущую запись в базу данных.
• Refresh. Перезагружает данные из базы данных (обновляет RecordSet).
Примечание
На самом деле элемент Data можно использовать для ввода данных. Для этого установите свойство EOFAction элемента управления Data в 2 — vbEOFActionAddNew. Когда пользователь, находясь на последней записи, щелкает на кнопке Next, элемент Data отображает новую пустую запись. Ее можно заполнить и записать в базу данных. Данный метод не нагляден и не отражает способ написания профессиональных приложений для ввода данных.
AddNew. Чтобы добавить новую запись в таблицу, вызовите метод AddNew объекта RecordSet (RecordSet имеет тип Table). Новая пустая запись добавляется в конец набора RecordSet, и на нее устанавливается элемент Data. Теперь можно ввести данные.
Update, Refresh.
Когда пользователь сообщает о намерении сохранить новую запись в базе данных (щелкая на кнопке ОК. или перемещаясь на новую запись), то вызывается метод Update объекта RecordSet. Чтобы отклонить данные, вызовите метод Refresh, который обновляет набор записей, прочитав его из базы данных. Поскольку добавленная запись не была сохранена в базе данных, то при обновлении RecordSet она будет потеряна.
Delete. Для удаления записи вызовите метод Delete объекта RecordSet. Из RecordSet будет удалена текущая запись, но только после того, как механизм JET проверит все задействованные отношения. Если база данных содержит некоторые ссылки, то удалить запись, связанную с другой записью, нельзя. Мы не будем подробно рассматривать целостность ссылок, но покажем, как механизм JET поддерживает ее в базе данных.
Ввод данных с помощью
Visual Data Manager
Visual Data Manager также может быть использован и для ввода данных. Двойной щелчок на имени таблицы в окне Database открывает таблицу в режиме ввода данных (рис. 17.10), в котором можно редактировать, добавлять и удалять записи.
Как выполнять эти операции из кода мы покажем позже, а сначала рассмотрим основные понятия разработки базы данных, исследуя структуру базы данных BIBLIO.
Рис 17.10 Visual Data Manager можно использовать и для ввода данных
Выполнение SQL-выражений
В выполнении SQL-выражений ADO проявляют чрезвычайную гибкость. SQL-выражение можно выполнить с любым их трех объектов (Connection. Command и RecordSet). Каждый из них имеет свои преимущества и недостатки. Проведем их сравнительный анализ.
Запрос с помощью объекта Connection
Первый способ выполнить SQL-выражение — использовать метод Execute объекта Connection.
ADOConn.Execute "SELECT * FROM Products", numRecords, adCmdText
Второй (необязательный) аргумент указывает количество записей, затронутых запросом действия или возвращаемых запросом выбора. Последний аргумент (не обязательный) определяет, является первый аргумент SQL-выражением (aCmdText) или сохраненной процедурой (aCmdStoredProc).
Запрос с помощью объекта Command
Второй способ — создание объекта Command и вызов его метода Execute Объект Command содержит множество свойств. Но указать необходимо хотя бы свойства ActiveConnection (Текущее соединение) и CommandText (Текст команды), как показано в следующем примере.
With ADOConn
.ActiveConnection = connectString
.CommandText = "SELECT * FROM Products", _
numRecords, adCmdText
.Execute
End With
Запрос с использованием объекта RecordSet
Наконец, можно использовать метод Open объекта RecordSet:
ADORSet.Open SQLStatement, connectString, RecordsetType, _
LockType, CommandType
Аргумент
RecordType задает тип объекта RecordSet и имеет одно из следующих значений:
• adOpenDynamic;
• adOpenForwardOnly;
• adOpenKeyset;
• adOpenStatic.
Примечание
Объекты RecordSet этих типов объясняются в следующем параграфе.
Аргумент
LockType задает тип блокировки при обращении к базе данных нескольких пользователей одновременно. Его значением могут быть:
• adLockBatchOptimistic;
• adLockOptimistic;
• adLockPessimistic;
• adLockReadOnly.
Примечание
Управление блокировкой и его типы в следующем параграфе рассмотрены подробнее.
Создадим объект RecordSet с использованием простого SQL-выражения.
Set ADORSet = "SELECT * FROM Products", connectString, _
adOpenForwardOnly, adLockReadOnly, adCmdText
Если необходимо выполнить SQL-выражение, оказывающее воздействие на большое количество записей или сохраненных процедур, то необходимо использовать объект Command. Он не создает курсор
(см. следующий параграф), и является единственным механизмом задания параметров. Избегайте использования SQL-выражений, выполняемых с помощью объекта RecordSet. Этот объект разрабатывался для приема наборов записей, а не для их создания. Кроме того, только объект Command поддерживает транзакции. Так что если требуется выполнить запрос на действие (который реализуется как транзакция), необходимо использовать объект Command.
Взаимодействие клиент-сервер
На рис. 22.1 показана типичная Web-страница для ввода информации, необходимой серверу для извлечения данных из базы. Это страница Infoseek - наиболее популярного справочного Web-узла. В данном примере аргументом поиска является строка "VB + books" (поиск документов VB, содержащих слово "books").
Рис. 22.1. Поиск документов по ключевому слову с помощью Web-узла Infoseek
Нажав кнопку Search (Поиск), клиент пересылает на сервер следующий URL
http://www.infoseek.com/Titles?qt=VB+%2Bbooks&rf=11&lk=noframes&st=10
Здесь
Titles — это имя приложения на сервере, которое будет выполнять поиск в базе данных и возвращать результат. Оно не является ASP-приложением, но в данном случае это не имеет значения. Для ASP-приложения понадобились бы те же параметры, и оно возвратило бы тот же результат. Все, что нужно знать клиенту, — это имя приложения, которое обрабатывает параметры его запроса на сервере. Эта информация помещается в тег <FROM> документа (подробности о размещении элементов управления на Web-странице см. в гл. 20).
Запустите Internet Explorer, подключитесь к узлу Infoseek и передайте аргументы поиска. Когда сервер передаст результаты поиска, вы увидите имя приложения, выполнившего поиск в базе данных на сервере, и аргументы поиска (строку, напоминающую приведенную выше) в поле Address (Адрес) броузера.
Информация, введенная пользователем в форму, передается на сервер в виде значений параметров, за которыми указано URL приложения, предназначенного для обработки этих параметров. Параметры имеют имя и значение.
parameter=value
Если для ввода параметров используется форма, то именами параметров являются имена элементов управления на форме, а значениями — значения элементов. Пары имя-значение отделяются символом '&'.
LastName=Petroutsos&FirstName=Evangelos
Строка с параметрами присоединяется в конец URL с помощью вопросительного знака после имени приложения, обрабатывающего запрос на сервере (имя ASP-файла). Если имя элемента управления содержит пробелы, то каждый из них замещается знаком "+".
Title=Mastering+VB6
В примере с узлом Infoseek имя первого параметра - qt
(сокращение от query text - текст запроса), а его значение - строка "VB+%2Bbooks". В ней пробел заменен знаком "+", а плюс в оригинале запроса - на %2В (2В является шестнадцатеричным значением ASCII-кода знака плюс). Параметр lk=noframes сообщает приложению на сервере, что генерируемый HTML-документ не должен содержать панелей (frame); параметр st=10 определяет,
что имена найденных в результате поиска файлов должны выводиться по 10 штук. На рис. 22.1 видно, что в результате поиска найдено 80000 файлов, но выводиться они будут по 10 за один раз. Всякий раз, когда пользователь выполняет щелчок на гиперссылке "Next 10", значение st увеличивается на 10 (а при щелчке на гиперссылке "Previous 10" — уменьшается на 10). Это вся информация, необходимая приложению Titles для отображения страницы с результатами поиска.
Примечание
В протоколе HTML используется множество символов, имеющих специальные значения, которые нельзя помещать в строку параметров. Например, нельзя использовать символы "/" и "&". Поэтому все специальные символы (т.е. не являющиеся буквой или цифрой) должны быть заменены шестнадцатеричным значением их ASCII-кода, перед которым указан знак процента (%).
Web-сервер запускает приложение, имя которого указано в строке URL, и передает ему полученные параметры. Программы, обрабатывающие запрос пользователя в реальном времени, обычно называют сценариями (scripts). Большая их часть написана на языке Perl.
Примечание
Perl — это аббревиатура от Practical Extraction and Report Language (Практический язык для извлечения данных и создания отчетов). Он является языком написания сценариев для Unix, позволяющим создавать мощные приложения для обработки данных и текстов. Однако рядом с Visual Basic и VBScript язык Perl выглядит подобно китайской грамоте. Программистам, работающим с Windows, он обычно незнаком.
Взаимодействие с
Word
Microsoft Word предоставляет многочисленные объекты, которые можно использовать для программирования любых операций, которые могут быть выполнены с помощью команд меню. Например, можно открыть документ, подсчитать количество слов и символов, заменить в нем некоторые слова, и снова сохранить его на диске — и все это без вмешательства пользователя. Все необходимые действия могут быть выполнены в фоновом режиме, без вывода окна Word на рабочий стол.
Объект верхнего уровня в Word — это объект Application, который представляет собой текущий экземпляр приложения. Можно воспользоваться объектом Application, чтобы обратиться к некоторым общим свойствам окна Word, включая свойство Visible (с помощью которого приложение можно сделать невидимым) и к активным документам (чтобы переключиться на обработке одного из открытых документов).
Ниже в иерархии под объектом Application располагается семейство Documents, которое содержит объект Document
для каждого открытого документа. Используя объектную переменную типа Document, можно обращаться к любому открытому документу (или открывать и создавать новые документы). Наиболее важный объект, который предоставляет каждый документ - это объект Range, представляющий собой непрерывную часть текста. Эта часть может быть словом, частью слова, символами или целым документом. Используя методы объекта Range, можно вставлять новый текст, форматировать, существующий текст (или удалять его), и так далее.
Чтобы адресовать специфические элементы текста, можно воспользоваться следующими семействами:
• семейством Paragraphs (Абзацы), состоящим из объектов типа Paragraph, которые представляют собой абзацы текста;
• семейством Words (Слова), состоящим из объектов типа Word, которые представляют собой слова;
• семейством Characters (Символы), состоящим из объектов типа Character, которые представляют собой отдельные символы.
Например, можно получить доступ ко всем абзацам документа с помощью семейства Paragraphs (Абзацы) объекта Document. Если применить тот же самый метод к текущему выделению (предоставленному объектом Selection), можно получить доступ ко всем абзацам в выделенном тексте. В следующем параграфе будут исследованы элементы базовых объектов, предоставляемых Word, чтобы продемонстрировать, как можно использовать их непосредственно в программе Visual Basic.
Чтобы обратиться к таким объектам, как папки, следует создать место для хранения MAPI сообщений. Память MAPI-сообщении — это источник данных, который предоставляет все типы информации, хранимой в Outlook. Приложение Outlook является, на самом деле, интерфейсной частью базы данных, которая содержит разнотипную информацию. Чтобы обратиться к этой информации, необходимо сначала создать объектную переменную mNameSpace.
Set mNameSpace = OLApp GetNamespace("MAPI")
Приведем фрагмент программы, позволяющий организовать доступ к информации, сохраненной Outlook.
Dim OLApp As Outlook.Application
Dim mNameSpace As NameSpace
Set OLApp = Create0bject ("Outlook.Application")
Set mNameSpace = OLApp.GetNamespace("MAPI")
Используя переменную mNameSpace,
можно обращаться к различным папкам Outlook. Для доступа к папке используется метод GetDefaultFolder, в который в качестве параметра передается имя папки. Метод возвращает объектную переменную, которая обеспечивает свойства и методы для доступа к объектам, хранящимся в папке.
К папкам, обслуживаемым Outlook, можно обращаться с помощью следующих констант (их имена очевидны):
olFolderContacts olFolderDeletedltems olFolderDrafts olFolderInBox olfolder Journal olFolderNotes olFolderOutBox olFolderSentMail olFolderTask
Чтобы получить информацию об объектах, хранящихся в папке Contacts (Контакты), можно воспользоваться следующим выражением:
Set AllContacts = _
mNameSpace.GetDefaultFolder(olFolderContacts).Items
После выполнения этого оператора свойство Items возвратит семейство объектов, хранящихся в папке.
Каждая папка содержит разнотипную информацию. Папка
Contacts (Контакты) состоит из объектов Contactltem, папки InBox и OutBox содержат объекты MailIterm, папка Calendar (Календарь) содержит семейство объектов Appointmentltem. Каждый из этих объектов обладает большим количеством свойств, являющихся, в свою очередь, атрибутами самого объекта. Например, объект Contactltem
обладает свойствами, установка значений которых влияет только на параметры контакта.
Чтобы просмотреть свойства объекта Contactltem, откройте Object Browser, выберите Outlook в окне Class (Класс), а в списке Classes (Классы) щелкните на элементе Contactltem (рис. 14.19). Члены выбранного класса появятся на правой панели. Чаще всего в приложениях используются следующие свойства: LastName, FirstName, Email1 Address, Title, и свойства, начинающиеся с HomeAddress и BusmessAddress. Это поля, которые можно заполнить в диалоговом окне Contact, добавляя или редактируя контакт в Outlook. Если требуются дополнительные поля, можно создать свои собственные. К этим свойствам также можно обращаться по именам полей, но такой способ здесь не рассматривается. Для получения более подробной информации следует обратиться к справочной системе Outlook.
Рис. 14.19. Свойства объекта Contactltem
Общим для всех объектов является свойство EntrylD (идентификатор объекта), являющееся значением типа Long. Значения EntrylD аналогичны значениям ID, которые присваиваются различным записям в базе данных (они идентифицируют запись и предназначены только для этого). Разумеется, нелепо требовать, чтобы пользователь выбирал контакт или сообщение по его EntrylD (более подходящими для этого представляются списки имен или компаний), но их можно использовать для создания закладок соответствующих записей. Если пользователь из Outlook заполняет узлы, перечисленные в окне элемента управления Tree View, сообщениями или контактами, он может воспользоваться полями EntrylD в качестве ключей для соответствующих узлов. Используя такой способ, пользователь может выбирать объекты, основываясь на более содержательной информации, например, имени абонента, названии компании или темы сообщения. Затем, используя значение ID, можно немедленно разыскать требуемый объект в соответствующей папке. В последующих" параграфах будут приведены примеры использования свойства EntrylD.
Взаимодействие с компонентами
ActiveX
Функциональные возможности активных серверных страниц не ограничиваются средствами VBScript и встроенными объектами, описанными в этой главе. Метод CreateObject объекта Server в ваших серверных страницах выполняет ту же роль, что и функция Create0bject() в VB-приложениях. Он позволяет использовать возможности как стандартных OLE приложений-серверов, так и пользовательских компонентов ActiveX (ActiveX DLL). Очень важно, что возможно взаимодействие и с компонентами ActiveX EXE, но при этом может возникнуть ряд проблем. ActiveX DLL являются активными (in-process) компонентами - они загружаются вместе с вызывающим приложением и становятся его частью. Компоненты ActiveX EXE являются пассивными (out-of-process) — независимо от числа вызвавших приложений в оперативной памяти всегда присутствует только один экземпляр компонента. Это может привести к трудноразрешимым проблемам. Например, когда одно приложение присваивает значение глобальной переменной, а другое - изменяет это значение. Поэтому чрезвычайно сложно разработать компонент ActiveX EXE, работающий корректно в любой ситуации.
В гл. 15 мы разработали компонент StringClass (проект NumStr на компакт-диске). В качестве напоминания в табл. 22.2 приведено описание трех методов компонента StringClass для манипулирования числами и строками.
Таблица 22.2. Методы компонента StringClass
Метод | Действие | ||
Number2String(number)
LowerCaps(string) Integer2Binary(number) | Преобразует переданный ему числовой аргумент в строку и возвращает ее. Если вызвать метод с числом 3462 в качестве аргумента, то возвращается значение "три тысячи четыреста шестьдесят два"
Преобразует строку аргумента в нижний регистр (первые буквы всех слов становятся прописными) и возвращает новую строку. Если передать этому методу в качестве аргумента строку "MASTERING visual basic", то будет возвращена строка "Mastering Visual Basic" Преобразует целочисленный аргумент в двоичное число и возвращает двоичное значение в виде строки. Если передать ему в качестве аргумента число 312, то результатом будет строка "000100111000" (без кавычек) |
Чтобы использовать компонент StringClass в ASP-файле, сначала необходимо создать DLL-файл и зарегистрировать его в вашей системе. Процесс создания и регистрации DLL описан в гл. 15.
Для доступа к методам компонента StringClass необходимо создать объектную переменную с помощью следующего оператора.
<%
Set STR=Server.CreateObject ("NumStrings.StringClass")
%>
Переменная
STR служит шлюзом для методов, предоставляемых классом StringClass. Преобразовать число в строку можно следующим образом.
<% STR.Nuniber2String(4325) %>
На рис. 22.11 показана страница NUMSTR.ASP, которая использует метод Number2String компонента StringClass для отображения чисел в виде строк. Обратите внимание: метод Number2String возвращает строку в нижнем регистре. Для перевода первых букв всех слов в верхний регистр воспользуйтесь методом LowerCaps. Можно объединить вызовы обоих методов в одно выражение.
<% STR.LowerCaps(STR.Number2String(4325)) %>
Рис. 22.11. Страница NUMSTR.ASP взаимодействует с компонентом StringClass, расположенным на сервере, для форматирования чисел
Полный исходный текст файла NUMSTR.ASP находится в папке этой главы на компакт-диске.
Для тестирования этого файла необходимо скопировать его с компакт-диска в корневую папку Web-сервера и открыть его с помощью Internet Explorer, задав URL файла в поле Address броузера (127.0.0.1/numstr.asp). Для регистрации компонента StringClass необходимо создать DLL, а затем зарегистрировать ее с помощью утилиты REGSVR32. Откройте проект NumStr с помощью Visual Basic и выберите команду Build StringClass.dll меню File. После того как DLL-файл создан, закройте Visual Basic, откройте окно DOS и перейдите в папку с DLL-файлом. Затем напечатайте следующую команду.
С:\WINDOWS\SYSTEM\REGSVR32 STRINGCLASS.DLL
Более подробно о регистрации компонентов ActiveX можно прочесть в параграфе "Регистрация компонентов ActiveX " гл. 15.
Как только компонент зарегистрирован, любой сценарий, выполняемый на вашем сервере, может обращаться к его методам, как к методам системных компонентов. Так вы можете зарегистрировать все компоненты, разработанные в гл. 15. Обратите внимание: перед использованием эти компоненты загружать не нужно.
Взаимодействие с объектом-контейнером
Предполагается, что элементы управления ActiveX используются как стандартные блоки при конструировании приложения. Поэтому они располагаются на формах или других элементах управления, которые могут функционировать как контейнеры. Разработчику элементов управления ActiveX необходим доступ к свойствам контейнера, чтобы корректировать вид элемента управления в соответствии со значениями свойств контейнера. Существует два весьма полезных для конструирования элементов управления объекта: Extender и Ambient.
Взаимодействие сервер-клиент
Web-узел, состоящий из HTML-страниц, является интерактивным только в том смысле, что позволяет пользователю переходить от одной страницы к другой по гиперссылкам. Клиент запрашивает документы с сервера, и сервер их предоставляет. В этой простой модели взаимодействия, которая преобладает в Web сегодня, Web-страницы находятся на дисках серверов, ожидая запроса клиента. Очевидно, что обновление информации влечет за собой редактирование HTML-документов. Неудивительно, что большинство узлов не предоставляет новейшую информацию.
Недостатком этой модели является то, что клиент в общении с сервером не может связаться с сервером так, чтобы информация пересылалась в обоих направлениях. Разработка такого шлюзового интерфейса как Common Gateway Interface
(CGI) предоставляет возможность Web-разработчикам придать содержимому Web динамику Клиент может послать специфический запрос на сервер (например, "покажите мне счета, подписанные в прошлом месяце" или "покажите мне обычаи Северной Америки"). Сервер не возвращает статическую страницу (которая существует на диске и может быть названа своим именем). Вместо этого он запускает сценарий или приложение, которые вырезают "живые" данные из базы данных, форматируют данные в HTML-документ и пересылают документ клиенту. Клиент видит новейшую, точную информацию.
Недостаток этого подхода — сложность в реализации и поддержке. Для упрощения программирования CGI Microsoft предлагает несколько технологий. Наиболее новой и популярной является ASP — Active Server Pages (Сервер активных страниц - см. гл. 22). Разработка ASP так же проста, как и разработка приложений VB.
Web-приложение
Мы ознакомились с разработкой Web-страниц, взаимодействующих с сервером. Семейство Web-страниц образует Web-сервер. Что же представляет собой 'Web-приложение? Является ли оно приложением, работающим в
Internet? Ответ -и да, и нет. Это приложение клиент-сервер, работающее в Internet, но в остальном Это - обычное приложение. Web-приложение является Web-узлом, который использует ASP-файлы на сервере. Окно обычного приложения соответствует одной странице Web-приложения. Страницы обмениваются информацией с помощью cookies или объектов Application и Session.
Для эффективного использования объектов Application и Session необходимо понимать, что представляют собой ASA-файлы. Каждое Web-приложение имеет файл GLOBAL.ASA, находящийся в корневом каталоге сервера. Этот файл содержит обработчики событий объектов Application и Session. Web-сервер ищет его, когда запускается Web-приложение или начинается сеанс связи с клиентом. Запускается Web-приложение при первом подключении к серверу. При этом сервер ищет файл GLOBAL.ASA, чтобы выполнить обработчик события Application_OnStart. Если обработчик найден, он выполняется.
Одновременно создается новый сеанс. Сервер просматривает
GLOBAL.ASA в поисках обработчика события Session_OnSrart и выполняет его, если таковой обнаружен. При этом создается новый объект Session, ассоциируемый с подключившимся клиентом. Этот объект существует в течение всего сеанса. Когда сеанс прекращается, сервер выполняет обработчик события Session_OnEnd (который должен находиться в файле GLOBAL.ASA).
Рассмотрим типичный файл GLOBAL.ASA. Приведенный ниже файл содержит код, который поддерживает счетчик количества пользователей, которые посетили стартовую страницу узла (переменная Visitors) и пользователей, которые подключены к узлу в данный момент (переменная Viewers).
Программа 22.10. Типовой файл GLOBAL.ASA
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Application_OnStart
Application ("Viewers") =0
End Sub
Sub Session_OnStart
Application.Lock
Application ("Viewers")="Application("Viewers")+1
Application ("Visitors")="Application("Visitors")+1
Application.Unlock
Session ("User") "Request.ServerVariables("REMOTE_ADDR")
End Sub
Sub Session_OnEnd
Application.Lock
Application ("Viewers")="Application("Viewers")-1
Application.Unlock
End Sub
</SCRIPT>
При запуске Web- сервер создает новую переменную Viewers. Этой переменной присваивается значение 0, которое увеличивается на 1, когда начинается новый сеанс, и уменьшается на 1, когда сеанс заканчивается. Таким образом, значение этой переменной всегда равно количеству пользователей, которые подключились к серверу.
Значение переменной Visitors
увеличивается на 1, когда начинается новый сеанс. Она предназначена для хранения общего числа пользователей, посетивших Web-узел. Переменная сбрасывается в 0, когда Web-сервер выключается, поэтому ее значение необходимо сохранить в файле с тем, чтобы его можно было восстановить при следующем запуске приложения. <>
Обработчик события OnStart каждого сеанса запоминает значение IP-адреса клиента в переменной User. Поскольку областью видимости этой переменной является объект Session, т.е. сеанс с конкретным пользователем, ее можно использовать для идентификации клиента.
Обратите внимание: объект Application должен быть заблокирован во время изменения его переменных. Для объекта Session делать это необязательно, поскольку каждый объект Session имеет собственный набор локальных переменных.
При тестировании файла GLOBAL.ASA необходимо создать ASP-файл для доступа к переменным Application и Session, объявленным в файле GLOBAL.ASA. Ниже приведен текст файла VIEWERS.ASP, который генерирует страницу, показанную на рис. 22.10. Для проверки этого файла запустите утилиту WINIPCFG (выберите команду Run меню Start и напечатайте WINIPCFG), которая отобразит ваш IP-адрес. Передайте этот адрес нескольким знакомым и попросите их подключиться к вашему серверу. Теперь при каждом новом подключении переменные Viewers и Visitors должны увеличиваться на единицу, а при отключении - уменьшаться.
Рис. 22.10. Страница, генерируемая файлом VIEWERS.ASP
В программе 22.11 приведен код страницы
VIEWERS.ASP, который совместно с кодом файла GLOBAL. ASA генерирует страницу, показанную на рис. 22.10.
Страница VI EWERS.ASP может располагаться в любой виртуальной папке на вашем сервере, а файл GLOBAL.ASA – обязательно в корневой папке (обычно это папка C:\INETPUB\WWWROOT). Страница отображает количество пользователей, подключенных к серверу, IP-адрес сеанса и основные свойства броузера клиента.
Программа 22.11. Файл VIEWERS.ASP
<HTML>
<FONT FACE= "Comic Sans MS" SIZE=3>
<H1>Welcome to ASP</H1>
There are <% "Application("Viewers") %> users currently connected to
the server.
<P>
You have connected from the following IP address:
<% ^Session ("User") %>
(<% "Session ("HName") %>)
<P>
We already know that your browser:
<BR>
1.
<% Set Browser = Server. CreateObject ("MSWC.BrowserType") %>
<% If Browser.VBscript Then
Response.Write "Can"
Else
Response.Write "Can't "
End If
%> execute VBScript code.
<BR>
2.
<% If Browser.Frames Then
Response.Write "Can"
Else
Response.Write "Can't"
End If
%> display frames.
<BR>
3.
<% If Browser.Tables Then
Response.Write "Can"
Else
Response. Write "Can't"
End If
%> display tables.
</FONT>
</HTML>
Код файла VIEWERS.ASP считывает значения переменных Visitors, Viewers, User и HName
и отображает их на странице. Кроме того, он демонстрирует использование компонента BrowserType (Тип броузера), который возвращает информацию о броузере клиента. Будет разумно проверять основные характеристики броузера клиента перед пересылкой документа, чтобы убедиться, что он будет отображен надлежащим образом. Почти все броузеры способны отображать панели и таблицы, но это не значит, что они могут выполнять VBScript-код.
Web-страница
FORM.HTM
Страница FORM.HTM (см. рис. 19.7) содержит все элементы управления, которые можно поместить на Web-странице для запроса информации от пользователя. Раздел FORM страницы определяется следующим тегом.
<FORM ACTION="ASPages/Register.asp" method="GET">
Данные, собранные на этой странице, передаются приложению REGISTER.ASP на сервере и там же обрабатываются. О том, как писать ASP-файлы (текстовые файлы с командами VBScript) для обработки данных, переданных клиентом, рассказывается в последней главе книги. Необходимо помнить: броузер автоматически передает значения элементов управления на сервер. Поэтому необходимо указать на сервере URL программы, ожидающей эти данные. Использовавшийся в этом примере URL содержит путь к папке ASPdges (в корневом Web-каталоге). Первую часть URL броузер получает из адреса текущего документа. Данные передаются на сервер после нажатия кнопки Register Now на форме.
Остальная часть кода тривиальна. Она использует тег <INPUT> для отображения разнообразных элементов управления. Большинство элементов управления для выравнивания группируется в таблицы. Чтобы узнать структуру страницы (см. рис. 19.7), откройте FORM HTM файл на компакт-диске. Ниже приведен список тегов, относящихся только к встроенным элементам управления (табличные теги пропущены для экономии места).
<FORM ACTION="ASPages/Register.asp" method="GET">
<FONT SIZE=4>
Last Name
<INPUT TYPE=Text SIZE=20 MAXLENGTH=20 NAME="LName">
First Name
<INPUT TYPE=text SIZE=20 MAXLENGTH=20 NAME="FName">
E-Mail Address
<INPUT TYPE=Text SIZE=46 MAXLENGTH-256 NAME="EMail">
My computer is:
My browser is:
<INPUT TYPE=Radio CHECKED NAME="hardware" VALUE="PC"> PC
<INPUT TYPE=Radio CHECKED NAME="browser" VALUE="IE"> Internet Explorer
<INPUT TYPE=radio NAME="hardware" VALUE="MAC"> Macintosh
<INPUT TYPE=radio NAME="browser" VALUE="NETSCAPE"> Netscape
<INPUT TYPE=radlo NAME="hardware" VALUE="OTHER"> Other
<INPUT TYPE=radio NAME="browser" VALUE="OTHER"> Other
When I connected I want to see:
<INPUT TYPE=checkbox name="Sports" value="ON"> <STRONG>Sports
<INPUT TYPE=Checkbox NAME="News" VALUE="ON"> News
<INPUT TYPE=Checkbox NAME="Stock" VALUE="ON"> Stock Prices
<INPUT TYPE=checkbox NAME="weather" value="ON"> Weather
<INPUT TYPE=checkbox name="bargains" value="ON">Our Bargains
Do you want to receive e-mail messages?
<INPUT TYPE=Radio CHECKED NAME="mail" VALUE="Yes">Yes
<INPUT TYPE=Radio NAME="MAIL" VALUE="No">No
Click here to submit your registration
<INPUT TYPE=submit NAME="Register" VALUE="Register Now!">
</FORM>
Если нажать кнопку Register Now, броузер выдаст сообщение, что приложение RAGISTERASP нельзя найти. Эту страницу нельзя протестировать без Web-сервера. Ее содержимое можно просмотреть, как содержимое любой другой страницы, но она не взаимодействует с сервером, пока не открыта на Web-сервере. В гл. 22 пойдет речь о том, как обрабатывать запросы клиентов с помощью Web-сервера. Поскольку приложение REGISTER ASP написано на VBScript, пришло время познакомиться с ним поближе.
Загрузка пользовательских элементов управления
ActiveX
Тестирование пользовательских (специальных) элементов управления на конкретном компьютере является простым процессом, а тестовые страницы будут работать всегда. Если страницу переслать на Web-сервер, а кто-то попытается открыть ее в режиме удаленного доступа, то увидеть элемент управления ActiveX страницы будет невозможно — элемент управления не зарегистрирован на его компьютере.
Если нужно использовать пользовательский элемент управления на конкретном Web-узле, то необходимо создать САВ-файл с ОСХ-файлом элемента управления (и другими файлами поддержки) и переслать его. Когда
Internet Explorer запускает Web-страницу с обычным элементом управления, то он просматривает CLASSID элемента управления в системном реестре. Если Internet Explorer находит его, то элемент управления отображается на странице. Если нет, то он пытается загрузить элемент управления с сервера и установить его на компьютере-клиенте, чтобы использовать его. Конечно, сначала он известит пользователя о том, что страница содержит незарегистрированный элемент управления.
Немногие пользователи согласятся загружать элемент управления с любого узла по Internet. Web-страницы с пользовательскими элементами управления легко можно использовать в Intranet (после установки элементов управления на сетевых компьютерах загружать их снова не нужно), но следует избегать их использования в Web. Можно использовать сертификаты аутентификации, чтобы убедить пользователей в том, что элемент управления безопасен для загрузки и использования. Процесс этот сложный и дорогой, поэтому здесь не рассматривается.
Чтобы загрузить САВ-файл с пользовательским элементом управления. Internet Explorer ищет атрибут CODEBASE в теге <OBJECT>. Атрибут CODEBASE является URL САВ-файла на Web-сервере. А как насчет самого САВ-файла? Visual Basic может создать его с помощью мастера Package and Deployment Wizard. Это отдельное приложение, устанавливаемое Visual Basic для создания дистрибутивов приложений.
Примечание
В книге не рассмотрен мастер Package and Deployment Wizard. Это довольно простая утилита, которая собирает необходимые ей данные и создает ЕХЕ-файл для клиентов или САВ-файл, передаваемый с помощью e-mail на Web-узел. Пользователи загружают этот файл на свои компьютеры, a Internet Explorer автоматически его устанавливает.
Закрытые и дружественные члены класса
Модули классов могут также содержать и закрытые
(private) процедуры. Эти процедуры могут быть вызваны внутри программного кода класса, но другие приложения, которые используют класс, их вызвать не могут. Если необходимо отследить, сколько раз вызывается метод в течение работы приложения, можно добавить функцию:
Private Function CallCounter() As Integer
Static Popularity As Integer
Popularity = Popularity + 1
CallCounter = Popularity
End Function
Эта функция может быть вызвана из кода класса, но приложение, использующее этот класс, функцию CallCounter() не видит. Так как CallCounter() - закрытая функция, она не является методом класса - это обычная функция кода класса. Можно добавить эту функцию в проект CTimer и увидеть, что к ней невозможен доступ из другого приложения.
В добавление к закрытым и общедоступным членам, классы имеют третий тип модификатора области видимости, имеющий название Friend (дружественный). Дружественные члены являются общедоступными для всего проекта и доступны всем классам проекта. Общедоступные переменные Standard ЕХЕ-проекта доступны всем другим модулям и формам. В стандартном ЕХЕ-приложении это самая широкая область видимости, которую может иметь переменная. У компонентов ActiveX, общедоступные члены которых доступны также и из других приложений, есть другой тип, который делает члены доступными из любых частей приложения, но не извне его. Запомните, что только методы (функции или процедуры) и свойства могут быть объявлены как дружественные. Переменные - только как закрытые, либо общедоступные. Это означает, что модули классов ActiveX DLL-проекта могут связываться друг с другом посредством вызова дружественных методов и свойств.
Запись и чтение
Cookies
Стартовые страницы некоторых Web-узлов (например, компании
Microsoft) допускают настройку в соответствии с требованиями пользователя. Как это делается? Каким образом сервер хранит информацию о настройках, выполненных отдельными пользователями, в перерывах между сеансами? Если бы каждый пользователь имел фиксированный IP-адрес, можно было бы (хотя вряд ли это разумно) создать базу данных с IP-адресами и настройками для каждого пользователя. IP-адрес клиентского компьютера хранится в семействе ServerVariables объекта Server. Однако адреса клиентов изменяются от сеанса к сеансу. Поэтому единственный способ сохранить информацию о каждом отдельном клиенте — это ее запоминание на клиентском компьютере и считывание необходимых данных при подключении клиента к серверу. Запоминание этой информации в специальной папке на клиентском компьютере осуществляет броузер. Причем хранится она в cookie.
Примечание
Термин Cookies пришел из операционной системы Unix. Даже не пытайтесь понять, какое это имеет отношение к вашему компьютеру.
Cookies используются для обмена информацией между отдельными страницами одного узла. Предположим, необходимо создать Web-узел для пользователей, работающих в режиме
on-line. Узел может содержать множество страниц, и пользователь должен иметь возможность запрашивать данные с каждой из них. Каким образом сохранить информацию о том, к каким страницам обращался пользователь? Ведь каждая страница может иметь свой собственный сценарий и переменные, областью видимости которых она является. Протокол HTTP работает так: когда на клиентский компьютер поступает новая страница, броузер "забывает" всю информацию о текущей странице кроме ее URL (чтобы была возможность при необходимости вернуться к ней). И здесь весьма кстати оказываются cookies, в которых можно сохранить информацию с предыдущих страниц и организовать обмен данными между страницами одного узла.
Поскольку обработку cookies осуществляет броузер, Web-страницы не имеют прямого доступа к вашему жесткому диску: в этом смысле cookies являются безопасными. Когда страница запрашивает данные из cookies, броузер отслеживает, чтобы использовались только cookies, созданные страницами того же узла. То есть, если некоторые cookies созданы Web-узлом компании Microsoft, то их не могут прочесть страницы, принадлежащие другим узлам.
Cookies могут иметь "срок годности". Те из них, которые его не имеют, прекращают свое существование по окончании сеанса. В противном случае они остаются на клиентском компьютере до истечения этого срока.
Для записи cookies на клиентский компьютер используется свойство Cookies объекта Response. Свойство Cookies является семейством, его члены можно создавать и осуществлять к ним доступ по именам. Для создания нового cookie используется следующий оператор.
<% Response. Cookies ("FavoriteSport") ="Hockey" %>
Если cookie с именем FavoriteSport
уже существует на клиентском компьютере, его значение перезаписывается. В противном случае создается новый cookie, который существует до конца текущего сеанса.
Срок жизни cookie определяется с помощью его свойства Expires.
<% Response.Cookies ("FavoriteSport") .Expires = "December 31, 1998
12:00:00 GTM" %>
Другие свойства cookies перечислены ниже.
Domain (Домен).
Если значение этого свойства установлено, то данные этого cookie передаются только в ответ на запросы, поступившие из того же домена. Используется вместе со свойством Path.
Path (Путь). Если значение этого свойства установлено, то данные этого cookie передаются только в ответ на запросы, поступившие от страниц, находящихся на сервере в указанном пути.
HasKeys (Имеет ключи).
Указывает, имеет ли cookie множественные ключи (т.е. является словарем). Это свойство имеет атрибут "только для чтения".
Чтобы создать cookie с ключами, следует использовать имя одного cookie при установке нескольких атрибутов.
<%
Response.Cookies ("Preferences") ("Books") = "Mystery"
Response.Cookies ("Preferences") ("News") = "Sports"
%>
Для чтения значений из cookie на клиентском компьютере используется семейство Cookies объекта Response. Количество cookie в семействе возвращается свойством Request.Cookies. Count.
Для сканирования элементов семейства используется цикл For...Next либо For Each...Next.
<%
For Each cookie In Request.Cookies
{ обработка текущего cookie, которым является Request.Cookies(cookie)}
Next cookie
%>
Обычно серверному сценарию известны имена cookies, поэтому доступ к ним можно осуществлять по именам.
BookType = Request.Cookies ("FavoriteSport")
При необходимости можно выяснить имена cookies, воспользовавшись циклом For Each...Next. На каждой итерации цикла значение переменной cookie
является именем очередного cookie, а переменная Request. Cookies(cookie) — его значением.
Если cookie имеет ключи, то доступ к ним осуществляется как к элементам семейства. Предположим, вы передали cookie, имеющий ключи, на клиентский компьютер.
<%
Response.Cookies ("Background") = "Planets.bmp"
Response.Cookies ("Preferences") ("Books") = "Mystery"
Response.Cookies ("Preferences") ("News") = "Sports"
%>
Первый cookie задает узор фона, который предпочитает пользователь. Пара следующих значений используется для создания стартовой страницы. Цикл, который читает все значения cookie, включая ключи, приведен ниже.
<%
For Each cookie In Request.Cookies
If Request.Cookies(cookie).HasKeys Then
For Each scookie In Request.Cookies(cookie)
{Обработка текущего cookie. Его значением является Request.Cookies(cookie)(scookie) }
Next
Else
{ Обработка текущего cookie. Его значением является Request.Cookies(cookie)}
End If
Next
%>
Организация обмена данными между страницами - далеко не единственное применение cookies. Каждый узел, имеющий настраиваемую стартовую страницу, использует их для хранения информации о пользователях. Некоторые Web-узлы используют cookies для запоминания информации о темах, обращение к которым происходит чаще всего.
Запросы к другим приложениям
Чтобы организовать запрос к другому приложению, необходимо указать вашей программе, о каком именно приложении идет речь. Один из способов, позволяющий это сделать, заключается в установке указателя мыши в окно другого приложения (информацию о состоянии которого требуется получить). Именно так сделано в приложении Query (рис. 13.8). Эта программа позволяет наблюдать за другими активными приложениями, используя уже известные функции GetCursorPos() и SetWindowPos(), а также нескольких новых функций, рассматриваемых в следующем параграфе.
VB6 в действии: проект Query
В окне приложения Query содержится информация о текущем активном окне и его родительском окне.
Рис. 13.8. Приложение Query
Для получения информации об остальных открытых окнах в этой программе используются следующие функции:
• SetWindowPos()
• GetCursorPos()
• WindowFromPoint()
• GetClassName()
• GetWindowText()
• GetParent()
SetWindowPos().
Функция используется для того, чтобы поместить окно данного приложения поверх окон других приложений. Ключевым элементом в ней является флаг HWND_TOPMOST, установка которого предписывает Windows располагать данное окно перед (либо позади, в зависимости от установки z-order) остальными окнами. Пользователь устанавливает указатель мыши в интересующее его окно и получает о нем информацию. Это достигается за счет использования функций GetCursorPos () и WindowFromPoint().
GetCursorPos(), WindowFromPoint().
Функция GetCursorPosQ возвращает координаты указателя мыши (в системе координат окна). Затем эти координаты используются в функции WindowFromPointO для отыскания имени окна (видимого в точке с указанными координатами). Объявление функции WindowFromPointO имеет вид:
Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As _
Long, ByVal yPoint As Long) As Long
Параметры
xPoint и yPoint являются парой координат. Функция возвращает число типа Long Integer, которое является дескриптором окна, расположенного в данной точке.
GetClassName(), GetWindowText().
Эти функции используются для организации наблюдения за другими приложениями. Функция GetClassName() позволяет получить имя класса окна, a GetWindowText() — текст заголовка окна, если таковой имеется. Если выбранное окно является элементом управления, функция возвращает его текст.
GetParent().
Позволяет получить дескриптор родительского окна для данного окна.
Ниже приведен текст программы Query.
Программа 13.10. Приложение Query
Option Explicit
Private Declare Function SetWindowPos Lib "user32"
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long,
_
ByVal X As Long, ByVal Y As Long, ByVal ex As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" _
(ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetParent Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" (ByVal hwnd As Long, _
ByVal IpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" (ByVal hwnd As Long, _
ByVal IpString As String, ByVal cch As Long) As Long
Const HWND_TOPMOST = -1 ,
Const SWP_SHOWWINDOW = &H40
Private Type POINTAPI
X As Long
Y As Long
End Type
Private gStop As Boolean
Private Sub Commandl_Click()
Dim mousePT As POINTAPI
Dim prevWindow As Long, curWindow As Long
Dim X As Long, Y As Long
Dim tmpStr As String
Dim parentWnd As Long, retValue As Long
‘ Начало отслеживания перемещения мыши
If Commandl.Caption = "Start" Then
Commandl.Caption = "Stop"
gStop = False
prevWindow = 0
‘ Отслеживание идет то тех пор, пока не будет прервано
‘ пользователем
Do
‘ Остановка отслеживания
If gStop = True Then Exit Do
Call GetCursorPos(mousePT)
X = mousePT.X
Y = mousePT.Y
‘ Получение информации об окне, расположенном под
‘ указателем мыши
curWindow = WindowFromPoint(X, Y)
If curWindow
<> prevWindow Then
tmpStr = String$(256, " ")
prevWindow = curWindow
retValue = GetClassName(curWindow, tmpStr, 255)
tmpStr = Left$(tmpStr, InStr(tmpStr, vbNullChar) - 1)
Text1(0).Text = curWindow
Textl(1).Text « tmpStr
retValue = GetWindowText(curWindow, tmpStr, 255)
Text1 (2).Text = tmpStr
‘ Получение дескриптора родительского окна
parentWnd = GetParent(curWindow)
retValue = GetClassName(parentWnd, tmpStr, 255)
tmpStr = Left$(tmpStr, InStr(tmpStr, vbNullChar) - 1)
Text1(3).Text = parentWnd
Text1(4).Text = tmpStr
retValue = GetWindowText(parentWnd, tmpStr, 255)
Text1(5).Text = tmpStr
End If
DoEvents
Loop
‘ Прекращение отслеживания мыши
Else
Commandl.Caption = "Start"
gStop = True
End If
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, _
UnloadMode As Integer)
gStop = True
End Sub
Private Sub Form_Load()
Dim retValue As Long
If Commandl.Caption = "Start" Then
gStop = False
‘ Commandl.Caption = "Stop"
retValue = SetWindowPos(Me.hwnd, HWND_TOPMOST, _
Me.CurrentX, Me.CurrentY, _
Me.Width, Me.Height, SWP_SHOWWINDOW)
Else
gStop = True
Commandl.caption = "Start"
End If
End Sub
Запуск сценариев с помощью
WSCRIPT.EXE
Двойной щелчок на значке сценария — самый быстрый способ его запуска, но такой метод не позволяет использовать аргументы. Когда сценарий не имеет визуального интерфейса, единственной возможностью воздействия на ход его выполнения является передача параметров. Для запуска сценария и передачи ему аргументов необходимо воспользоваться приложением WSCRIPT.EXE.
Для этого выберите в меню Start команду Run, которая открывает диалоговое окно запуска. Введите имя приложения WSCRIPT.EXE, а затем — имя запускаемого сценария. Например, FILEDTR.VBS из папки SCRIPTS на рабочем столе.
WSCRIPT С:\WINDOWS\DESKTOP\SCRIPTS\FILEDTR.VBS
Команда запускает программу WSCRIPT, которая запускает FILEDTR.VBS. Если путь содержит пробелы, то его необходимо заключить в двойные кавычки.
WSCRIPT "С:\WINDOWS\DESKTOP\SIMPLE SCRIPTS\FILEDTR.VBS"
Можно передавать и аргументы, отделив их от команды пробелами.
WSCRIPT С:\WINDOWS\DESKTOP\SCRIPTS\FILEDTR.VBS arg1 arg2
В данном случае используются два аргумента — arg1 и arg2.
Примечание
Множественные аргументы разделяются пробелом (или несколькими пробелами). Запятая воспринимается как часть аргумента.
Кроме среды запуска сценариев, WSCRIPT предоставляет доступ к нескольким возможностям оболочки Windows (к которым VBScript не имеет доступа). Можно рассматривать объекты WSCRIPT как расширение VBScript. Мы начнем с рассмотрения семейства Arguments, которое содержит аргументы, передаваемые сценарию. Далее мы научимся осуществлять доступ к аргументам сценария.
Примечание
Если необходимо передать большое количество аргументов (достаточно распространенная ситуация), то имеет смысл сохранить их в текстовом файле. Пользователю легче ввести дюжину имен файлов, подлежащих обработке, в текстовый файл. Не рассчитываете на то, что пользователь сценария введет длинное имя пути и сделает это правильно с первого раза.
Использование аргументов
Рассмотрим обработку аргументов в коде сценария. VBScript не может обрабатывать аргументы. Свойство Arguments объекта Wscript позволяет сценарию прочесть аргументы. Для этого необходимо создать экземпляр объекта следующим оператором.
Set Args = Wscript.Arguments
Переменная
Args - это семейство со свойствами Item и Count. Для обработки такого семейства можно использовать цикл For... Next
For i = 0 to Args.Count - 1
{Обработка каждого аргумента}
Next
или цикл For Each . . . Next
For Each arg In Args
{Обработка каждого аргумента}
Next
В первом случае доступ к каждому аргументу осуществляется через Args(i), а во втором — через переменную arg. Сценарии ARGS1.VBS и ARGS2.VBS демонстрируют, как это выполняется обоими способами.
Программа 20.13. Сценарий ARGS1.VBS
Set Args = Wscript.Arguments
For i = 0 to Args.Count - 1
txt =
txt & Args(i) & vbCrLf
Next
MsgBox txt
Каждый аргумент — это член семейства Args,
в котором он появляется в том же порядке, в котором был передан.
Программа 20.14. Сценарий ARGS2.VBS
Set Args = Wscript.Arguments
For Each arg In Args
txt = txt & arg & vbCrLf
Next
MsgBox txt
Для запуска этих сценариев необходимо воспользоваться командой Run (Выполнить) из меню Start (Пуск). В диалоговом окне Run необходимо ввести следующую строку.
WSCRIPT "C:\SCRIPTS\ARGS1.VBS" John Doe 33.55
Предположим, необходимо модифицировать путь к сценарию ARGS1.VBS согласно структуре жесткого диска. Двойные кавычки необходимы, так как длинные имена Windows 98 могут содержать пробелы. Аргументы разделены пробелами. Если запустить сценарий с указанными аргументами, то будет выведено сообщение (рис 20.7).
Рис. 20.7. Сценарии ARGS1.VBA и ARGS2.VBA: отображение аргументов в окне сообщений
Нельзя пользоваться запятой в качестве разделителя. Она будет рассматриваться как часть аргумента. Например, если ввести
WSCRIPT "С:\SCRIPTS\ARGS1.VBS" 1, 2, string
результат будет иметь вид, показанный на рис. 20.8.
Рис. 20.8. Параметры сценария не разделяются запятой
Если аргумент содержит пробелы, то его необходимо заключить в двойные кавычки. Например, если последний аргумент в следующей строке будет без кавычек,
WSCRIPT "С:\SCRIPTS\ARGS1.VBS" 1, 2, "string variable"
то семейство Arguments будет содержать четыре аргумента: 1, 2, "string" и "variable" (сами кавычки в аргумент не входят).