Visual2000 · Архив статей Колесова & Павловой
Андрей Колесов, Ольга Павлова
Дополнительно смотрите:
© 1999, Андрей Колесов, Ольга ПавловаЗагрузить программные приложения
(12 Кб, VB-WEB3.ZIP)
Все файлы ZIP-файла
необходимо разместить в каталоге C:\VB-DB\VB6-WEB\EXAM3-1\.
Подробнее о запуске примера см. файл README3.TXT.
В этой статье мы покажем возможности Visual Basic 6.0 по созданию DHTML-приложений, которые структурно представляют собой комбинацию динамических HTML-страниц и программного кода на VB. Напомним, что работа этих приложений основана на DHTML-технологии, реализованной в Internet Explorer начиная с версии 4.0.
Идея нашего проекта такова. Пусть имеется некая база данных, в которой хранятся сведения о сотрудниках фирмы. Мы создадим приложение с использованием двух DHTML-страниц: на первой будет вводиться запрос на поиск сведений о сотруднике (рис. 1), а на вторую будет выдаваться соответствующая персональная информация (рис. 2).
Рис. 1.
Рис. 2.
Мы будем использовать базу NWind.mdb, входящую в состав VB6. [Дополнение от 25.04.00] Чтобы не приходилось заботиться об указании точных путей к файлам, скопируйте ее в корневой каталог C:\VB-DB\. Сам проект будет размещаться в каталоге C:\VB-DB\VB6-WEB\EXAM3-1\. Как выяснилось, DHTML-приложения является довольно чувствительным к изменению адресом файлов проекта.
В ходе выполнения этого примера мы рассмотрим общую логику создания приложения, его структуру, познакомимся с работой встроенного HTML-конструктора, создадим Webстраницу с использованием формы, состоящей из нескольких вкладок. И в итоге получим приложение, которое будет работать...
Загрузите VB6 и в окне New Project выберите элемент DHTML Application. Обратите внимание, что панель инструментов Toolbox приняла вид, специально адаптированный для данного типа приложений (рис. 3).
Рис. 3.
В окне проекта сразу появились две группы элементов - модули и конструкторы HTMLфайлов (рис. 4). В папке Modules автоматически создается модуль modDHTML, который содержит две процедуры - GetProperty и PutProperty - с уже сформированным кодом для управления взаимодействием HTML-модулей данного приложения (мы не будем дальше корректировать содержимое модуля, поэтому можно закрыть этот узел дерева проекта).
Рис. 4.
Мы будем иметь дело Конструктором, содержащим модули, в каждом из которых находится ссылка на базовый HTML-файл и необходимый для него программный код (соответствующий файл на диске имеет расширение DSR). Дважды щелкните элемент DHTMLpage1, после чего на экране появится окно Конструктора. Далее замените в окне Properties свойство Name этого элемента на HRintro и сохраните (Save As) весь проект под именем DHTMLex1.vbp.
Приступим к формированию первого DHTML-элемента. На панели инструментов Конструктора щелкните кнопку DHTML Page Designer Properties (рис. 5). В появившемся окне HRintro Properties установите переключатель "Save HTML in an external file", чтобы сохранить саму HTML-страницу в виде внешнего файла. Этот вариант лучше, чем вариант с сохранением страницы во внутреннем VB-формате, так как позволяет в нужный момент использовать любой внешний редактор, в том числе текстовый, для коррекции содержимого файла.
Рис. 5.
Далее нажмите кнопку New и сохраните создаваемый файл в текущем каталоге вашего проекта под именем Intro.htm. Для завершения процедуры щелкните OK в окне HRintro Properties (рис. 6).
Рис. 6.
Замечание. К сожалению, встроенный HTML-редактор VB6 нельзя отнести к "продвинутым", поэтому внешняя помощь иногда не помешает. Более того, мы не рекомендуем вообще пользоваться этим редактором, и нижеследующий пример работы с ним служит подтверждением этого совета.
Содержимое текущей (для Конструктора) HTML-страницы можно просматривать и редактировать напрямую в редакторе, который вы определили по умолчанию (команда Tools|Options|Advanced). К нему можно обратиться, щелкнув кнопку Launch Editor на панели инструментов Конструктора. Мы же будем сейчас работать со средствами редактирования самого Конструктора и Launch Editor (в нашем случае это Notepad). Конструктор состоит их двух смежных окон: в правом находится собственно графический HTML-редактор, а в левом - дерево, которое отображает структуру HTML-страницы.
Для начала изменим цвет фона станицы. Для этого щелкнем кнопкой Launch Editor и откроем исходный HTML-код нашей страницы, который содержит всего одну сточку:
<body></body></html>
Заменим первый тег <body> на <head></head><body bgcolor="#87ceed">. Зачем здесь нужен тег <head>? Структура HTML-документа требует наличия двух частей — заголовка документа, описывамого тегом <head>, и тела документа, описываемым тегом <body>. Обе эти части располагаются внутри тега <html>. В случае отсутствия тега <head> Конструктор зачем-то дописывает свои строки в заголовок создаваемого временного HTML-файла во время выполнения приложения, в результате чего портится цвет фона выводимого окна. Если интересно - попробуйте указать <head> и посмотрите, что получится.
Выйдем из Notepad (сохранив изменения) и убедимся, что цвет фона стал голубым. Далее, используя средства форматирования (шрифт, размер и пр.), введите в правом поле встроенного редактора Конструктора нужный нам текст (рис. 1). Следите при этом за изменением структуры HTML-страницы в левом окне Конструктора.
Написав в последней строке слово "Сотрудники:", щелкните на панели инструментов элемент списка, который в данном случае называется Select, и разместите его на формируемой нами странице. В окне Properties установите свойство ID данного элемента как cboEmpNames, а свойству Value присвойте пустое значение. Затем аналогичным образом разместите на странице командную кнопку подтверждения SubmitButton и установите ее свойства ID и Value как btnGo и Выбор соответственно.
Замечание. Обратите внимание, что названия и смысловое содержание визуальных элементов DHTML-страниц и их свойств несколько отличаются от обычных VBэлементов. В частности, в VB идентификация элемента управления выполняется с помощью свойства Name, а в DHTML - ID.
Но это еще не все. Еще раз войдите в Launch Editor и удалите в тексте Intro.htm строку:
<OPTION selected value=Select>Select
Иначе у вас в качестве первого значения списка в процессе выполнения приложения будет появляться Select, нумерация списка будет нарушена и поиск по базе данных будет проходить неверно.
Мы закончили формирование первой DHTML-страницы (рис. 7), структура которой представлена деревом в левом окне Конструктора. А сам исходный текст файла Intro.htm должен иметь приблизительно такой вид, как на листинге 1.
Рис. 6.
Правой кнопкой мыши щелкните папку Designers в окне Project, в появившемся меню выберите команду Add, а затем - HTML Page. Здесь возникает вопрос: формировать страницу самим в среде Конструктора или использовать некоторую внешнюю заготовку?
Сейчас мы выберем второй вариант, поэтому в появившемся окне DHTMLpage1 Properties установим переключатель Save HTML in an external file, щелкнем кнопку Open, а затем откроем существующий файл Entry.htm. Далее в окне Properties заменим свойство Name элемента DHTMLpage1 на HRentry и сохраним новый модуль на диске.
Разверните Конструктор во весь экран и внимательно посмотрите на структуру HTML- страницы и на ее внешний вид. Для лучшей наглядности элементов дизайна страницы, щелкните кнопку Show Table Borders на панели инструментов (рис. 8).
Рис. 8.
На странице видны четыре группы графических элементов, обозначенных прямоугольниками с серой границей. На дереве страницы им соответствуют папки dvTab1Sel, dvTab2Sel, dvTabPage1 и dvTabPage2, а в коде HTM-файла границы этих фреймов определяются тегами DIV, которые имеют приблизительно такой вид (для dvTab1Sel):
<DIV id=dvTab1Sel style="HEIGHT: 25px; LEFT: 110px; POSITION: absolute; TOP: 72px; WIDTH: 153px; Z-INDEX: 100"> <p><FONT size=2>Сотрудник</FONT></p> </DIV>
С помощью этих фреймов мы будем формировать две вкладки на выходной форме нашего приложения: dvTabxSel будут использоваться в качестве заголовка, а dvTabPagex — содержимого.
Здесь следует подчеркнуть, что редактор DHTML-Конструктора в VB 6.0 реально годится только для создания довольно простых проектов. (Мы использовали для создания второй страницы MS FrontPage Expess 2.0.) В принципе, некоторое подобие формы, приведенной на рисунке 8, можно создать и в VB 6 (в том числе и сформировать таблицы для dvTabPagex, хотя работа с таблицами в редакторе тоже реализована не очень удачно). Но для оформления фреймов с помощью тегов <DIV> придется корректировать код HTM- файла вручную.
Начнем писать код с входного модуля HRintro. Чтобы попасть в окно кода, нужно щелкнуть правой кнопкой мыши этот элемент в окне Project и выбрать команду View Code. В первую очередь нужно сформировать процедуру BaseWindow_onLoad - именно это событие выполняется в момент загрузки страницы:
Private Sub BaseWindow_onload() ' Описание соединения с используемой базой данных ' используется в обоих DSR-модулях - HRintro.dsr и HRentry.dsr Dim DBname$ DBname$ = "c:\vb-db\Nwind.mdb" ConnectionString = "Provider=Microsoft.Jet.OLEDB.3.51;Persist Security Info=False;Data Source=" + DBname$ ' формирование списка сотрудников Call LoadComboBox End Sub
[Дополнение 25.04.00] Здесь мы описали строковую переменную ConnectionString, которую будем далее использовать для доступа к базе данных в обоих DSR-конструкторах. Сама переменная должна быть описисана как глобальная (Public) в модуле modDHTML.bas. Здесь же происходит обращение к процедуре LoadComboBox (см. листинг 2), в которой выполняется обращение к базе данных Nwind.mbd и формирование списка фамилий сотрудников для элемента управления cboEmpNames (Select). Далее введем следующий код для кнопки "Выбор":
Private Function btnGo_onclick() As Boolean If cboEmpNames.selectedIndex >=0 Then ' фиксация фамилии выбранного сотрудника PutProperty BaseWindow.Document, "EmpID", _ cboEmpNames(cboEmpNames.selectedIndex).Value ' обращение к выходной странице Entry.htm BaseWindow.navigate "Entry.htm" End If End FunctionВНИМАНИЕ! [25.04.00] При повторном тестировании примера мы обнаружили, что программа выдает ошибку при обращении к процедурам PutProperty (в Function btnGo_onclick) и GetProperty (в Sub PopulateTabs). Это стандартные процедуры, сформированные автоматически при создании модуля modDHTML.bas, такие конструкции соответствуют примерам в составе VB 6.0 и раньше они работали. (Примеры самого VB6 также перестали работать в этом месте). Ошибка связана с какой-то проблемой при передаче параметра BaseWindow.Document (тип объекта As HTMLDocument). Возможно, это связано с какими-то обновлениями ПО. Мы решили эту проблему, изменив код приложения, который можно найти в загружаемом проекте-примера.
Если из списка выбран некий сотрудник, производится передача его идентификатора в модуль modDHTML через автоматически сформированную процедуру PutProperty. Далее активизируется страница Entry.htm. (На самом деле запускается на выполнение модуль HRentry.dsr, но почему-то Microsoft решила для обращения к нему использовать не его имя, а название исходной страницы.)
Далее формируем код для выходной HTML-страницы - HRentry. Откроем ее окно кода и введем для события BaseWindow_onLoad:
Private Sub BaseWindow_onload() ' Инициализация страницы Entry.htm ' Заполнение формы данными Call PopulateTabs 'Формирование выходной формы из двух вкладок: Call TabsOnScreen End Sub
Как видите, здесь производится обращение к двум процедурам: PopulateTabs (листинг 3) выполняет поиск данных в базе данных на основе идентификатора, получаемого с помощью процедуры GetProperty, а TabsOnScreen (листинг 4) выводит графическое изображение формы с двумя вкладками на экран. Чтобы завершить написание кода, нужно еще сформировать процедуры dvTab1Sel_onClick и dvTab2Sel_onClick (листинг 5), которые обеспечивают перерисовку вкладок после щелчка их заголовков.
Теперь запустите созданное нами приложение и убедитесь, что все работает, как было задумано. Однако обратите внимание на следующие моменты:
4. При переносе исходных модулей приложения могут нарушиться связи между модулями из-за изменения путей в именах файлов. ВНИМАНИЕ! [25.04.00] К сожалению, оказалось, что коррекция связи DSR-модулей с исходными HTML-файлами НЕ решается простым повторым их открытием в Конструкторе. Для этого трубуется "ручная" коррекция DSR-модуля с помощью текстового редактора типа NotePad - нужно прописать точные адреса исходного и результирующего HTML-файлов в строке параметров SourceFile и BuildFile.
Рис. 9.
</html> <head> </head> <body bgcolor="#87ceeb" id=""> <!—METADATA TYPE="MsHtmlPageDesigner" startspan—> <object id="DHTMLPage1" classid="clsid: F10CB540-E882-11D2-AFCA-ABB579C55564" width=0 height=0></object> <!—METADATA TYPE="MsHtmlPageDesigner" endspan—> <P><STRONG> <FONT size=5 style="BACKGROUND-COLOR: #87ceeb"> Выбор сотрудника</FONT></STRONG></P> <P><FONT style="BACKGROUND-COLOR: #87ceeb"> Для просмотра информации о сотруднике выберите фамилию из приведенного ниже списка и щелкните кнопку "Выбор".</FONT></P> <P> Сотрудники:</P> <P> <SELECT id=cboEmpNames name=Select1 style="HEIGHT: 26px; LEFT: 147px; POSITION: absolute; TOP: 169px; WIDTH: 175px" value = Select1></SELECT> <INPUT id=btnGo name=SubmitButton1 style="HEIGHT: 29px; LEFT: 331px; POSITION: absolute; TOP: 166px; WIDTH: 98px" type=submit value=Выбор> </P> </body></HTML>
Private Sub LoadComboBox() ' формирование списка сотрудников ' Dim con As New ADODB.Connection, rs As New ADODB.Recordset Dim sSQL As String, objEntry As Object, iCnt As Integer ' формирование запроса для открытия базы данных sSQL = "Select EmployeeID, FirstName + ' ' +" & _ "LastName as Name from Employees" con.open ConnectionString rs.open sSQL, con, adOpenKeyset, adLockReadOnly ' формирование списка Do Until rs.EOF Set objEntry = Document.createElement("option") objEntry.Text = rs("Name") cboEmpNames.Add objEntry cboEmpNames(iCnt).Value = rs("EmployeeID") rs.MoveNext iCnt = iCnt + 1 Loop rs.Close con.Close End Sub
Private Sub PopulateTabs() ' 'формирование полей выходной формы данными из ' базы данных по иденификатору сотрудника ' Dim con As New ADODB.Connection, rs As New ADODB.Recordset Dim sSQL As String, iEmpID As Integer ' открываем базу данных C:\NWind.mdb con.open ConnectionString ' получаем идентификатор сотрудника, который ' определен на странице Inrto.htm iEmpID = GetProperty(BaseWindow.Document, "EmpID") ' SQL-запрос на поиск записи sSQL = "Select FirstName + ' ' + LastName as Name," & _ " Address, City, Region, BirthDate, HireDate," & _ " Title From Employees where EmployeeID = " & iEmpID ' поиск и чтение записи rs.open sSQL, con, adOpenKeyset, adLockReadOnly ' переписываем данные на форму txtName.Value = rs("Name") txtAddress.Value = rs("Address") & _ vbCrLf & rs("city") & " " & rs("Region") txtDOH.Value = rs("HireDate") txtBirthDate.Value = rs("BirthDate") txtTitle.Value = rs("Title") rs.Close con.Close End Sub
Private Sub TabsOnScreen() Dim iTop As Integer ' 'формирование выходной формы из двух вкладок: iTop = (dvTabPage1.Style.posTop - dvTab1Sel.Style.posHeight) + 2 dvTab1Sel.Style.Top = iTop dvTab2Sel.Style.Top = dvTab1Sel.Style.Top dvTabPage2.Style.Top = dvTabPage1.Style.Top ' dvTab2Sel.Style.Height = dvTab1Sel.Style.Height dvTab2Sel.Style.Left = dvTab1Sel.Style.posLeft + _ dvTab1Sel.Style.posWidth ' tblPerInfo.Style.Top = tblEmp.Style.Top ' ' изображение в красивом 3D-виде ' With dvTab1Sel .Style.fontWeight = "bold" .Style.cursor = "hand" .Style.backgroundColor = "lightgrey" .Style.borderLeftStyle = "outset" .Style.borderLeft = "whitesmoke solid 2px" .Style.borderRight = "darkgray solid 2px" .Style.borderTop = "whitesmoke solid 2px" .Style.visibility = "visible" End With ' With dvTab2Sel .Style.cursor = "hand" .Style.backgroundColor = "lightgrey" .Style.borderLeft = "whitesmoke solid 1px" .Style.borderRight = "darkgray solid 2px" .Style.borderTop = "whitesmoke solid 2px" .Style.borderBottom = "whitesmoke solid 2px" End With ' With dvTabPage1 .Style.backgroundColor = "lightgrey" .Style.Left = dvTab1Sel.Style.Left .Style.visibility = "Visible" .Style.borderTop = "whitesmoke solid 2px" .Style.borderLeft = "whitesmoke solid 2px" .Style.borderRight = "darkgray solid 3px" .Style.borderBottom = "darkgray solid 3px" .Style.zIndex = "-1" End With ' With dvTabPage2 .Style.backgroundColor = "lightgrey" .Style.Left = dvTab1Sel.Style.Left .Style.visibility = "Hidden" .Style.Height = dvTabPage1.Style.Height .Style.Width = dvTabPage1.Style.Width .Style.borderTop = "whitesmoke solid 2px" .Style.borderLeft = "whitesmoke solid 2px" .Style.borderRight = "darkgray solid 3px" .Style.borderBottom = "darkgray solid 3px" End With End Sub
Private Function dvTab1Sel_onclick() As Boolean ' переключение на первую вкладку dvTab1Sel.Style.fontWeight = "bold" dvTab2Sel.Style.fontWeight = "normal" dvTabPage1.Style.visibility = "visible" dvTabPage2.Style.visibility = "hidden" dvTab2Sel.Style.borderBottom = "whitesmoke solid 2px" dvTab1Sel.Style.borderBottom = "lightgrey solid 4px" End Function Private Function dvTab2Sel_onclick() As Boolean ' переключение на вторую вкладку dvTab2Sel.Style.fontWeight = "bold" dvTab1Sel.Style.fontWeight = "normal" dvTabPage2.Style.visibility = "visible" dvTabPage1.Style.visibility = "hidden" dvTab1Sel.Style.borderBottom = "whitesmoke solid 2px" dvTab2Sel.Style.borderBottom = "" dvTabPage2.Style.zIndex = "-1" End Function
<html> <head> <meta http-equiv="Content-Type" content="text/html; "> <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> <title></title> </head> <body bgcolor="#87ceeb" id="bodyTag"> <h4 align="center"><FONT face="" size=4>Информация о сотрудниках</FONT></h4><FONT face=Arial size=2> <DIV id=dvTab1Sel style="HEIGHT: 25px; LEFT: 110px; POSITION: absolute; TOP: 72px; WIDTH: 153px; Z-INDEX: 100"> <p><FONT face=Arial size=2>Сотрудник </FONT> </p></DIV> <DIV id=dvTab2Sel style="HEIGHT: 31px; LEFT: 351px; POSITION: absolute; TOP: 68px; WIDTH: 131px; Z-INDEX: 100"> <p><FONT face=Arial size=2> Личное дело </FONT> </p></DIV> <P> </P> <P> </P> <DIV id=dvTabPage1 style="HEIGHT: 235px; LEFT: 51px; POSITION: absolute; TOP: 110px; WIDTH: 454px; Z-INDEX: 100"> <P> <TABLE border=0 height=88 id=tblEmp style="HEIGHT: 88px; LEFT: 34px; POSITION: absolute; TOP: 8px; WIDTH: 323px; Z-INDEX: 100" width=323 name = Table1 background=""> <TR> <TD align=left colSpan=2><FONT face="" size=2>Фамилия и адрес сотрудника</FONT> <TD> <TR> <TD align=left colSpan=2> <TD> <TR> <TD align=right><FONT face="" size=2>Фамилия:</FONT></TD> <TD> <INPUT id=txtName name=TextField1 style="HEIGHT: 22px; LEFT: 316px; TOP: 34px; WIDTH: 221px"></TD></TR> <TR> <TD align=right><FONT face="" size=2>Адрес:</FONT></TD> <TD><TEXTAREA cols=25 id=txtAddress name=TextArea1 rows=4 style="LEFT: 159px; TOP: 75px"></TEXTAREA></TD></TR></TABLE></P></DIV></FONT> <P></P> <DIV id=dvTabPage2 style="HEIGHT: 193px; LEFT: 55px; POSITION: absolute; TOP: 378px; WIDTH: 451px; Z-INDEX: 100"> <p><FONT face=Arial size=2> <TABLE border=0 height=112 id=tblPerInfo style="HEIGHT: 112px; LEFT: 26px; POSITION: absolute; TOP: 23px; WIDTH: 352px; Z-INDEX: 100" width=352 name = Table1 background=""> <TR> <TD width=1% colSpan =2 noWrap><FONT size=2>Персональная информация</FONT> <TD id=""> <TR> <TD noWrap align=right><FONT face="" size=2>Дата рождения:</FONT> <TD id=""> <INPUT id=txtBirthDate name=TextField1 style="HEIGHT: 22px; LEFT: 109px; TOP: 54px; WIDTH: 84px"> <TR> <TD align=right noWrap><FONT face="" size=2> Дата приема на работу:</FONT></TD> <TD noWrap> <INPUT id=txtDOH name=TextField1 style="HEIGHT: 22px; LEFT: 94px; TOP: 77px; WIDTH: 84px" readOnly ></TD></TR> <TR> <TD align=right><FONT face="" size=2>Должность:</FONT></TD> <TD noWrap> <INPUT id=txtTitle name=TextField2 style="HEIGHT: 22px; LEFT: 76px; TOP: 102px; WIDTH: 193px" readOnly ></TD></TR></TABLE></FONT> </p> <P></P></DIV> <P></P> </body> </html>