Белорусская цифровая библиотека




AboutPC+
Реклама в журнале
 [скрыть меню]

Раздел "Кодинг". Содержание:

Статьи:

Вперед Разработка CGI приложений на Delphi
Вперед Пример создания DivX драйвера на Delphi
Вперед Создание Web-броузера на Delphi
Вперед Строковые типы в Delphi
Вперед Получение и установка текущей раскладки клавиатуры средствами Delphi

Раздел "Кодинг". Статьи:

В конец страницы

Разработка CGI приложений на Delphi

В последнее время в связи с растущей популярностью сети Интернет все чаше становится необходимость разработки приложений, которые бы могли работать непосредственно в www среде. Т.е. такие, которые бы полностью бы интегрировались в уже привычные нам веб-странички. По сути дела работа с таким приложением происходит полностью через любимый браузер пользователя и ничем не отличается от серфинга по страничкам. Ввод данных равно как и выдача обработанных результатов происходит через html-формы веб-страничек. Обработка же данных происходит на веб-сервере. Таким образом, мы получим самое что ни есть клиент-серверное приложение в его самом классическом понимании.

Необходимо отметить, что CGI-приложения разрабатываемые в средах разработки ориентированных на Win32 системы, в том числе и в Дельфи, а вернее серверная часть такого приложения может работать только под Win32 сервером, например IIS из NT или Personal Web Server из Windows98. Что касается клиентской части, то здесь никаких проблем совместимости не должно быть в принципе, т.к. клиентская часть представляет собой сгенерированный HTML код, который поддерживается любым браузером, не важно какую платформу использует пользователь, будь то Win32, OS/2, Unix и др.

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

Что касается веб-интерфейсов, то здесь желательно знать хотя бы основы языка HTML. Здесь мы не будем уделять этому особое внимание, хотя знание HTML для программиста CGI-приложений очень желательно. Сейчас же для нас будет вполне достаточным знание таких основопологающих тэгов как <HTML>,<BODY> и конструкции <FORM>.

Ну а теперь будем разбираться непосредственно с телом CGI-приложения. Во-первых, что такое CGI-приложение разрабатываемое в Win32 среде разработки? Это приложение типа Win32 CONSOLE, т.е. консольное приложение Win32. Только вот для такого приложения в отличии от классической Win32 консоли стандартным устройством ввода является либо поля ввода HTML формы либо строка адреса браузера, а в качестве стандартного устройства вывода используется окно браузера. Активизация приложения происходит непосредственно из какой-либо HTML странички, например так <A target="_blank" href="https://library.by/index.php?myhost/myapp.exe">My Application</A> Как мы уже выяснили такое CGI-приложение будет представлять собой исполняемую Win32 программу (exe), таким веб-приложениям принято давать расширение CGI, хотя это и непринципиально.

Для начала рассмотрим пример самой простой CGI-программки выдающей в окно пользовательского браузера текст "HELLO WORLD".

===cut===
program MyApp
{$APPTYPE CONSOLE}	// тип приложения Win32 консоль
{$E cgi}		// Расширение приложения cgi
begin
WriteLn('Content-Type: text/html');
WriteLn;
WriteLn;
WriteLn('<HTML>');
WriteLn('<HEAD>');
WriteLn('<TITLE>Простейшее CGI приложение</TITLE>');
WriteLn('<META http-equiv="Content-Type" content="text/html;' +
                          ' charset=windows-1251">');
WriteLn('</HEAD>');
WriteLn('<BODY>');
WrОтiteLn('<H1>HELLO WORLD</H1>');
WriteLn('</BODY>');
WriteLn('</HTML>');
end.
===cut===

Откомпиллируйте этот исходный код в среде Дельфи, поместите скомпонованный исполняемый код в ваш CGI-BIN каталог ( в каталог, где разрешено исполнение скриптов), напишите небольшую веб страничку для активизации нашего CGI-приложения, например, такую:

===cut==
<HTML>
<HEAD>
<TITLE>Форма для активизации CGI-приложения</TITLE>
</HEAD>
<BODY>
<A target="_blank" href="https://library.by/index.php?localhost/cgi-bin/myapp.cgi">
Нажми сюда для запуска приложения</A>
</BODY>
</HTML>
===cut==

