WebBrowser知识

Q: What is WebBrowser?
A: The WebBrowser is Microsoft's Internet Explorer in the form of an ActiveX control. It can be imported into the Delphi IDE and dropped on a form like any other component. Therefore, you can harness the power of Internet Explorer to turn your Delphi application into a customized browser.

Q: Where can I get documentation on the WebBrowser?
A: For more information, visit the WebBrowser overview section of the Microsoft site and the WebBrowser object page.

Q: How can I use the WebBrowser component in my Delphi application?
A: You must have Internet Explorer installed on your system. From the menu in the Delphi IDE, select "Component - Import ActiveX Control". Select "Microsoft Internet Controls" and add it to a new or existing package. Delphi will generate a ShDocVw_TLB.pas file and add the WebBrowser component to the component palette's ActiveX tab.

Q: I see 2 components on my component palette's ActiveX tab, WebBrowser and WebBrowser_V1. Which one do I use?
A: If you have 2 components then you are using IE 4.x or greater and WebBrowser is IE 4.x and WebBrowser_V1 is IE 3.x. If you only have one component, then WebBrowser is IE 3.x.

Q: How can I determine which version of IE is installed on a target machine?
A: Information is available on the Microsoft site.

Q: How do I Print?
A: There are a couple of ways to print. The first example works in IE 4.x and up, but you'll have to use the second example in IE 3.x:
var
vaIn, vaOut: OleVariant;
...
WebBrowser.ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, vaIn, vaOut);
or
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
// Nothing
end;
end;
Note: If you're not using Delphi 3.02 or higher, you'll have to change
PGuid(nil)
to
PGuid(nil)^
. And you really should upgrade to 3.02, if you're using 3.0 or 3.01.

Q: How do I invoke the Find, Option or View Source options?
A: Here's a code sample for invoking the Find dialog:
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
// Nothing
end;
Dispose(PtrGUID);
end;

Q: How do I disable the right-click popup menu?
A: You have to implement the IDocHostUIHandler interface. You'll need these two files: ieConst.pas and IEDocHostUIHandler.pas. In the ShowContextMenu method of the IDocHostUIHandler interface, you have to change the return value from E_NOTIMPL to S_OK and the menu will not appear on a right-click. Add the two units mentioned above to your Uses clause and implement the following code:
...
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;

Q: How do I load a string into the WebBrowser without Navigating to a file?
A: Load the string into a Variant array and then write to the Document:
...
var
v: Variant;
HTMLDocument: IHTMLDocument2;
begin
HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
v := VarArrayCreate([0, 0], varVariant);
v[0] := HTMLString; // Here's your HTML string
HTMLDocument.Write(PSafeArray(TVarData(v).VArray));
HTMLDocument.Close;
...
end;
...
This tip provided by Ron Loewy

Q: How do I load a stream into the WebBrowser without Navigating to a file?
A: Here's some sample code:
function TForm1.LoadFromStream(const AStream: TStream): HRESULT;
begin
AStream.seek(0, 0);
Result := (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(AStream));
end;
This tip provided by Per Larsen

Q: How do I use the "about:" protocol?
A: The "about:" protocol will let you Navigate to an HTML string:
procedure TForm1.LoadHTMLString(sHTML: String);
var
Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
WebBrowser1.Navigate('about:' + sHTML, Flags, TargetFrameName, PostData, Headers)
end;

Q: How do I use the "res:" protocol?
A: The "res:" protocol will let you Navigate to an HTML file stored as a resource. More informations is available from the Microsoft site:
procedure TForm1.LoadHTMLResource;
var
Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
WebBrowser1.Navigate('res://' + Application.ExeName + '/myhtml', Flags, TargetFrameName, PostData, Headers)
end;
Create a resource file (*.rc) with the following code and compile it with brcc32.exe:
MYHTML 23 ".\html\myhtml.htm"
MOREHTML 23 ".\html\morehtml.htm"
Edit your project file so that it looks like this:
{$R *.RES}
{$R HTML.RES} //where html.rc was compiled into html.res

