Тема 3.6. Проектирование приложений для Интернет

1.   Создание собственного браузера

2.   Динамические страницы Web - приложения CGI

3.   Сервер Web C++ Builder

4.   Использование форм и таблиц в HTML

5.   Использование шаблонов HTML

6.   Использование активных форм

7.   Обзор дополнительных возможностей работы с Интернет

 

1. Создание собственного браузера

Рассмотрим пример построения простейшего браузера средствами C++Builder. Поместим на форму компонент СррWebBrowser со страницы Internet, установим свойство Align= alClient.

Чтобы просматривать различные HTML документы, добавим в приложение диалог OpenDialog и в свойстве Filter введем:

файлы HTML

(*.html, *.htm)

*.html;*.htm

все файлы

*.*

 

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

if (OpenDialog1->Execute() )

CppWebBrowser1->Navigate(WideString(OpenDialog1->FileName));

Выполним приложение. В браузер с помощью меню Открыть можно открывать любые документы HTML.

Метод Navigate загружает в браузер выбранный документ. Первый обязательный параметр метода Navigate - строка типа BSTR, содержащая имя файла или URL. Строки типа AnsiString автоматически к типу BSTR не приводятся. Поэтому надо использовать явное приведение типа, например, конструктором WideString.

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

Если выберем любой файл со стандартным расширением, увидим, что браузер запустит при открытии файла приложение Windows, которая связана с этим расширением. Например, открытие файла с расширением .bmp вызовет в отдельном окне приложение Microsoft Paint и загрузит в нее этот файл изображения. Можно отрывать видео- и аудио-файлы и они будут исполняться. Можно даже открыть проект C++Builder, и вызовется среда разработки C++Builder с этим загруженным проектом. Можно также открывать и выполняемый файл .ехе.

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

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

Добавим на форму панель CoolBar и перенесем на него инструментальную панель ToolBar. Поместим на панель щелчками правой кнопки мыши две кнопки: первая - ТВВаск, а вторая - TBForward. Это будут кнопки, перемещающие соответственно к предыдущему и последующему из просмотренных документов. Изменим свойство Caption первой на  «Назад», а на второй –на  «Вперед»., Установим свойство Enabled равным false для обеих кнопок, поскольку в момент открытия приложения перемещаться будет некуда. Можно задать и пиктограммы, прибавив в приложение список пиктограмм ImageList.

Перенесем на панель CoolBar компонент ComboBox. В окне редактирования этого списка пользователь сможет набирать URL или имя файла документа HTML, а из выпадающего списка выбирать один из ранее просмотренных документов. Назовем выпадающий список CBURL.

Установим для панели CoolBar свойства AutoSize и ShowText в true. Первое из них обеспечит автоматическое изменение размеров панели при перемещении пользователем расположенных на ней компонентов. А второе обеспечит видимость текстов полос. Выполним щелчок на кнопке с многоточием в окне ИО свойства Bands и в открывшемся окне редактора полос для второй полосы, на которой размещен CBURL, установим свойство Text равным «Адрес:».

Перенесем на форму панель StatusBar. Установим ее свойство SimplePanel в true.

Теперь нужно написать обработчики. Ниже приведен текст модуля.

заголовочный файл:

class  TForm1 : public  TForm

{

published:   // IDE-managed Components

TCoolBar *CoolBarl;

TCppWebBrowser *CppWebBrowser1;

TToolBar *ToolBarl;

TToolButton *TBBack;

TToolButton *TBForward;

TImageList *Imagelndexl;

TStatusBar *StatusBarl;

TOpenDialog *«OpenDialogl;

TMainMenu *«MainMenul;

TMenuItem *N1;

TMenuItem *MOpen;

TComboBox *CBURL;

void _fastcall FormCreate(TObject *Sender);

void _fastcall CBURLClick(TObject *Sender);

void _fastcall CBURLKeyDown(TObject *Sender, WORD SKey,TShiftState Shift);

void _fastcall CppWebBrowser1BeforeNavigate2(TObject *Sender, LPDISPATCH pDisp, Variant *URL, Variant *Flags, Variant TargetFrameName, Variant *PostData, Variant *Headers, VARIANT_BOOL *Cancel);

void _fastcall CppWebBrowser1ProgressChange(TObject *Sender, long Progress, long ProgressMax)

void _fastcall MOpenClickfTObject *Sender);

void _fastcall TBBackClick (TObject *Sender);

void _fastcall TBForwardClick(TObject *Sender);

private:  // User declarations

void _fastcall Load();

public:  // User declarations

_fastcall TForm1(TComponent * Owner);

};

файл реализации:

TForm1 *Form1;

void _fastcall TForm1::Load()

{

// Загрузка URL или файла, заданного в  свойстве  CBURL->Tex

CppWebBrowser1->Navigate(WideString(CBURL->Text));

}

void _fastcall TForm1::FormCreate(TObject *Sender)

{

// Загрузка URL или файла  в момент начала  выполнения

CBURL->Text = "C:\\TESTS\\INTERNET\\HTML1.htm";

Load () ;

}

void _fastcall TForm1::CBURLClick(TObject *Sender)

// Загрузка  при выборе в  CBURL

{

Load () ;

}

void _fastcall TForm1::CBURLKeyDown(TObject *Sender, WORD SKey, TShiftState Shift)

{

// Загрузка  при нажатии Enter на CBURL

 if (Key == VK_RETURN)

Load();

}

void _fastcall TForm1::CppWebBrowser1BeforeNavigate2(TObject *Sender, LPDISPATCH pDisp, Variant *URL, Variant *Flags, Variant *TargetFrameName, Variant *PostData, Variant *Headers, VARIANT_BOOL *Cancel)

// Обработка  события перед загрузкой

{

// Управление  списком  CBURL

int Index = CBURL->Items->IndexOf(AnsiString(*URL) ) ;

if (Index ==-1)

{

CBURL->Items->Insert(0,AnsiString(*URL) ) ;

CBURL->ItemIndex = 0;

}

else CBURL->ItemIndex = Index;

// Задание доступности кнопок  TBForward и  ТВВаск

TBForward->Enabled = (CBURL->ItemIndex > 0) ;

TBBack->Enabled=(CBURL->ItemIndex < CBURL->Items->Count-1);

}

void _fastcall TForm1::CppWebBrowser1ProgressChange (TObject *Sender, long Progress, long ProgressMax)