Теперь откройте нашу веб-страничку и перейдите по ссылке "Нажми сюда для запуска приложения". Если вы все сделали правильно, то на экране в окне вашего любимого браузера появиться текст "HELLO WORLD".

Как видите все достаточно просто! Однако, для полноценной работы приложения, оно должно уметь не только выводить некие данные, но получать данные от пользователя, т.е. обеспечивать ввод информации. Ввод данных в случае CGI-приложения, как мы уже говорили, будет осуществляться по средствам интерфейса организованного веб-формой. Такая форма может передавать данные двумя способами, в зависимости от значения атрибута "METHOD".

В случае <FORM METHOD="GET" ...>... данные передаются через строку адреса браузера и записываются в переменную системного окружения QUERY_STRING, а размер строки данных в переменную CONTENT_LENGTH.

В случае <FORM METHOD="POST" ...>... передаваемые данные в строке адреса не отображаются, передаются через стандартный поток ввода консольной программы.

Таким образом задача получения данных CGI-приложением сводится к чтению определенной переменной окружения. Надо отметить, что передаваемые веб-формой данные имеют следующий формат: <имя_атрибута1>=<значение_атрибута1>&<имя_атрибута2>=<значение_атрибута2>...

Задача программиста сводится к извлечению значений нужных атрибутов из полученной от браузера строки и преобразования этих значений из вида URLencoded в обычные текстовые данные. Суть URLencoded формата заключается в том, что некоторые символы, содержащиеся в значении поля, заменяются на % и следующим за ним шестнадцатиричным кодом символа, а пробел заменяется на +.

А сейчас давайте рассмотрим пример CGI приложения, которое бы производило подобие некоторой идентификации пользователя системы.

===cut==
<!-- HTML форма ввода пароля -->
<HTML>
<HEAD>
<TITLE>Авторизация доступа</TITLE>
</HEAD>
<BODY>
<FORM method="POST" action="http://localhost/cgi-bin/chkpaswd.cgi">
  Введите пароль: 
  <input type="text" name="paswd" size=20>
  <input type="submit" value="Найти">
  <input type="reset" value="Очистить">
</FORM>
</BODY>
</HTML>
===cut==

Далее идет пример непосредственно CGI приложения. Следует отметить, что приведенный в этом примере способ получения данных от веб формы (непосредственное чтение устройства стандартного ввода STD_INPUT) является наиболее наглядным, но не самым удобным, в Дельфи предусмотренны более удобные механизмы, которых мы каснемся позже.

===cut==
{Файл проекта CGIApp2}
program CGIApp2;{$APPTYPE CONSOLE}uses 
  MainUn in 'MAinUn.pas';{$E cgi}begin
  Main;
end.program MainUn;
interface
uses
  SysUtils, Windows, Classes;implementation// Функция перевода шестнадцетиричного символа в число
function HexToInt(CH : char): integer;
begin
  Result:=0;
  case CH of
    '0'..'9': Result:=Ord(CH)-Ord('0');
    'A'..'F': Result:=Ord(CH)-Ord('A')+10;
    'a'..'f': Result:=Ord(CH)-Ord('a')+10;
  end;
end;// Преобразует символы, записанные в виде URLencoded
function Decode(Value: string): string;
var
  i, L: integer;
begin
  Result:='';
  L:=0;
  for i := 1 to Length(Value) do
  begin
    if(Value[i] <> '%') and (Value[i] <> '+') and (L<1) then
    begin
      Result := Result + Value[i];
    end
    else
    begin
      if(Value[i] = '+') then
        Result := Result + ' '
      else if(Value[i] = '%') then
      begin
        L := 2;
        if(i < Length(Value) - 1) then
        begin
          Result := Result + Chr(HexToInt(Value[i+1]) * 16 + 
					HexToInt(Value[i+2]));
        end;
      end
      else
        Dec(L);
    end;
  end;
end;// Фнкция возвращает значение атрибута заданного 
//в качестве параметра функции из строки данных 
//считанной из устройства стандартого ввода.function ParamByName(Name: string): string;
var
  SS, ST : string;
  K : integer;