Q: How can I get the full HTML source?
A: With IE5, you can get the source by using the HTML tags outerHTML property. With IE4 or IE3, you have to save the document to a file and then load the file into a TMemo, TStrings, etc.
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;
This tip provided by Ron Loewy
Note: You have to import the MSHTML type library and include the resulting MSHTML_TLB, as well as ActiveX, in your Uses clause.

Q: How can I pass PostData when I Navigate to a URL?
A: I call the below method with a URL destination, PostData in the format of 'animal=cat etc. and the TWebBrowser object that I want to load the URL inside of...
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.}
This tip provided by Craig Foley based on techniques from Nathan Wilhelmi's Usenet posting to borland.public.delphi.internet on the 31/1/99
A: Here's another option:
procedure TForm1.SubmitPostForm;
var
strPostData: string;
Data: Pointer;
URL, Flags, TargetFrameName, PostData, Headers: OleVariant;
begin
{
submit this html form: -- method="post" action="http://127.0.0.1/cgi-bin/register.pl" type="text" name="FIRSTNAME" value="Hans" type="text" name="LASTNAME" value="Gulo" type="text" name="NOTE" value="thats it" type="submit" }
strPostData := 'FIRSTNAME=Hans 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 will see that we are providing
// post data and then should automatically fill
// this Headers with appropriate value
WebBrowser1.Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
end;
This tip provided by Hans Gulo.

Q: How can I make WebBrowser flat instead of 3D?
A: Here's a code sample to set the Body's 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;
This tip provided by Donovan J. Edye

Q: How can I save a web page to a bitmap?
A: Here's a code sample:
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;
This tip provided by John

Q: How can I save a web page to a bitmap?
A: Here's a code sample:
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));
// Resize the src bitmap to the target bitmap
targetDrawRect := Rect(0,0, tarWidth, tarHeight);
targetBitmap.Height := tarHeight;
targetBitmap.Width := tarWidth;
targetBitmap.Canvas.StretchDraw(targetDrawRect, sourceBitmap);
// Create a JPEG from the Bitmap and save it
jpeg.Assign(targetBitmap) ;
makeFileWriteable(jpegFQFilename);
jpeg.SaveToFile (jpegFQFilename);
finally
jpeg.free;
sourceBitmap.free ;
targetBitmap.free;
end;
except
// Error Code
end;
end;
This tip provided by Donall Burns

Q: What is DOM?
A: The Document Object Model is a platform- and language-neutral interface that will allow programs and scripts to dynamically access and update the content, structure and style of documents. The document can be further processed and the results of that processing can be incorporated back into the presented page.

Q: Where can I get documentation on the DOM?
A: There's an overview of DOM-related materials at the W3C site and an FAQ. Check the Document object on the Microsoft site for the DOM implementation in IE 4 5.

Q: How can I iterate through all frames currently shown in the WebBrowser?
A: This sample code shows how to interate through all frames in order to test whether the 'copy' command is enabled:
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;
This tip provided by Peter Friese

Q: How can I iterate through all the cells of a
A: This sample code shows how to interate through all the cells of a table, adding the contents of each cell to a TMemo:
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
ovTable: OleVariant;
begin
ovTable := WebBrowser1.OleObject.Document.all.tags('TABLE').item(0); // I'm using the first TABLE on the page as an example only
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;

Q: Paste works fine, but Cut and Copy won't work. What's the problem?
A: You have to add the following line to the bottom of your unit:
initialization
OleInitialize(nil);
finalization
OleUninitialize;

Q: ShortCut (Ctrl-C, Ctrl-O, etc.) and Delete keys have no effect. What's the problem?
A: It's not a bug, it's a feature. There's information about this in a Microsoft KnowledgeBase article Q168777. The code below should fix the problem:
...
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;

此博客中的热门博文

咖啡加牛奶,对健康更有益

Chrome超越Firefox的20条技巧

林牧之女谈《烛烬梦犹虚》出版幕后点滴