|
Раздел "Кодинг". Содержание:
Статьи:
Разработка 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
mov eax, Flags
mov ecx, Message
mov edi, Caption
mov esi, Callback
mov edx, ReferenceData int 20H
dd 170004h
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);
|