begin  Result := '';
  SS := InParams;  while Length(SS) <> 0 do
   begin
    K := Pos('&',SS);
    if (K <> 0) then
    begin
      ST := Copy(SS,1,K-1);
      SS := Copy(SS,K+1,10000);
    end
     else
     begin
      ST :=SS;
      SS:='';
    end;
    K := Pos('=',ST);
    if(K <> 0) then
    begin
      if(Name = Copy(ST,1,K-1)) then
      begin
        Result := Decode(Copy(ST,K+1,6000));
      end;
    end;
  end;
end;procedure Main;
var
  STR : string;
  StdIn, Size, Actual : cardinal; 
  InParams : string;
const
  UserPassword : String = 'MyPass';
begin
  StdIn := GetStdHandle(STD_INPUT_HANDLE);
  Size := SetFilePointer(StdIn, 0, nil, FILE_END);
  SetFilePointer(StdIn, 0, nil, FILE_BEGIN);
  SetLength(STR,Size+1);
  if (Size <= 0) then
    Exit;
  // Читаем данные из стандартного устройства ввода
  ReadFile(StdIn, STR[1], Size, Actual, nil); 
  STR[Size+1] := #0;
  InParams := PChar(@STR[1]);
  
  APasswd := ParamByName('paswd');  WriteLn('Content-Type: text/html');
  WriteLn;
  WriteLn;
  WriteLn('<HTML>');
  WriteLn('<HEAD>');
  WriteLn('<TITLE>Идентификация пользователя</TITLE>');
  WriteLn('<META http-equiv="Content-Type" content="text/html;'+
					' charset=windows-1251">');
  WriteLn('</HEAD>');
  WriteLn('<BODY>');
  if APasswd = UserPassword then
    WriteLn('<H1>Успешная идентификация!</H1>')
  else
    WriteLn('<H1>Пароль введен неверно!</H1>')
  WriteLn('</BODY>');
  WriteLn('</HTML>');
  
end;
===cut==

Назад В начало страницы На главную страницу В конец страницы Вперед 

В конец страницы

Пример создания DivX драйвера на Delphi

Общая информация

Компиляция данного примера возможна только с Delphi 3. Delphi 2 не был опробован в связи с его отсутствием, объектные фалы созданные Delphi 4 отвергаются Microsoft® Linker 5.12.8181 как файлы неизвестного формата.

При написании данного материала были использованы Microsoft® Macro Assembler ver. 6.11d и Microsoft® Incremental Linker ver. 5.12.8181 из поставки.

Windows 98DDK

Введение

VxD драйвера делятся два типа:

  • Статические Загружаются в память при загрузке операционной системы и присутствуют в памяти постоянно
  • Динамические Загружаются в память при первом обращении к драйверу и могут быть выгружены при закрытии последнего дескриптора VxD.

Практически возможно создание драйвера поддерживающего оба типа загрузки.

Нам необходим динамически загружаемый VxD драйвер (далее "VxD") т.к. такой драйвер можно будет без перезагрузки Windows загружать из Win32® приложений используя процедуру CreateFile().

Когда Win32 приложение открывает дескриптор для VxD, виртуальное устройство VWIN32 используя сервис LoadDevice загружает VxD-драйвер в память и посылает информационное сообщение W32_DEVICEIOCONTROL загруженному VxD.

Таким образом для построения VxD необходимо обрабатывать как минимум три системных сообщения:

  • SYS_DYNAMIC_DEVICE_INIT
  • SYS_DYNAMIC_DEVICE_EXIT
  • W32_DEVICEIOCONTROL.

Собщение SYS_DYNAMIC_DEVICE_INIT посылается при попытке динамической загрузки VxD, SYS_DYNAMIC_DEVICE_EXIT посылается при попытке динамической выгрузке. Из обработчиков сообщений для подтверждения успеха необходимо вернуть VXD_SUCCESS в регистре AX

Сообщение W32_DEVICEIOCONTROL имеет следующие значения для параметра dwService.

  • DIOC_OPEN - посылается посылается при открытии дескриптора VxD функцией CreateFile() только после SYS_DYNAMIC_DEVICE_INIT. В случае успеха необходимо вернуть NO_ERROR (0);
  • DIOC_CLOSEHANDLE - посылается при закрытии дескриптора VxD функцией API CloseHandle() и только перед SYS_DYNAMIC_DEVICE_EXIT
  • (Значение > 0) - Номер функции, заданный в параметре dwIoControlCode при обращении к VxD функцией API DeviceIoControl