{

// Занесение текста  в  панель состояния

if(Progress >0)

StatusBarl->SimpleText =Format("Документ %s: прочитано %d Кбайт из %d", ARRAYOFCONST((AnsiString(CppWebBrowser1->LocationName) , (int)(Progress / 1024), (int)(ProgressMax/1024))));

}

void _fastcall  TForm1::MOpenClick(TObject *Sender)

{

if (OpenDialogl->Execute ())

{

CBURL->Text = OpenDialogl->FileName;

Load() ;

}

}

void _fastcall  TForm1::TBBackClick(TObject *Sender)

{

// Переход  на предыдущий документ

CBURL->Text= CBURL->Items->Strings[CBURL->ItemIndex + 1];

Load ();

}

void _fastcall TForm1::TBForwardClick(TObject *Sender)

{

// Переход на следующий документ

CBURL->Text = CBURL->Items->Strings[CBURL->ItemIndex - 1] ;

Load() ;

}

Рассмотрим подробнее приведенный код. В раздел private класса формы введена функция - утилита Load, которая методом Navigate загружает в браузер файл или URL страницы Web, указанный в окне списка CBURL.

Функция FormCreate заносит в список CBURL имя файла или URL страницы Web-документа, который должен открываться в момент начала выполнения приложения. Если нет необходимости автоматически открывать какой-то документ в первый момент, то обработчик события OnCreate не нужен. Если нужно открыть в первый момент страницу Web, можно занести в список CBURL ее URL. Например:

CBURL->Text  = "http://www.icc.dgu.ru/index.html";

Если нужно в первый момент отображение домашней страницы,  достаточно выполнить оператор: CppWebBrowser1->GoHome() ;

После задания текста списка CBURL в функции FormCreate следует вызов утилиты Load. Та же утилита Load вызывается при выборе пользователем адреса в списке CBURL (функция CBURLClick) и при нажатии пользователем клавиши Enter в окне этого списка (функция CBURLKeyDown).

Функция CppWebBrowser1BeforeNavigate2 является обработчиком события OnBeforeNavigate2 компонента CppWebBrowser, наступающего перед переходом браузера на новый документ. Оно наступает независимо от того, чем вызван этот переход: выполнением метода Navigate или переходом по ссылке в окне браузера. Передаваемый в обработчик параметр URL является адресом, по которому будет осуществляться переход. Параметр Cancel=false прервет переход на новый документ.

В обработчике CppWebBrowser1BeforeNavigate2 прежде всего методом IndexOf определяется индекс нового URL в списке CBURL. Здесь выполнено явное приведение адреса в URL к типу AnsiString конструктором AnsiString. Если метод IndexOf вернул -1, значит данного адреса ранее в списке не было. В этом случае он включается методом Insert в первую позицию списка и индекс списка устанавливается на 0. Если новый адрес уже был в списке, то индекс списка устанавливается равным этому значению. В обоих случаях изменение индекса списка обеспечивает отображение в его окне нового адреса.

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

Функция CppWebBrowser1ProgressChange является обработчиком события браузера OnProgressChange. Эти события происходят во время загрузки страницы в браузер. В обработчик передаются параметры Progress - объем загруженного документа и ProgressMax - полный объем документа. Когда загрузка завершена, значение Progress становится равным -1. В обработчике CppWebBrowser1ProgressChange использовано свойство LocationName - имя загружаемого документа, извлеченное из URL.

Функция MOpenCIick является обработчиком щелчка на разделе меню Открыть. Имя выбранного пользователем файла загружается в свойство Text списка CBURL, после чего вызывается утилита Load.

Функции TBBackClick и TBForwardClick являются обработчиками щелчков на кнопках Назад и Вперед. В них в качестве текста списка CBURL задается текст элемента соответственно следующего или предыдущего в списке по отношению к текущему элементу.

Запустите приложение. Пользователь может ввести в окно списка Адрес ссылку на URL страницы Web или имя файла и соответствующий документ будет открыт. Аналогично можно перейти на любую ранее открывавшуюся страницу, выбрав ее адрес из выпадающего списка. Можно открыть любой документ HTML, выбрав имя файла в диалоге, вызываемом командой меню Открыть. Достоинство создания браузера средствами C++Builder состоит в том, что можно создать специализированный инструмент, предназначенный для конкретных задач, удобный пользователю и лишенный той избыточности, которая неизбежна при работе с универсальными приложениями. В частности, это может быть браузер, допускающий просмотр только ограниченного количества ресурсов. Это может быть полезно в корпоративных сетях Интранет.

 

2. Динамические страницы Web - приложения CGI

 

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

В основном используется два основных способа формирования динамического документа:

вызов сервером исполняемой программы, которая формирует динамический документ, осуществляется интерфейсами CGI и WIN-CGI;

обращение сервера к библиотеке DLL, формирующей ответ клиенту, осуществляется интерфейсами ISAPI и NSAPI.

Исполняемые на сервере приложения CGI или WIN-CGI и динамически присоединяемые библиотеки DLL, использующие программный интерфейс ISAPI или NSAPI, имеют свои преимущества и недостатки.

Приложения CGI (Common Gateway Interface) получают от сервера информацию, передаваемую через стандартный ввод и переменные окружения. Формируемый документ HTML, который должен быть послан пользователю, как правило, помещается приложением CGI в стандартный вывод.

Некоторое преимущество прикладных программ CGI над приложениями ISAPI  или NSAPI состоит в том, что такую исполняемую программу можно использовать практически на любом сервере Web.

Однако эффективность CGI заметно ниже. Дело в том, что каждый раз, когда прикладная программа вызывает программу CGI, сервер Web должен создать новый процесс, выполнить CGI-программу, результаты работы возвратить пользователю и, в заключение, освободить использовавшиеся ресурсы. А программные интерфейсы ISAPI и NSAPI позволяют серверу выполнять задание внутри своего пространства процессов и не порождать новый процесс в результате каждого динамического запроса.

 

3. Сервер Web C++Builder

Создание модуля Web

В C++Builder имеется инструментарий, который позволяет легко решать проблемы взаимодействия клиента и сервера.

