FAQ по использованию компонента TWebBrowser
Перевод материала с сайта members.home.com/hfournier/webbrowser.htm
Вопрос: Что такое Веббраузер?
Ответ: Веббраузер это Microsoft's Internet Explorer в виде
ActiveX контрола. Его можно импортировать в Delphi IDE и
размещать на форме на равне с другими
компонентами. Поэтому, чтобы превратить Ваше
приложение в браузер, достаточно
воспользоваться всей мощью IE.
Вопрос: Где можно найти документацию на
WebBrowser?
Ответ: Можно заглянуть на сайт Microsoft в раздел
WebBrowser overview, а так же
на страницу WebBrowser object.
Вопрос: Как использовать компонент WebBrowser в
своём Delphi приложение?
Ответ: Для этого необходимо, чтобы у Вас был
установлен Internet Explorer. В меню в Delphi IDE, выберите
"Component - Import ActiveX Control". Далее выберите
"Microsoft Internet Controls" и добавьте его как новый
исполняемы пакет. Delphi сгенерирует файл ShDocVw_TLB.pas и
добавит компонент WebBrowser в закладку компонентов
ActiveX.
Вопрос: Я вижу 2 компонента в
закладке компонетов ActiveX, WebBrowser и WebBrowser_V1. Какой
из них нужно использовать?
Ответ: Если у Вас 2 компонента, то в системе
установлен IE 4.x или выше. Соответственно WebBrowser
это IE 4.x а WebBrowser_V1 это IE 3.x. Если Вы видете только
один компонент, то будет использоваться WebBrowser
для IE 3.x.
Вопрос: Как определить, какая версия IE
установлена на компьютере?
Ответ: Можно почитать на Microsoft site.
Вопрос: Как производить Печать?
Ответ: Есть два способа вывода на печать. Первый
пример работает в IE 4.x и выше, в то время как
второй пример расчитан на IE 3.x:
var
vaIn, vaOut: OleVariant;
...
WebBrowser.ControlInterface.ExecWB(OLECMDID_PRINT,
OLECMDEXECOPT_DONTPROMPTUSER, vaIn, vaOut);
либо
procedure TForm1.PrintIE;
var
CmdTarget : IOleCommandTarget;
vaIn, vaOut: OleVariant;
begin
if WebBrowser1.Document <> nil then
try
WebBrowser1.Document.QueryInterface(IOleCommandTarget, CmdTarget);
if CmdTarget <> nil then
try
CmdTarget.Exec( PGuid(nil), OLECMDID_PRINT,
OLECMDEXECOPT_DONTPROMPTUSER, vaIn, vaOut);
finally
CmdTarget._Release;
end;
except
// Ничего
end;
end;
Обратите внимание: Если версия Delphi ниже чем 3.02,
то необходимо заменить
PGuid(nil)
на
PGuid(nil)^
. А лучше всего проапгрейдить до 3.02 (если Вы
пользуетесь версиями 3.0 или 3.01).
Вопрос: Как вызвать команды Find, Option или View
Source?
Ответ: Вот пример вызова диалога Find:
const
HTMLID_FIND = 1;
HTMLID_VIEWSOURCE = 2;
HTMLID_OPTIONS = 3;
...
procedure TForm1.FindIE;
const
CGID_WebBrowser: TGUID = '{ED016940-BD5B-11cf-BA4E-00C04FD70816}';
var
CmdTarget : IOleCommandTarget;
vaIn, vaOut: OleVariant;
PtrGUID: PGUID;
begin
New(PtrGUID);
PtrGUID^ := CGID_WebBrowser;
if WebBrowser1.Document <> nil then
try
WebBrowser1.Document.QueryInterface(IOleCommandTarget, CmdTarget);
if CmdTarget <> nil then
try
CmdTarget.Exec( PtrGUID, HTMLID_FIND, 0, vaIn, vaOut);
finally
CmdTarget._Release;
end;
except
// Ничего
end;
Dispose(PtrGUID);
end;
Вопрос: Как запретить всплывающее меню при
нажатии правой книпки мыши?
Ответ: Вам необходимо включить интерфейс
IDocHostUIHandler. Для этого Вам понадобятся два файла: ieConst.pas и IEDocHostUIHandler.pas.
В методе ShowContextMenu интерфейса IDocHostUIHandler,
необходимо изменить возвращаемое значение с
E_NOTIMPL на S_OK. После этого меню перестанет
реагировать на правое нажатие кнопки мыши.
Добавьте два модуля, упомянутые выше в секцию Uses
и добавьте следующий код:
...
var
Form1: TForm1;
FDocHostUIHandler: TDocHostUIHandler;
...
implementation
...
procedure TForm1.FormCreate(Sender: TObject);
begin
FDocHostUIHandler := TDocHostUIHandler.Create;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FDocHostUIHandler.Free;
end;
procedure TForm1.WebBrowser1NavigateComplete2(Sender: TObject;
pDisp: IDispatch; var URL: OleVariant);
var
hr: HResult;
CustDoc: ICustomDoc;
begin
hr := WebBrowser1.Document.QueryInterface(ICustomDoc, CustDoc);
if hr = S_OK then
CustDoc.SetUIHandler(FDocHostUIHandler);
end;
Вопрос: Как загрузить строковые данные в
WebBrowser не прибегая к открытию файла?
Ответ: Загрузите строку массив Variant, а затем
запишите в документ (Document):
...
var
v: Variant;
HTMLDocument: IHTMLDocument2;
begin
HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
v := VarArrayCreate([0, 0], varVariant);
v[0] := HTMLString; // Это Ваша HTML строка
HTMLDocument.Write(PSafeArray(TVarData(v).VArray));
HTMLDocument.Close;
...
end;
...
Автор: Ron Loewy
Вопрос: Как загрузить потоковые(stream) данные
в WebBrowser не прибегая к открытию файла?
Ответ: Вот пример кода:
function TForm1.LoadFromStream(const AStream: TStream): HRESULT;
begin
AStream.seek(0, 0);
Result := (WebBrowser1.Document as
IPersistStreamInit).Load(TStreamAdapter.Create(AStream));
end;
Автор: Per Larsen
Вопрос: Как использовать протокол
"about:"?
Ответ: Протокол "about:" позволяет Вам
просмотреть HTML строку:
procedure TForm1.LoadHTMLString(sHTML: String);
var
Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
WebBrowser1.Navigate('about:' + sHTML, Flags, TargetFrameName, PostData, Headers)
end;
Вопрос: Как можно использовать протокол
"res:"?
Ответ: Протокол "res:" позволяет просмотреть
HTML файл, сохранённый как ресурс. Более подробная
информация доступна на Microsoft site:
procedure TForm1.LoadHTMLResource;
var
Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
WebBrowser1.Navigate('res://' + Application.ExeName + '/myhtml',
Flags, TargetFrameName, PostData, Headers)
end;
Создайте файл ресурса (*.rc) со следующими
строками и откомпилируйте его при помощи brcc32.exe:
MYHTML 23 ".\html\myhtml.htm"
MOREHTML 23 ".\html\morehtml.htm"
Отредактируйте файл проекта, чтобы он выглядел
примерно так:
{$R *.RES}
{$R HTML.RES} //где html.rc будет скомпилирован в html.res
Вопрос: Как получить полный исходник HTML?
Ответ: В IE5, можно получить исходник используя
свойство outerHTML тэгов HTML. В IE4 или IE3, Вам
понадобится записать документ в файл, а затем
загрузить файл в TMemo, TStrings, и т.д.
var
HTMLDocument: IHTMLDocument2;
PersistFile: IPersistFile;
begin
...
HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
PersistFile := HTMLDocument as IPersistFile;
PersistFile.Save(StringToOleStr('test.htm'), True);
while HTMLDocument.readyState <> 'complete' do
Application.ProcessMessages;
...
end;
Автор: Ron Loewy
Обратите внимание: Вам понадобится
импортировать библиотеку MSHTML и добавить MSHTML_TLB
как ActiveX, в секцию Uses.
Вопрос: Как получить POST данные?
Ответ: Если данные передаются в формате
'animal=cat&color=brown' и т.д., то попробуйте использовать
следующий код:
procedure TDBModule.Navigate(stURL, stPostData: String; var wbWebBrowser: TWebBrowser);
var
vWebAddr, vPostData, vFlags, vFrame, vHeaders: OleVariant;
iLoop: Integer;
begin
{Are we posting data to this Url?}
if Length(stPostData)> 0 then
begin
{Require this header information if there is stPostData.}
vHeaders:= 'Content-Type: application/x-www-form-urlencoded'+ #10#13#0;
{Set the variant type for the vPostData.}
vPostData:= VarArrayCreate([0, Length(stPostData)], varByte);
for iLoop := 0 to Length(stPostData)- 1 do // Iterate
begin
vPostData[iLoop]:= Ord(stPostData[iLoop+ 1]);
end; // for
{Final terminating Character.}
vPostData[Length(stPostData)]:= 0;
{Set the type of Variant, cast}
TVarData(vPostData).vType:= varArray;
end;
{And the other stuff.}
vWebAddr:= stURL;
{Make the call Rex.}
wbWebBrowser.Navigate2(vWebAddr, vFlags, vFrame, vPostData, vHeaders);
end; {End of Navigate procedure.}
Автор: Craig Foley
Ответ: А это другой способ:
procedure TForm1.SubmitPostForm;
var
strPostData: string;
Data: Pointer;
URL, Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
{
<!-- submit this html form: -->
<form method="post" action="http://127.0.0.1/cgi-bin/register.pl">
<input type="text" name="FIRSTNAME" value="Hans">
<input type="text" name="LASTNAME" value="Gulo">
<input type="text" name="NOTE" value="thats it">
<input type="submit">
</form>
}
strPostData := 'FIRSTNAME=Hans&LASTNAME=Gulo&NOTE=thats+it';
PostData := VarArrayCreate([0, Length(strPostData) - 1], varByte);
Data := VarArrayLock(PostData);
try
Move(strPostData[1], Data^, Length(strPostData));
finally
VarArrayUnlock(PostData);
end;
URL := 'http://127.0.0.1/cgi-bin/register.pl';
Flags := EmptyParam;
TargetFrameName := EmptyParam;
Headers := EmptyParam; // TWebBrowser автоматически заполнять
// эти заголовки соответствующими значениями
WebBrowser1.Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
end;
Автор: Hans Gulo.
Вопрос: Как сделать WebBrowser плоским вместо 3D?
Ответ: Следующий пример устанавливает borderStyle:
procedure TForm1.WBDocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
Doc : IHTMLDocument2;
Element : IHTMLElement;
begin
Doc := IHTMLDocument2(TWebBrowser(Sender).Document);
if Doc = nil then
Exit;
Element := Doc.body;
if Element = nil then
Exit;
case Make_Flat of
TRUE : Element.style.borderStyle := 'none';
FALSE : Element.style.borderStyle := '';
end;
end;
Автор: Donovan J. Edye
Вопрос: Как сохранить веб страничку в bitmap?
Ответ: Вот пример:
procedure TForm1.Button1Click(Sender: TObject);
var
ViewObject: IViewObject;
sourceDrawRect: TRect;
begin
if EmbeddedWB1.Document <> nil then
try
EmbeddedWB1.Document.QueryInterface(IViewObject, ViewObject);
if ViewObject <> nil then
try
sourceDrawRect := Rect(0, 0, Image1.Width, Image1.Height);
ViewObject.Draw(DVASPECT_CONTENT, 1, nil, nil, Self.Handle,
image1.Canvas.Handle, @sourceDrawRect, nil, nil, 0);
finally
ViewObject._Release;
end;
except
end;
end;
Автор: John
Ответ: А следующий пример позволяет сохранить
её как JPEG:
procedure generateJPEGfromBrowser(browser: iWebBrowser2; jpegFQFilename: String;
srcHeight: Integer; srcWidth: Integer; tarHeight: Integer; tarWidth: Integer);
var
sourceDrawRect : TRect;
targetDrawRect: TRect;
sourceBitmap: TBitmap;
targetBitmap: TBitmap;
jpeg: TJPEGImage;
viewObject: IViewObject;
begin
sourceBitmap := TBitmap.Create ;
targetBitmap := TBitmap.Create ;
jpeg := TJPEGImage.Create ;
try
try
sourceDrawRect := Rect(0,0, srcWidth , srcHeight );
sourceBitmap.Width := srcWidth ;
sourceBitmap.Height := srcHeight ;
viewObject := browser as IViewObject;
if viewObject = nil then
Exit;
OleCheck(viewObject.Draw(DVASPECT_CONTENT, 1, nil, nil, self.Handle,
sourceBitmap.Canvas.Handle, @sourceDrawRect, nil, nil, 0));
// Изменяем размер исходного битмапа для конечного битмапа
targetDrawRect := Rect(0,0, tarWidth, tarHeight);
targetBitmap.Height := tarHeight;
targetBitmap.Width := tarWidth;
targetBitmap.Canvas.StretchDraw(targetDrawRect, sourceBitmap);
// Создаём JPEG из Bitmap и сохраняем его
jpeg.Assign(targetBitmap) ;
makeFileWriteable(jpegFQFilename);
jpeg.SaveToFile (jpegFQFilename);
finally
jpeg.free;
sourceBitmap.free ;
targetBitmap.free;
end;
except
// Обработка ошибок
end;
end;
Автор: Donall Burns
Вопрос: Что такое DOM?
Ответ: Document Object Model это платформенно
независимый интерфейс, позволяющий программам и
скриптам динамически обновлять и изменять
содержимое, структуру и стиль документов.
Вопрос: Где можно почитать
документацию по DOM?
Ответ: Обзор материалов по DOM на W3C
site , а так же FAQ. Не
забудьте заглянуть на Document object на
сайте Microsoft.
Вопрос: Как работать со всеми фреймами,
отображёнными в данный момент в WebBrowser?
Ответ: Данный пример показывает как определить
в каких фреймах разрешена команда 'copy':
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
for i := 0 to (WebBrowser1.OleObject.Document.frames.Length - 1) do
if WebBrowser1.OleObject.Document.frames.item(i).document.queryCommandEnabled('Copy') then
ShowMessage('copy command is enabled for frame no.' + IntToStr(i));
end;
Автор: Peter Friese
Вопрос: Как работать со всеми ячейками
<TABLE>?
Ответ: Пример показывает как добавить
содержимое каждой ячейки в TMemo:
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
ovTable: OleVariant;
begin
// Я использовал первую таблицу на странице в качестве примера
ovTable := WebBrowser1.OleObject.Document.all.tags('TABLE').item(0);
for i := 0 to (ovTable.Rows.Length - 1) do
begin
for j := 0 to (ovTable.Rows.Item(i).Cells.Length - 1) do
begin
Memo1.Lines.Add(ovTable.Rows.Item(i).Cells.Item(j).InnerText;
end;
end;
end;
Вопрос: Paste работает отлично, но Cut и Copy
отказываются работать. В чём проблема?
Ответ: Вам нужно добавить следующие строки в
начало unit:
initialization
OleInitialize(nil);
finalization
OleUninitialize;
Вопрос: Кобинации клавиш Ctrl-C, Ctrl-O, и т.д. не
срабатывают. В чём проблема?
Ответ: Это не ошибка. Информацию по данному
вопросу можно найти на сайте Microsoft KnowledgeBase статья Q168777.
Приведённый ниже код, устраняет данную проблему:
...
var
Form1: TForm1;
FOleInPlaceActiveObject: IOleInPlaceActiveObject;
SaveMessageHandler: TMessageEvent;
...
implementation
...
procedure TForm1.FormActivate(Sender: TObject);
begin
SaveMessageHandler := Application.OnMessage;
Application.OnMessage := MyMessageHandler;
end;
procedure TForm1.FormDeactivate(Sender: TObject);
begin
Application.OnMessage := SaveMessageHandler;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.OnMessage := SaveMessageHandler;
FOleInPlaceActiveObject := nil;
end;
procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
var
iOIPAO: IOleInPlaceActiveObject;
Dispatch: IDispatch;
begin
{ exit if we don't get back a webbrowser object }
if WebBrowser = nil then
begin
Handled := False;
Exit;
end;
Handled:=(IsDialogMessage(WebBrowser.Handle, Msg) = True);
if (Handled) and (not WebBrowser.Busy) then
begin
if FOleInPlaceActiveObject = nil then
begin
Dispatch := WebBrowser.Application;
if Dispatch <> nil then
begin
Dispatch.QueryInterface(IOleInPlaceActiveObject, iOIPAO);
if iOIPAO <> nil then
FOleInPlaceActiveObject := iOIPAO;
end;
end;
if FOleInPlaceActiveObject <> nil then
if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and
((Msg.wParam = VK_BACK) or (Msg.wParam = VK_LEFT) or (Msg.wParam = VK_RIGHT)) then
//nothing - do not pass on Backspace, Left or Right arrows
else
FOleInPlaceActiveObject.TranslateAccelerator(Msg);
end;
end;
|