Загрузочный модуль (vxdmain.asm)

При обращении к процедурам находящимся в модулях Delphi надо учесть для fastcall-процедур к имени добавляется в начале символ "@"

...
extrn SysDynamicDeviceInit :PROC
extrn SysDynamicDeviceExit :PROC
extrn W32DeviceIoControl   :PROC
...
Control_0	proc
cmp	eax, SYS_DYNAMIC_DEVICE_INIT
jnz	short chkSysDynExit
call	SysDynamicDeviceInit
cmp	eax, 1
retn	
;-------------chkSysDynExit:
cmp	eax, SYS_DYNAMIC_DEVICE_EXIT
jnz	short chkDevIOCtl
call	SysDynamicDeviceExit
cmp	eax, 1
retn	
;-------------
chkDevIOCtl:
cmp	eax, W32_DEVICEIOCONTROL
jnz	short loc_ret
push	esi
push	edx
push	ebx
push	ecx
call	W32DeviceIoControl
cmp	eax, 1
retn	
;-------------
loc_ret:
clc	
retn	Control_0	endp
...

Delphi создает код для инициализации/деинициализации модулей, обращаясь к внешним процедурам HandleFinaly и initialization даже если блоки initilization и finalization в модуле отсутствуют. Создадим пустую "заглушку" для этих процедур и объявим их доступными для внешних модулей.

...
Public  @@HandleFinally
Public  @initialization
...
@@HandleFinally:
@initialization:
ret
...
end.

Процедурный модуль (vxdProcs.pas)

procedure ShellMessage(Handle, Flags : integer; const Message, Caption : PChar; 
Callback, ReferenceData : pointer); stdcall; assembler;
asm
mov	ebx, Handle		// virtual machine handle
mov	eax, Flags		// message box flags
mov	ecx, Message		// address of message text
mov	edi, Caption		// address of caption text
mov	esi, Callback		// address of callback
mov	edx, ReferenceData		// reference data for callback  int	20H			// VxDCall
dd 	170004h			// Shell_Message
end;const
Copyright : PChar = '(c) 1999 Emil Biserov, ' +
'fatty777@mail.ru, http://dinfo.da.ru';function SysDynamicDeviceInit : INTEGER;
begin
ShellMessage(0, $10, Copyright, 'SysDynInit: Hello from Delphi VxD !!!', nil, nil);
Result := VXD_SUCCESS;
end;function SysDynamicDeviceExit : INTEGER;
begin
ShellMessage(0, $10, Copyright, 'SysDynDevExit: Bye from Delphi VxD !!!', nil, nil);
Result := VXD_SUCCESS;
end;function W32DeviceIoControl(dwService : INTEGER;
      dwDDB : INTEGER;
      hDevice : INTEGER;
      lpDIOCParms : pointer) : INTEGER;
begin
ShellMessage(0, $10, Copyright, 'W32DevIOCtl', nil, nil);  if (dwService = DIOC_OPEN) then
begin
Result := NO_ERROR;
end
else if (dwService = DIOC_CLOSEHANDLE) then
begin
Result := VXD_SUCCESS;
end
else if (dwService > MAX_PASVXD_W32_API) then
begin
Result := ERROR_NOT_SUPPORTED;
end
else
begin
Result := VXD_SUCCESS; 
end;
end;

Инструмент для загрузки/выгрузки VxD

Представляет из себя простую форму с двумя кнопками. Приведу лишь методы для открытия и закрытия VxD драйвера.

const
VxDName = '\\.\DELPHIIO.VXD';...function TVxDTestForm.OpenVxDDriver: boolean;
begin
HVxDHandle := CreateFile(VxDName,0,0,nil,0,FILE_FLAG_DELETE_ON_CLOSE,0);
Result := HVxDHandle <> INVALID_HANDLE_VALUE;
end;procedure TVxDTestForm.CloseVxDDriver;
begin
if HVxDHandle <> INVALID_HANDLE_VALUE then begin
CloseHandle(HVxDHandle);
HVxDHandle := INVALID_HANDLE_VALUE;
end;
end;