Серверные приложения строятся на основе модуля Web - компонента типа TWebModule. Этот компонент служит контейнером для ряда других компонентов. Сервер типа TWebModule отсутствует в палитре компонентов. Проектировать его можно командой File|New|Other и в окне New Items на странице New выбрать пиктограмму Web Server Application. Откроется окно, в котором нужно указать тип модуля. Выберите тип CGI Standalone executable - выполняемый модуль CGI. После этого C++Builder создаст в Редакторе Кода заготовку соответствующего модуля и откроется окно модуля, в котором можно размещать компоненты, создающие страницы, осуществляющие связи с базами данных и т.п. В контекстном меню нужно вызвать редактор действий, и в нем появится дерево действий, которые нужно вводить в модуль (вначале, конечно, вершина Actions в нем будет пустой). Это окно помогает осуществлять навигацию по действиям.

В окне Инспектора Объектов появятся свойства модуля Web. Основное свойство модуля - Actions. Это собрание действий - объектов типа TWebActionItem. Заполняется это список специальным редактором действий, вызываемым щелчком на кнопке с многоточием в окне Инспектора Объектов рядом со свойством Actions или при  выборе из контекстного меню раздел Action Editor. В открывшемся окне кнопкой Add New можно добавить новое действие, кнопкой Delete Selected - удалить выделенное действие, кнопками со стрелками - изменить последовательность действий.

Каждое действие - объект типа TWebActionItems со своими свойствами, методами, событиями. Свойства можно увидеть в Инспекторе Объектов, выделив одно из действий. Основное свойство действия - PathInfo. Чтобы понять его назначение, надо сообщить некоторые дополнительные сведения об URL. URL обычно может выглядеть, например, так:

http://www.myserv.com/p1/serv1.exe/action1?value=5&Resp=Yes

Начинается URL с указания протокола (HTTP). Далее следует имя хоста - адрес сервера (в приведенном примере «www.myserv.com»). Затем следует имя серверного приложения и путь к нему (в приведенном примере «/pl/serv1.exe»). После этого, начинаясь с последнего символа слэша и до вопросительного знака записывается необязательная часть URL, именуемая PathInfo. В приведенном примере это «/action1». Эта информация определяет способ обработки информации серверным приложением. Например, может указываться процедура, которая должна обрабатывать данное сообщение. После символа вопросительного знака следует часть URL, называемая Query - запрос. Обычно состоит из списка, включающего идентификаторы, символы равенства и значения этих идентификаторов. Отдельные элементы списка отделяются друг от друга символами "&". В приведенном примере введено имя value со значением «5» и имя Resp со значением «Yes». Это информация, которая передается процедуре серверного приложения для обработки.

Вернемся к рассмотрению свойств действия и к главному свойству - PathInfo. Это свойство совпадает с элементом PathIfo запроса URL. При получении запроса производится поиск действия, в котором PathInfo совпадает с запросом PathInfo. Если такое действие найдено, и оно имеет обработчик события OnAction, то выполняются операторы, записанные в этом обработчике. Заголовок обработчика имеет вид:

WebModule1WebActionItemlAction(TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled)

Параметр Request определяет объект запроса типа TWebRequest. Основное свойство этого объекта Query - строка типа string, представляющая часть Query запроса URL. В приведенном примере URL она имеет вид: «value=5&Resp=Yes». Другое свойство объекта запроса - QueryFields типа TStrings. Это свойство представляет Query запроса URL в виде списка строк. В приведенном примере он будет содержать две строки: «value=5» и «Resp=Yes». Таким образом, через объект QueryFields обработчик события получает доступ к содержащейся в запросе информации. Обращаться к значениям параметров запроса удобно с помощью метода Values[имя]. Например, в приведенном примере выражение Request->Query-Fields->Values["Resp"] вернет строку «Yes».

Параметр Response определяет объект ответа типа TWebResponse. Основное свойство этого объекта Content - ответ пользователю типа string в виде текста HTML, имени файла HTML и некоторых других видов.

Параметр Handled определяет, завершен ли ответ, или объект Response должен дополнительно формироваться другими действиями. Если требуется, чтобы формирование Response завершили другие действия, следует в обработчике задать значение Handled равным false. Тогда, если ответом займется другое действие, ему будет передан объект Response, в котором свойство Content содержит текст, занесенный предыдущими действиями.

У объекта действия есть также свойство Default. Если в одном из действий установлено в true, то это действие является действием по умолчанию. Если в модуле не нашлось действия, в котором PathInfo совпадает с запросом, то наступает событие OnAction действия по умолчанию. Свойство Enabled объекта действия определяет его доступность.

Сервер типа TWebModule имеет два события, которые часто используются для управления сервером - BeforeDispatch и AfterDispatch, наступающие в начале и в конце обработки запроса. Их заголовки подобны приведенному выше для события OnAction. При получении запроса наступает событие BeforeDispatch. В его обработчике можно проанализировать запрос и дать на него ответ или произвести настройку сервера, например, сделать с помощью свойств Enabled доступными или недоступными отдельные действия. Затем наступают события действий. В конце наступает событие AfterDispatch. В его обработчике можно проанализировать ответ, сформированный действиями, и что-то в нем изменить.

Пример серверного приложения

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

Нужно создать модуль сервера (команда File|New|Other, пиктограмма Web Server Application). Откройте редактор действий и занесите в него два действия. Первое действие будет формировать ответ на выбор пользователя.

Свойство PathInfo задайте равным «/1». Второе действие будет действием по умолчанию. Его назначение - задать пользователю вопрос. Установите свойство Default = true.

Для действия по умолчанию обработчик OnAction может иметь вид:

void  _fastcall TWebModule1::WebModule1WebActionItem2Action(TObject *Sender, TWebRequest *Request, TwebResponse  *Response, bool &Handled)

{

Response->Content  = "<hl>  Знаете ли  вы дважды два?  </hl>"

"<р>Сколько будет 2x2 ?</p> <HR>" "<А  HREF=\"/cgi-bin/TwiceTwo.exe/l?4\"> 4</А> или " "<А  HREF=\"/cgi-bin/TwiceTwo.exe/l?5\">5</A> ?, <HR>";

Handled  =  true;

}

Этот код возвращает документ HTML. Пользователю предоставляются на выбор две ссылки с текстами «4» и «5». В обеих ссылках PathInfo равняется «/1». Таким образом, обе ссылки направляют запрос первому действию, у которого задано это значение PathInfo. Но запрос Query в этих двух ссылках разный: «4» и «5». Так что по значению запроса в первом действии можно распознать, какую из ссылок выбрал пользователь. Обработчик события OnAction первого действия может иметь вид:

void  _fastcall TWebModule1::WebModule1WebActionItemlAction(TObject *Sender, TWebRequest *Request, TWebResponse "Response, bool &Handled)

{

 if(Request->Query  == "4")

Response->Content  = "Ответ 4. Вы  прекрасный  математик!";

else  Response->Content  ="Ответ  5. Вы немного  забыли  таблицу  умножения.";

Handled  =  true;

}

Этот обработчик формирует разные ответы в зависимости от значения свойства Request.Query.

Приведенный пример демонстрирует модуль сервера с несколькими действиями.

 

4. Использование форм и таблиц в HTML

 

Обработка ответа пользователя

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

Введенные клиентом в форму данные кодируются в специальный формат и посылаются на сервер.

Форма начинается с тега <FORM>, в котором нужно задать несколько атрибутов. Атрибуты задаются в формате «имя=значение». Адрес URL получателя данных, внесенных пользователем в компоненты формы, указывается атрибутом action. Например:

Action="http://mycomputer/cgi-bin/test.exe"

Атрибут method задает имя используемого метода протокола HTTP. Возможны два значения метода - «get» и «post». Метод get используется для передачи данных формы серверному приложению, которое должно сформировать ответ на основе этого запроса, и вернуть его клиенту. Метод Post предназначен для публикации данных в Web. Если форма использует метод Post, то в серверном приложении данные можно прочитать в свойстве ContentFields объекта, передаваемого в обработчик события OnAction действия параметром Request. Если в запросе применяется метод Get, то данные запроса будут находится в свойстве QueryFields объекта Bequest.

Компоненты вводятся в форму с помощью тегов <input ="text "> однострочное окно редактирования, <input type="submit"> - кнопка, при щелчке на которой осуществляется пересылка данных серверному приложению, <textarea> - многострочное окно редактирования с полосами прокрутки, и многими другими. Вы можете посмотреть их в любом редакторе HTML, например, пробуя в редакторе FrontPage вводить компоненты с помощью команды Insert | Form Field.

Компоненты имеют ряд атрибутов. Атрибут type определяет тип компонента. Атрибут name определяет имя компонента. Атрибут value определяет значение данных компонента - текст в окне, надпись на кнопке и т.п. Серверному приложению посылаются строки вида «name=value», так что по имени name можно прочитать значение value. Как уже говорилось, в зависимости от метода Post или Get

эти строки лежат в свойстве ContentFields или Query Fields объекта Request. Например, выражения

Request->ContentFields->Values["result"] или

Request->QueryFields->Values["result"]

вернут значения атрибута result.

В однострочном окне редактирования имеется атрибут size, задающий размер окна - количество размещаемых в нем без прокрутки символов.

Чтобы упорядочить в форме размещение компонентов, их обычно размещают в ячейках таблицы. Таблица начинается тегом <table> и завершается тегом </table>. Между ними вставляются пары тегов <tr> и </tr>, определяющие очередную строку таблицы. А между этими тегами вставляются пары тегов <td> и </td>, определяющие очередную ячейку в строке. Между этими тегами размещается содержимое ячейки.

Поясним все это примером. Усовершенствуем и сделаем универсальным ранее созданное приложение для проверки знания клиентом таблицы умножения.

Серверное приложение должно заносить в документ HTML значения двух перемножаемых одноразрядных чисел. Для этого надо предусмотреть два окна редактирования,: num1 и num2. Ответ пользователь должен помещать в окно редактирования result. Кнопка Ответ - пересылает данные в серверное приложение mult.exe с PathInfo равным «/1». Кнопка Новые числа при нажатии вызывает приложение mult.exe.

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

<html>

<head>

<title>Taлица Умножения</title>

</head>

<body>

<h1>Проверьте свое знание таблицы умножения</h1

<р>3апишите в окне, чему равно произведение, и нажмите кнопку "Ответ"

</р>

<form method="POST"

action="http://mycomputer/cgi-bin/mult.exe/l">

<table>

<tr><td><input type="text" name="Num1" size="l"></td>

<td> x </td>

<td><input type="text" name="num2" size="l"></td>

<td> = </td>

<td><input type="text" name="result" size="3"> </td>

<td><input type="submit" name="post" vа1ue="Ответ"> </td>

</tr>

</table>

</form>

<form method="POST"

action="http://mycomputer/cgi-bin/mult.exe">

<p><input type="submit"  value="Hoые числа" name="New"></p>

</form>

</body>

</html>

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

Теперь построим серверное приложение, выполняющее проверку знания таблицы умножения. Проблема, возникающая в этом приложении, характерна для большинства задач обмена информацией между клиентом и сервером. Предположим, диалог с клиентом начинается с того, что приложение посылает ему два случайных числа, которые надо перемножить. После этого связь серверного приложения с клиентом прерывается. Когда клиент занесет в окно результат и нажмет кнопку Ответ, серверное приложение опять будет вызвано. Но для того, чтобы проверить ответ пользователя, надо знать, какие числа были заданы ему для перемножения. А приложение этого не знает, поскольку оно запускается на выполнение и никакие глобальные переменные не могут хранить данные, переданные при его прошлом запуске. Один из вариантов - хранить значения заданных чисел на внешнем носителе - в файле или базе данных. Другой вариант - читать их из документа, из которого вызывается приложение. Рассмотрим второй вариант. Именно для его реализации и предусмотрены окна num1 и mim2. В них передается информация при создании документа HTML и из них же читается информация при вызове приложения из этого документа.

Итак, чтобы построить подобное приложение, создайте новый модуль сервера и задайте в нем два действия. Первое действие со значением PathInfo = "/1" будет анализировать ответ клиента. Второе действие с пустым значением PathInfo и с Default = true будет создавать основной документ HTML. Его обработчик события OnAction может иметь следующий вид:

void _fastcall TWebModule1::WebModule1WebActionItem2Action (TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool sHandled)

{

randomize () ;

Word Num1 = random(8)+1;

Word Num2 = random (8)+1;

Response->Content = "<html><head><title>Taблицa умножения </title></head><body>"

"<h1>Проверьте  свое  знание  таблицы умножения</h1";

Response->Content =  Response->Content  +

"Запишите  в  окне, чему равно  произведение, и  нажмите кнопку \"Ответ\"";

Response->Content = Response->Content + "<form method=\"POST\" "

"action=\"http://mycomputer/cgi-bin/mult .exe/l\" " "<table><tr><td>

<input  type=\"text\" name=\"Num1\"" "size-\"l\" value-=\"" + IntToStr (Num1) + "\"></td><td>  x "

"<td><input  type=\"text\" name=\"nun\2\" size=\"l\"" "value-\"" + IntToStr(Num2) + "\"></td><td>  = " "<td><input type=\"text\" name=\"result\" size=\"3\"> " "</td>  <td><input type=\"submit\" name=\"post\" " "  value=\"Oтвет\">" "</td></tr></table></form><BR>" "<form method=\"POST\" "

"action=\"http://mycomputer/cgi-bin/mult. exe\">" "<p><input type=\"submit\" value=\"Hoвые числа\" " "name=\"New\"></p></form></body></html>" ;

Handled = true;

}

Первые операторы заносят с помощью функции random в локальные переменные Num1 и Num2 случайные целые числа, равномерно распределенные в интервале от 1 до 9. Предварительно функцией randomize производится рандомизация, чтобы при каждом запуске приложения генерировались новые числа. А после этого генерируется приведенный выше документ HTML. При этом в окна с именами Num1 и num2 в атрибут value заносятся в текстовом представлении значения чисел Num1 и Num2.

Обработчик события OnAction первого действия может иметь вид:

void _fastcall  TWebModule1::WebModule1WebActionItem1Action(TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled)

{

 if (Request->ContentFields->Values["result"] -=IntToStr(StrToInt(Request->ContentFields->Values["Num1"]) * StrToInt(Request->ContentFields->values["num2"])))

Response->Content  = "<b>Поздравляю1 ! ! </b><р>Вы  блестящий математик!";

else 

Response->Content  ="Вы  немного забыли таблицу  умножения<р>" "<а  HREF=\"http://mycomputer/cgi-bin/mult.exe\">" "<р>Попробуйте  еще  раз</а></р>";

 Handled =  true;

}

Условие в операторе if сравнивает ответ пользователя в окне result с произведением чисел, введенных в окнах Num1 и num2.

Сохраните приложение под именем Mult, скомпилируйте его и поместите выполняемый модуль в выполняемый каталог сервера.

 

5. Использование шаблонов HTML

 

Формировать сложные документы HTML в обработчике событий сервера OnAction неудобно. Выходом из положения является использование шаблонов HTML. Шаблонами называются специальные теги, которые приложение сервера заменяет на какие-то выражения HTML. Тег шаблона выглядит следующим образом:

<#TagName Param1=Value1 Param2=Value2 ...>

Шаблон помещается между символами угловых скобок. За открывающейся скобкой без пробела должен следовать символ "#", а за ним тоже без пробела - имя шаблона. По этому имени приложение может распознать шаблон. Есть некоторые общепринятые имена шаблонов. Например, имя Link применяется для задания ссылок, имя Image - для задания элементов графики и т.п.

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

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

Создайте новый модуль сервера и задайте в нем два действия. Первое действие со значением PathInfo = "/1" будет анализировать ответ клиента. Обработчик его события OnAction ничем не будет отличаться от приведенного выше. Только переменные Num1 и Num2 надо сделать глобальными, чтобы к ним можно было обращаться из нескольких функций.

Второе действие с пустым значением PathInfo и с Default = true будет создавать основной документ HTML. Перенесите компонент PageProducer в окно сервера WebModule1.

свойства компонента. Основные свойства PageProducer - HTMLDoc и HTMLFile. HTMLDoc типа TStrings - позволяет записать документ HTML, пользуясь обычным редактором строк, вызываемым нажатием клавиши с многоточием около этого свойства. Свойство HTMLFile - позволяет указать имя используемого файла документа .html или .htm. Для поиска этого файла можно воспользоваться диалогом открытия файла, вызываемым нажатием кнопки с многоточием. Таким образом, документ HTML с включенными  в него тегами шаблонов может включаться в выполняемый модуль (если заполнить свойство HTMLDoc) или быть отдельным файлом.

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

Хранение документа в отдельном файле имеет некоторые недостатки. Во первых, если серверное приложение передается каким-то пользователям, небходимо одновременно передавать и файлы документов. Кроме того, при смене адреса сервера могут потребоваться изменения ссылок на документы и перекомпиляция приложения. Всех этих трудностей не будет, если документ хранится в приложении, т.е. используется свойство HTMLDoc.

Единственное событие компонента PageProducer OnHTMLTag -  наступает, когда в тексте документа HTML встречается шаблон. Заголовок обработчика события OnHTMLTag имеет вид:

void _fastcall TWebModule1.PageProducer1HTMLTag(TObject *Sender, TTag Tag, const AnsiString TagString, TStrings TagParams, String ReplaceText)

Параметр Tag определяет тип шаблона, если имя шаблона - параметр TagString равно одному из общепринятых. При имени, отличном от общепринятых, тип равен tgCustom. Параметр TagParams определяет параметры шаблона, если они заданы. А в параметр ReplaceText обработчик должен занести текст, заменяющий шаблон. Если текст не будет занесен, шаблон заменится пустой строкой.

Соотношение возможных значений параметров определяется следующей таблицей:

 

Tag

TagString

TagParams

ReplaceText

tgLink

LINK

Ссылка

Последовательность команд HTML, начинающаяся с тега <А> и кончающаяся тегом </А>.

tglmage

IMAGE

Описание графического изображения

Тег <IMG>.

tgTable

TABLE

Описание элементов таблицы

Последовательность команд HTML, начинающаяся с тега <TABLE> и кончающаяся тегом </TABLE>.

tglmageMap

IMAGEMAP

Графическое изображение, связанное с «горячей» областью

Последовательность команд HTML, начинающаяся с тега <МАР> и кончающаяся тегом </МАР>.

tgObject

OBJECT

Ссылка на компонент ActiveX

Последовательность команд HTML, начинающаяся с тега <OBJECT> и  кончающаяся тегом </OBJECT>.

tgEmbed

EMBED

Ссылка на элемент стиля Netscape

Последовательность команд HTML, начинающаяся с тега <EMBED> и кончающаяся тегом </EMBED>.

tgCustom

Произвольное имя, отличное от указанных

Может быть пустым или определяться приложением

Произвольная последовательность

команд, определяемая приложением.

 

В большинстве случаев наиболее удобно произвольное имя шаблона, дешифруемое приложением. Впрочем, ничто не мешает использовать и общепринятые имена по своему усмотрению.

Привязка компонента PageProducer к тому или иному действию серверного приложения Web может осуществляться двумя путями. Можно в действии указать в свойстве Producer имя одного из включенных в модуль компонентов PageProducer. В этом случае текст документа HTML, поставляемый компонентом PageProducer, передается в свойство Response->Content обработчика события действия OnAction, после чего он может быть изменен в этом обработчике. А если ничего не надо изменять в этом документе, то вообще можно не писать обработчик события OnAction. Таким образом, подобное связывание действия и PageProducer позволяет не описывать в обработчике OnAction документ HTML, Это существенно облегчает написание обработчика.

Каждый компонент PageProducer в некоторый момент времени может быть привязан свойством Producer только к одному действию. Если окажется, что он привязан к нескольким действиям, то во всех, кроме первого, свойствам Producer будет принудительно присвоено значение nil.

Более интересный способ связи обработчика события действия OnAction с компонентом PageProducer является вызов из обработчика метода PagePro-ducer->Content. При вызове этого метода PageProducer начинает анализировать документ, генерирует события OnHTMLTag и в обработчиках этих событий может производить замены шаблонов с учетом каких-то установок, произведенных в обработчике OnAction.

Посмотрим, как это все можно использовать при воспроизведении примера серверного приложения. Выше уже говорилось, что в модуле сервера надо создать те же действия, что и ранее, и перенести в модуль компонент PageProducer. Текст основного документа HTML, который ранее генерировался в обработчике второго действия, может быть записан в отдельном файле или в свойстве HTMLDoc компонента PageProducer. В данном случае это текст может иметь следующий вид:

<html>

<head>

<tit1е>Таблица умножения</title>

</head>

<body>

<h1Проверьте свое знание  таблицы умножениж/h1>

<р>Запишите в окне, чему  равно произведение, и нажмите кнопку "Ответ"

</p>

<form method="POST"

action="http://mycomputer/cgi-bin/raultl.exe/1"

<table> <tr><td><input type="text" name="Num1" size="l"

value="<#TNum1>"></td> <td> x </td>

<td><input type="text" name="num2" size="l"

value="<#TNum2>"><x/td> <td><input type="text"  name="result"  size="3">  </td>

<td><input  type="submit"  name="post"  value="0твет"> 

</td> </tr>

</table>

</form>

<form  method="POST"

action="http://mycomputer/cgi-bin/multl. exe">

<p><input type=" submit" value=''Новые  числа" name="New"></p>

</form>

 </body>

 </html>

В тексте имя модуля в ссылках изменили с «mult.exe» на «multl.exe» и в описаниях компонентов num1 и num2 добавили атрибуты value со значениями, задаваемыми шаблонами <#TNum1> и <#TNum2>. Если текст создан в отдельном файле, то в свойстве HTMLFile компонента PageProducer должен быть указан этот файл.

При создании страницы в виде файла в C++Builder 6 можно воспользоваться вызовом редактора или браузера непосредственно из окна Редактора Кода.

Обработчик события OnAction первого действия остается без изменения. А обработчик события OnAction второго действия примет вид:

void _fastcall  TWebModule1::WebModule1WebActionItem2Action(TObject *Sender, TWebRequest *Request, TWebResponse *«Response, bool &Handled)

{

randomize();

Num1  =  random(8)+1;

Num2  =  random(8)+l;

Response->Content  = PageProducer1->Content();

}

В этом обработчике только задаются случайные значения перемножаемых чисел Num1 и Num2, а затем активизируется методом Content компонент PageProducer1 и результат работы этого компонента присваивается возвращаемому ответу Response->Content. Чтобы в обработчике события OnHTMLTag компонента PageProducer1 можно было получить доступ к заданным значениям Num1 и Num2, эти переменные сделаны глобальными, т.е. их объявление вынесено за пределы обработчика OnAction.

Обработчик события OnHTMLTag компонента PageProducer1 может иметь вид:

void _fastcall TWebModule1::PageProducer1HTMLTag(TObject *Sender, TTag Tag, const AnsiString TagString, TStrings *TagParams, AnsiString &ReplaceText)

{

 if (TagString  == "TNum1")

ReplaceText  = IntToStr(Num1);

else

if(TagString  == "TNum2")

ReplaceText = IntToStr (Num2);

}

В этом обработчике шаблоны, содержащиеся в приведенном ранее тексте HTML, заменяются значениями чисел Num1 и Num2.

Сохраните проект под именем Multl и исполняемый файл перенести в выполняемый каталог сервера.

 

6. Использование активных форм

 

Создание активной формы

Мощным способом включения приложений C++Builder в страницы Web является разработка их в виде активных форм или активных компонентов ActiveX. Это позволяет создавать сложные приложения и диалоги, с трудом реализуемые на языке HTML. Однако технология ActiveX применительно к приложениям Интернет имеет и ряд недостатков.

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

Рассмотрим на примере процесс создания активной формы и ее включение в страницу Web.

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

1.   Закройте все открытые проекты и выполните команду File | New | Other.

2.   В диалоговом окне New Items перейдите на страницу ActiveX  и выберите пиктограмму ActiveX Library (библиотека активных компонентов).

В результате в окно Редактора Кода загрузится модуль библиотеки ActiveX.

3. Выполните опять команду File | New | Other, перейдите на страницу ActiveX и выберите на ней пиктограмму Active Form (активная форма). Появится окно Active Form Wizard (мастер активных форм). В окошке VCL ClassName указан класс, на основе которого создается форма. В окошке New ActiveX Name нужно задать имя создаваемой формы (например, MyShop), а в окошке Implementation Unit нужно задать нмя программного модуля (например, UMyShop.cpp). Все остальное в этом окне можно оставить без изменения.

В результате в окне Редактора Кода появится довольно большой программный модуль.

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

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

Перенесите на форму компонент StringGrid, в котором будут отображаться данные об имеющихся товарах, метку Label, в которой будет формироваться сумма заказа, окно Edit для ввода адреса e-mail, окно Memo для ввода адреса, кнопку Button и две метки Label с поясняющими надписями.

В обработчик события формы OnCreate нужно ввести следующий код:

StringGrid1->RowCount =6;

StringGrid1->Cells[0] [0] ="Товар";

StringGrid1->Cells[1] [0] ="Цена";

StringGrid1->Cells[2] [0] ="Количество";

StringGrid1->Cells[3] [0] ="Стоимость";

StringGrid1->Cells[0] [1] ="Дверь деревянная";

StringGrid1->Cells[1] [1] =3500;

StringGrid1->Cells[2] [1] =0";

StringGrid1->Cells[0] [2] ="Телевизор Sony";

StringGrid1->Cells[1] [2] =18000;

StringGrid1->Cells[2] [2] =0;

StringGrid1->Cells[0] [3] ="Холодильник Sharp";

StringGrid1->Cells[1] [3] =7000;

StringGrid1->Cells[2] [3] =0;

StringGrid1->Cells[0] [4] ="Стиральная машина Bosh";

StringGrid1->Cells[1] [4] =17800;

StringGrid1->Cells[2] [4] =0;

StringGrid1->Cells[0] [5] ="Газовая плита Indisit";

StringGrid1->Cells[1] [5] =12300;

StringGrid1->Cells[2] [5] =0;

StringGrid1->Col =2;      // передача  фокуса  в  третий  столбец

В этом коде первый оператор задает число строк таблицы на 1 больше числа различных наименований товаров. Следующие четыре оператора задают надписи заголовка таблицы: «Товар», «Цена», «Количество», «Стоимость». Последующие операторы, которые, конечно, могут содержать любой текст, заполняют строки информацией о товарах и заносят нули в третий столбец, содержащий количество заказанного товара. Последний оператор устанавливает фокус в третьем столбце таблицы.

В компоненте StringGrid число строк задано программно (RowCount = 6). Число столбцов ColCount надо задать равным 4. Задайте число фиксированных столбцов FixedCols =0, а число фиксированных строк FixedRows = 1.

Теперь надо обеспечить расчет сумм заказа по каждому виду товара и по всему заказу в целом. Моментом для такого пересчета можно выбрать событие OnSelectCell компонента StringGrid, наступающее при изменении пользователем выделения в таблице. Значит, это событие наступит, когда пользователь введет количество приобретаемых товаров одного наименования и перейдет в строку какого-то другого товара.

Обработчик события OnSelectCell может иметь вид:

void _fastcall TMyShop::StringGrid1SelectCell(TObject *Sender, int ACol, int  ARow, bool sCanSelect)

{

CanSelect  = (ACol ==  2);

int summ  =0;

if (CanSelect)

{

for (int i= 1; i  <  StringGrid1->RowCount; i++)

{ // подсчет  сумм по  отдельным видам товара

StringGrid1->Cells[3][i] =IntToStr(atoi(StringGrid1->Cells[l][i].c_str()) * atoi (StringGrid1->Cells[2j [i] .c_str ()));

// накапливание суммы всего заказа

summ += atoi(StringGrid1->Cells[3][i].c_str());

}

 Labell->Caption  = "Сумма  заказа; " + IntToStr[summ) + "  руб."; )

}

Первый оператор этого обработчика запрещает выделение очередной ячейки, если это не ячейка третьего столбца. Для этого передаваемому в обработчик по ссылке параметру CanSelect (разрешение выделения) присваивается значение выражения (ACol == 2), где ACol - индекс выделяемого столбца. Поскольку индексы отсчитываются от нуля, то при ACol, равном 2 (третий столбец), значение параметра CanSelect делается равным true, а при любом другом значении ACol CanSelect равно false и выделения не происходит. Дальнейшие операторы заносят в цикле в четвертый столбец (его индекс 3) произведения чисел, лежащих во втором |и третьем столбцах каждой строки, и формируют в переменной summ сумму всего заказа. В результате формируется текст в надписи метки Label1.

Подсчет сумм целесообразно повторить в случае, если пользователь ввел очередное количество заказанного товара, нажал клавишу Enter и не переходит ни в какую ячейку таблицы. Для этого надо написать обработчик события OnKeyDown компонента StringGrid1:

void      _fastcall TMyShop::StringGrid1KeyDown(TObject *Sender,

WORD  SKey, TShiftState  Shift)

{if  (Key == VK__RETURN)

{

int summ  =0;

for (int i= 1; i <  StringGrid1->RowCount; i++)

{

StringGrid1->Cells[3][i] =IntToStr(atoi(StringGrid1->Cells[1j [i].c_str())  * atoi(StringGrid1->Cells[2] [i] .c_str ()));

summ  += atoi(StringGrid1->Cells[3j [i].c_str());

 }

Labell->Caption  = "Сумма заказа: " + IntToStr(summ) + " руб."; )

}

Наконец, при щелчке пользователя на кнопке Заказ нужно предусмотреть,  заполнил ли клиент поля адреса и e-mail, сообщить клиенту; номер его заказа, занести заказ в базу данных. В приложении м ограничимся только сообщением клиенту о принятом заказе:

void      _fastcall TMyShop::ButtonlClick(TObject *Sender)

{

Application->MessageBox("После  оплаты  заказа он  будет  Вам прислан  по  указанному  адресу", "Заказ принят",МВ_ОК);

}

Теперь активная форма спроектирована. Откомпилируйте форму командой Project | Build.

Развертывание и использование активной формы

Теперь надо произвести ее развертывание на сервере Web. Однако сначала надо установить параметры развертывания. Это выполняется командой Project | Web Deployment Options. Откроется окно.

В окошке Target dir надо указать каталог файла библиотеки ActiveX на сервере Web. В окошке Target URL указывается URL этого каталога. В окошко HTML dir занесите каталог, в котором будет размещаться документ HTML, ссылающийся на библиотеку ActiveX. Вы можете использовать этот документ как заготовку для вашей будущей страницы Web, которая будет включать активную форму. Установка индикатора Include file version number включит в ссылку на форму информацию о версии разработки, которая задается в процессе разработки командой Project | Options на странице VersionInfo.

Окно Web Deployment Options только устанавливает параметры развертывания. Само развертывание осуществляется командой Project|Web Deploy, в результате чего файлы разместятся на сервере Web в указанных папках.

В первый раз надо зарегистрировать активный сервер ActiveX в Windows с помощью команды Run|Register ActiveX Server. Теперь активную форму, можно просматривать браузерами. Если потребуется снять сервер ActiveX с регистрации в Windows, нужно выполнить команду Run|Unregister ActiveX Server.

Теперь посмотрите пробный документ HTML, созданный C++Builder во время развертывания. Этот документ имеет то же имя, что и проект, а его расширение .htm. Документ хранится в папке, указанной в окошке HTML dir диалогового окна Web Deployment Options. Можете открыть его непосредственно в среде C++Builder. Для этого примера документ имеет вид:

<HTML>

<Н1> Тестовая страница ActiveX C++Builder 6 </Н1><р>

Ниже вы должны увидеть форму или элемент, созданный вами в C++Builder 6

<HR><center><p>

<OBJECT

classid="clsid:lC17E3C9-8FDl-4AE0-8 971-2E393E99D326"

codebase="http://www.Myshop.com/PMyShop.ocx#version=l, 0,0, 0"

width=350

height=250

align=center

hspace=0

vspace=0 >

</OBJECT> </HTML>

Тег <Н1> определяет заголовок первого уровня, в котором записан текст: - «Тестовая страница ActiveX C++Builder 6». Далее в файле размещен текст: «Ниже вы должны увидеть форму или элемент, созданный вами в C++Builder 6». Далее в файле имеется тег <HR> - отчеркивание.

Затем в файле расположен сгенерированный C++Builder тег <OBJECT>. Он определяет объект, который должен быть внедрен в страницу HTML. Атрибуты width (ширина), height (высота), align (выравнивание), hspace (отступ по горизонтали) и vspace (отступ по вертикали) определяют размещение и размер компонента на форме. Атрибут classid определяет компонент, который должен быть внедрен. Если на машине клиента имеется компонент ActiveX, который соответствует указанному идентификатору класса, то он и будет внедрен в форму. Если такой компонент не зарегистрирован в системе, то он будет загружен в соответствии с указанным URL.

Учтите, что значения атрибутов, в частности, ширины и длины занесены в файл исходя из размеров формы. Если в дальнейшем необходимо изменить размер формы, надо соответственно изменить значения из атрибутов.

Включение в атрибут classid информации о версии происходит, если был включен индикатор Include file version number. Указание версии гарантирует, что клиент будет использовать версию, не младше указанной. Например, если клиент в настоящее время использует версию 1.1.0.0 или более раннюю, то браузер переустановит активную форму, заменив ее указанной версией. Если указать в файле значение версии «-1, -1, -1, -1», то форма будет всегда переустанавливаться.

Таким образом, C++Builder подготовил образец документа HTML, включающего активную форму. Остается отредактировать документ и он примет, например, следующий вид:

<HTML>

<Н1> Магазин MyShop </Н1>

В нашем магазине вы можете купить множество товаров.

Заполните в списке количество заказываемых вами товаров каждого

наименования, укажите свой адрес и e-mail и нажмите кнопку заказ.

<HR><center><P>

<OBJECT

classid="clsid: 39A30D25-B8B7-11D4-84B9-444553540000 version 1,2,0,0"

codebase="http://www.Myshop.com/PMyShop.ocx

height=310

align=center

hspace=0

vspace=0

> 

</OBJECT>

</HTML>

Далее можно просматривать его с помощью любого браузера.

Некоторые браузеры Web могут отказаться использовать активный компонент, если он не подписан электронной подписью. Чтобы разрешить использование не подписанных компонентов ActiveX, нужно изменить установки защиты браузера. В Microsoft Internet Explorer энужно установить параметр safety level (уровень безопасности) на значение medium (средний).

 

7. Обзор дополнительных возможностей работы с Интернет

 

Нами рассмотрены не все возможности создания в C++Builder приложений для Интернет. Дадим краткий обзор других возможностей работы с Интернет.

Обмен текстовыми сообщениями между компьютерами можно организовать с помощью компонентов NMMSGServ и NMMsg, расположенных на странице FastNet. Эти компоненты могут включаться в любое приложение C++Builder. Сообщения передаются компонентом NMMsg. Он имеет свойства Host и Port, определяющие адрес и порт сервера, которому отправляется сообщение. Как правило, порт, через который осуществляется обмен сообщениями, имеет номер 6711. Это значение присвоено свойству Port по умолчанию и может оставляться без изменения.

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

Компонент NMMSGServ обеспечивает получение сообщение в сервере. Свойства этого компонента подобны свойствам NMMsg. Отсутствует свойство FromName. Основное событие компонента - OnMSG, в обработчик которого передаются полученные тексты sFrom и NMMsg.

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

Компонент NMStrm помещается в клиентское приложение и по своим свойствам и событиям ничем не отличается от компонента NMMsg. Передачу этот компонент ведет в тот же порт 6711 тем же методом Portlt. Только вместо строки сообщения в этот метод передается поток - объект класса TStream или одного из его потомков.

Компонент NMStrmServ принимает в сервере переданный поток. Этот компонент аналогичен компоненту NMMSGServ по своим свойствам и событиям. Только обработчик события OnMSG принимает вместо текстового сообщения sMsg переданный поток.

Передача информации между клиентами и серверами Интернет можно также организовывать с помощью сокетов. Сокеты - это некие коммутаторы, обслуживающие соединения в сети. По своему назначению они разделяются на три типа: клиентские, слушающие и серверные. Клиентский сокет инициирует соединение, указывая имя или IP-адрес удаленного сервера и порт, используемый сервером. В сервере запрос клиента об установлении связи получает слушающий сокет. Его задача - сформировать очередь запросов. А серверный сокет, берет очередной запрос из очереди и устанавливает соединение с клиентским сокетом. В результате клиентский сокет получает описание серверного сокета, с которым он установил связь.

Функции клиентского сокета выполняет компонент ClientSocket со страницы Internet. Для соединения с сервером используется метод Open, для завершения соединения - метод Close. Метод SendText посылает серверу текстовое сообщение. Методы SendStream и SendStreamThenDrop передают поток, в который можно записать любую информацию, в том числе любые двоичные файлы. Для чтения сообщения предусмотрены методы ReceiveText - чтение строки, и ReceiveBuf - чтение двоичной информации.

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

На странице FostNet библиотеки имеется ряд компонентов, работающих с различными службами Интернет. Компоненты NMDayTime и NMTime позволяют приложению получить информацию о дате и точном времени от серверов даты и времени. Компонент NMFTP позволяет организовать общение с сервером по протоколу FTP.

Компоненты NMSMTP и NMPOP3 работают с протоколами SMTP и POP, используемыми соответственно для отправки и приема писем электронной почты.

На странице FastNet имеется также ряд компонентов, позволяющих решать чисто служебные задачи, связанные с Интернет. Компонент NMUUProcessor позволяет кодировать и декодировать файлы методами MIME/Base 64 и UUEn-coding/Decoding. Компонент NMURL декодирует строки в формате URL в обычные символьные строки и решает обратную задачу - кодирование символьных строк в строки формата URL, которые можно использовать в запросах HTTP.

Язык SQL (Structured Query Language - язык структурированных запросов) позволяет формировать запросы к базам данных. Запрос - это вопрос к базе данных, возвращающий запись или множество записей, удовлетворяющих вопросу.