Выгрузку неиспользуемого модуля можно производить автоматически, указав в параметрах CreateFile(,,,,,FILE_FLAG_DELETE_ON_CLOSE,). В данном случае система при каждом открытии дескриптора к VxD будет увеличивать внутренний счетчик использования на 1 и вычитать 1 при закрытии дескриптора. При значении счетчика равном нулю VxD будет автоматически выгружен.

Выводы

Драйвера на Delphi писать можно. Но вот только стоит ли?

Использование VxD имеет смысл только для использования Windows 3.1 и Windows 95. Да и доступ к аппаратным ресурсам в них гораздо прозрачнее чем Windows NT/2000/XP. Windows 98, NT 2000 и XP поддерживают новую модель драйверов WDM 1.0/2.0, использующую формат PE (Portable Executable) и (предположительно) проблем будет меньше, чем с VxD и его LE (Linear Executable) форматом драйверов.

Назад В начало страницы На главную страницу В конец страницы Вперед 

В конец страницы

Создание Web-броузера на Delphi

Читая и перечитывая вопросы и ответы, я все время натыкался на вопросы о компоненте TWebBrowser. Сначала я думал, что все просто, но когда самому понадобилось написать приложение с использованием TwebBrowser… оказалось, что не все так просто!

Эта статья не претендует на исчерпывающие руководство по написанию браузера в Delphi 5 - скорее всего она будет со временем дополняться и исправляться. Я постарался обобщить в одном работающем примере решения большинства вопросов, заданных на этом сайте (признаюсь, там были и мои). Также выражаю большую признательность Елене Филлиповой за исчерпывающие ответы на некоторые из них, и всему Королевству за столь хороший и полезный сайт.

Компонент TWebBrowser в Delphi 4 нужно было специально инсталлировать как Active X компонент. В 5-й версии нам пошли навстречу, и он сразу есть на вкладке Internet. Не буду останавливаться на особенностях интерфейса программы - он очень прост (надеюсь, не очень) и не вызовет трудностей. Пример сдесь.

Рассмотрим некоторые свойства и функции TwebBrowser.

procedure GoBack;

procedure GoForward;

procedure GoHome;

procedure GoSearch;

procedure Refresh;

procedure Stop;

procedure Quit;

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

Последняя команда самая интересная - в Help написано, что использовать ее не надо. Она завершает работу IE и очищает окно. Но я проверял - вроде вреда от ее использования не наблюдалось.

Далее идет целая группа процедур:

procedure Navigate(const URL: WideString); overload;

procedure Navigate(const URL: WideString; var Flags: OleVariant); overload;

procedure Navigate(const URL: WideString; var Flags: OleVariant; var

TargetFrameName: OleVariant); overload;

procedure Navigate(const URL: WideString; var Flags: OleVariant;

var TargetFrameName: OleVariant; var PostData: OleVariant); overload;

procedure Navigate(const URL: WideString; var Flags: OleVariant;

var TargetFrameName: OleVariant; var PostData: OleVariant;

var Headers: OleVariant); overload;

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

procedure Navigate(const URL: WideString);

Например так:

WebBrowser1.Navigate(' http://delphi.vitpc.com/');

Или

WebBrowser1.Navigate(' http://delphi.vitpc.com/',empty,empty,empty,empty)

Для значения Flag определены такие константы:

navOpenInNewWindow 1 Открывает URL в новом окне браузера

navNoHistory 2 Не заносит адрес в список History.

navNoReadFromCache 4 Не использует сохраненную в кеше страницу, а загружает с сервера.

navNoWriteToCache 8 Не записывает страницу в дисковый кеш.

navAllowAutosearch 16 Если броузер не может найти указанный домен, он передает его в поисковый механизм.

Все, это можно также вручную установить в настройках браузера.

TargetFrameName указывает имя фрейма, куда надо загрузить страницу. Если присвоить NULL страница просто загрузиться в текущее окно.

PostData - указывает на данные, которые нужно отослать, используя метод HTTP POST. Если установить в NULL, процедура Navigate будет использовать метод HTTP GET.

Следующая довольно интересная и полезная процедура

procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT); overload;

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

CmdID - задает команду, которую нужно выполнить. Может принимать следующие значения:

OLECMDID_OPEN, OLECMDID_NEW, OLECMDID_SAVE, OLECMDID_SAVEAS, OLECMDID_SAVECOPYAS, OLECMDID_PRINT, OLECMDID_PRINTPREVIEW, OLECMDID_PAGESETUP, OLECMDID_SPELL, OLECMDID_PROPERTIES, OLECMDID_CUT, OLECMDID_COPY, OLECMDID_PASTE, OLECMDID_PASTESPECIAL, OLECMDID_UNDO, OLECMDID_REDO, OLECMDID_SELECTALL, OLECMDID_CLEARSELECTION, OLECMDID_ZOOM, OLECMDID_GETZOOMRANGE, OLECMDID_UPDATECOMMANDS, OLECMDID_REFRESH, OLECMDID_STOP, OLECMDID_HIDETOOLBARS, OLECMDID_SETPROGRESSMAX , OLECMDID_SETPROGRESSPOS, OLECMDID_SETPROGRESSTEXT, OLECMDID_SETTITLE, OLECMDID_SETDOWNLOADSTATE, OLECMDID_STOPDOWNLOAD, OLECMDID_FIND, OLECMDID_ONTOOLBARACTIVATED, OLECMDID_DELETE, OLECMDID_HTTPEQUIV, OLECMDID_ENABLE_INTERACTION, OLECMDID_HTTPEQUIV_DONE, OLECMDID_ONUNLOAD, OLECMDID_PROPERTYBAG2, OLECMDID_PREREFRESH

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

Cmdexecopt - указывает дополнительно, как команда должна исполняться. Может принимать значения:

OLECMDEXECOPT_DODEFAULT 0 Команда исполняеться так, как принято по умолчанию.

OLECMDEXECOPT_PROMPTUSER 1 Перед выполнением выводиться окно диалога или дополнительных настроек.

OLECMDEXECOPT_DONTPROMPTUSER 2 Не задается никаких вопросов.

OLECMDEXECOPT_SHOWHELP 3 Выводиться справка по запрошеному действии, но сама команда не выполняеться. Удобно для вызова из вашего приложения справки по IE.

Вызивать эту комманду желательно и даже нужно в блоке

try

WebBrowser1.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER);

except

end;

Эта команда вызивает диалоговое окно печати документа. Если же опустить try…except, то при нажатии "Отмена" в этом окне будет сгенерировано уведомление об ошибке типа:

raised exception class EOleException with message "Невозможно установить свойство coISpan. Недопустимое значения свойства. Требуется ввести значение от 1 до 1000".

Теперь поговорим о свойствах.

PopupMenu; Как оконный элемент управления, TwebBrowser поддерживает всплывающие меню. НО! Ваше меню будет появляться только пока в браузер не загружена страница. Дальше - только меню IE.

В Конференции предложили такой вариант для запрета появления стандартного меню:

…
private
{ Private declarations }
procedure WMMouseActivate(var Msg: TMessage); message
WM_MOUSEACTIVATE;
public
{ Public declarations }
end;
…
…
procedure TForm1.WMMouseActivate(var Msg: TMessage);
begin
try
inherited;
//правая кнопка мышки ?
if Msg.LParamHi = 516 then
 Msg.Result:= MA_NOACTIVATEANDEAT;// Тут  можно  вставить  код  для показания своего меню   except
end;
end;

property OffLine : WordBool; Позволяет загружать документы из локального кеша - если присвоить True.

property LocationURL: WideString; Позначено как "только для чтения" и содержит URL ресурса, загруженого в браузер.

Теперь события.

Среди самых важных/нужных есть:

OnDownloadBegin

OnDownloadComplete

OnBeforeNavigate2

OnNewWindow2

OnNavigateComplete2

OnDocumentComplete

OnDownloadBegin - происходит, когда вы, набрав URL, хотите перейти по нему. Тут можно задать например анимацию или ProgressBar для индикации процесса загрузки страницы (совмесно с OnProgressChange).

OnDownloadComplete, OnDownloadComplete, OnNavigateComplete2 - происходит, когда страница закончила грузиться.

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

OnBeforeNavigate2 - происходит когда вы переходите по щелчку на гиперссылке из основной страницы, загруженной в браузер. Сюда можно писать код, который например, анализирует - куда пользователь переходит, и соответственно, что-то делать. Или запретить открывание новых окно, или открывать свои окна (типа сделатьTtabbedNotebook c IE на каждой странице)

OnNewWindow2 - происходит, когда открывается новое окно браузера.

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

Назад В начало страницы На главную страницу В конец страницы Вперед 

В конец страницы

Строковые типы в Delphi

В выражениях Delphi поддерживает три физических строковых формата: короткий (ShortString), длинный (LongString) и широкий (WideString). Их можно комбинировать в операторах присваивания и выражениях (все необходимые преобразования Delphi выполняет автоматически).

Переменные типов AnsiString и WideString — это динамически распределяемые массивы символов, максимальная длина которых ограничивается только наличием памяти. Разница между ними состоит в том, что в AnsiString знаки записываются в формате char, а в WideString— в формате WideChar. Обычно вполне достаточно одного типа AnsiString, однако при работе с международными наборами символов, такими как UNICODE, удобнее использовать WideString.

Тип ShortString—это, по существу, массив Array [0..255] of char.
Первый его элемент задает динамическую длину строки, которая может принимать значения от 0 до 255 символов. Символы, составляющие строку, занимают места от 1 до 255. Тип ShortString предназначен, в основном, для обеспечения совместимости с ранними версиями Delphi и Borland Pascal.

Логический строковый тип именуется просто String. Отнесение его к типу AnsiString или ShortString задается командой $Н. По умолчанию задается { $Н+}, и String совпадает с AnsiString. Если задать команду {$Н- }, то String будет совпадать с ShortString и иметь максимальную длину, равную 255 символам.

Для совместимости с другими языками программирования в Delphi поддерживается класс строк с конечным нулем. Зарезервированных слов или идентификаторов для этого класса не существует.

Строки с конечным нулем состоят из ненулевых символов и оканчиваются символом с порядковым номером 0 (#0). В отличие от типов AnsiString, ShortString и WideString, строки с нулевым окончанием не имеют указателя длины. Конец в этих стооках обозначается нулем.

Физически строки с нуль-окончанием подобны массивам символов с нумерацией элементов от нуля, наподобие array [ 0 . . X] of char, где Х — некоторое положительное целое, большее нуля, хотя никаких объявлении подобного рода не происходит. Вместо этого определяется переменная-указатель PChar и распределяется необходимый объем памяти. При необходимости строке AnsiString можно присвоить тип PChar.

В табл. 1 перечислены некоторые процедуры и функции обработки данных строковых типов.

Совет: Программисты, работающие на С, привыкли записывать все строки в массивы с нуль-окончанием. Фактически они применяют в выражениях не строковые переменные, а указатели на них. Программисты, работающие на Basic, привыкли использовать строку как одно целое. Для типа AnsiString из Delphi годятся оба подхода.

Таблица 1 - Строковые функции

ФункцияОписание
Concat(sl, s2, s3)Возвращает последовательное соединение строк. Эквивалентна оператору sl+s2+s3
Copy(s, pos, len)Возвращает подстроку длиной максимум len символов, начинающуюся в позиции pos строки s
Delete(s, pos, len)Удаляет максимум len символов из строки s, начиная с позиции pos
Insert(sourse, tar-get, pos)Вставляет строку source в строковую переменную target, начиная с позиции pos
Length (s)Возвращает динамическую длину строки. Подобна функциям LEN в Basic и strlen — в C/C++
Pos(substring, s)Возвращает место первого вхождения подстроки substring в строку s. Подобна функциям SUBSTR в Basic и strstr () — в C/C++
SetLength(s, newlen)Задает новую динамическую длину newlen строковой переменной s
SetStringЗадает содержимое и длину строки
Str(x, s)Преобразует численное значение х в строковую переменную s
StringOfCharsВозвращает строку с конкретным числом символов
UniqueStringДелает данную строку уникальной со счетом обращений 1
Val (s, v, code)Преобразует строку s в соответствующее численное представление v

Назад В начало страницы На главную страницу В конец страницы Вперед 

В конец страницы

Получение и установка текущей раскладки клавиатуры средствами Delphi

Ниже представлены 5 функций для получения/установки раскладки клавиатуры в своем или активном в текущий момент времени приложении:

  • function NameKeyboardLayout(layout : LongWord) : string; - Получает название раскладки из списка (для удобства сделал :)))
  • function GetActiveKbdLayout : LongWord; - Получает раскладку в своей программе
  • function GetActiveKbdLayoutWnd : LongWord; - Получает раскладку в активном окне
  • procedure SetKbdLayout(kbLayout : LongWord); - Устанавливает раскладку в своей программе
  • procedure SetLayoutActiveWnd(kbLayout : LongWord); - Устанавливает раскладку в активном окне

Исходный текст

{ **** UBPFD *********** by delphibase.endimus.ru ****
Зависимости: Windows, Messages
Автор:       savva, savva@nm.ru, ICQ:126578975, Орел
Copyright:   Сапронов Алексей (Savva)
Дата:        27 июня 2004 г.
**************************************************** }{типы описываем }
const
  CNT_LAYOUT = 2; // количество известных раскладок
  ENGLISH = $409;
  RUSSIAN = $419;  TKbdValue : array [1..CNT_LAYOUT] of LongWord =
                ( ENGLISH,
                  RUSSIAN
                );
  TKbdDisplayNames : array [1..CNT_LAYOUT] of string =
                ('English',
                 'Русский'
                );
{----- собственно сами процедури и функции -----}
  
{получаем название раскладки}
function NameKeyboardLayout(layout : LongWord) : string;
var
  i: integer;
begin
  Result:='';
  try
    for i:=1 to CNT_LAYOUT do
      if TKbdValue[i]=layout then Result:= TKbdDisplayNames[i];
  except
    Result:='';
  end;
end;
//**************** end of NameKeyboardLayot ***************************
{активная раскладка в своей программе}
function GetActiveKbdLayout : LongWord;
begin
  result:= GetKeyboardLayout(0) shr $10;
end;
//***************** end of GetActiveKbdLayot ****************************
{активная раскладка в активном окне}
function GetActiveKbdLayoutWnd : LongWord;
var
  hWindow,idProcess : THandle;
begin
  // получить handle активного окна чужой программы
  hWindow := GetForegroundWindow;
  // Получить идентификатор чужого процесса
  idProcess := GetWindowThreadProcessId(hWindow,nil);
  // Получить текущую раскладку в чужой программе
  Result:=(GetKeyboardLayout(idProcess) shr $10);
end;
//***************** end of GetActiveKbdLayotWnd **************************
{установить раскладку в своей программе}
procedure SetKbdLayout(kbLayout : LongWord);
var
  Layout: HKL;
begin
  // Получить ссылку на раскладку
  Layout:=LoadKeyboardLayout(PChar(IntToStr(kbLayout)), 0);
  // Переключить раскладку на русскую
  ActivateKeyboardLayout(Layout,KLF_ACTIVATE);
end;
//****************** end of SetKbdLayot **********************************
{установить раскладку в активном окне}
procedure SetLayoutActiveWnd(kbLayout : LongWord);
var 
  Layout: HKL;
  hWindow{, idProcess} : THandle; // ION T: не используется
begin
  // получить handle активного окна чужой программы
  hWindow := GetForegroundWindow;
  // Получить ссылку на раскладку
  Layout:=LoadKeyboardLayout(PChar(IntToStr(kbLayout)), 0);
  // посылаем сообщение о смене раскладки
  sendMessage(hWindow,WM_INPUTLANGCHANGEREQUEST,1,Layout);
end;
//***************** end of SetLayoutActiveWnd *****************************

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

...
  {активная раскладка в активном окне}
    Label1.Caption:= NameKeyboardLayout(GetActiveKbdLayoutWnd);
  {активная раскладка в своей программе}
    Label2.Caption:= NameKeyboardLayout(GetActiveKbdLayout);
  {установить раскладку в своей программе}
    SetKbdLayout(ENGLISH);
  {установить раскладку в активном окне}
    SetLayoutActiveWnd(ENGLISH);

Назад В начало страницы На главную страницу В конец страницы Вперед 

 
design: ФуксЪ, Solmex 
Реклама в журнале


@ library.by