[转载]WebBrowser知识

WebBrowser知识

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;

发表者 midpoint at 10:17 下午 0 评论  

标签: 编程人生
TWebBrowser编程简述

1、初始化和终止化(Initialization inalization)
  大家在执行TWebBrowser的某个方法以进行期望的操作,如ExecWB等的时候可能都碰到过“试图激活未注册的丢失目标”或“OLE对象未注册”等错误,或者并没有出错但是得不到希望的结果,比如不能将选中的网页内容复制到剪贴板等。以前用它编程的时候,我发现ExecWB有时侯起作用但有时侯又不行,在Delphi生成的缺省工程主窗口上加入TWebBrowser,运行时并不会出现“OLE对象未注册”的错误。同样是一个偶然的机会,我才知道OLE对象需要初始化和终止化(懂得的东东实在太少了)。
  我用我的前一篇文章《Delphi程序窗口动画 />
  initialization
   OleInitialize(nil);
  finalization
   try
    OleUninitialize;
   except
   end;
  这几句话放在主窗口所有语句之后,“end.”之前。
-----------------------------------------------------------------------
2、EmptyParam
  在Delphi 5中TWebBrowser的Navigate方法被多次重载:
  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;
  而在实际应用中,使用后几种方法调用时,由于我们很少用到后面几个参数,但函数声明又要求是变量参数,一般的做法如下:
  var
   t:OleVariant;
  begin
   webbrowser1.Navigate(edit1.text,t,t,t,t);
  end;
  需要定义变量t(还有很多地方要用到它),很麻烦。其实我们可以用EmptyParam来代替(EmptyParam是一个公用的Variant空变量,不要对它赋值),只需一句话就可以了:
  webbrowser1.Navigate(edit1.text,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
  虽然长一点,但比每次都定义变量方便得多。当然,也可以使用第一种方式。
  webbrowser1.Navigate(edit1.text)
-----------------------------------------------------------------------
3、命令操作
  常用的命令操作用ExecWB方法即可完成,ExecWB同样多次被重载:
  procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT); overload;
  procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT; var pvaIn:
    OleVariant); overload;
  procedure ExecWB(cmdID: rOLECMDID; cmdexecopt: OLECMDEXECOPT; var pvaIn:
    OleVariant; var pvaOut: OleVariant); overload;
  打开: 弹出“打开Internet地址”对话框,CommandID为OLECMDID_OPEN(若浏览器版本为IE5.0,
      则此命令不可用)。
  另存为:调用“另存为”对话框。
      ExecWB(OLECMDID_SAVEAS,OLECMDEXECOPT_DODEFAULT, EmptyParam,
           EmptyParam);

  打印、打印预览和页面设置: 调用“打印”、“打印预览”和“页面设置”对话框(IE5.5及以上版本才支持打
                印预览,故实现应该检查此命令是否可用)。
      ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, EmptyParam,
           EmptyParam);
      if QueryStatusWB(OLECMDID_PRINTPREVIEW)=3 then
       ExecWB(OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DODEFAULT,
           EmptyParam,EmptyParam);
      ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_DODEFAULT, EmptyParam,
           EmptyParam);

  剪切、复制、粘贴、全选: 功能无须多说,需要注意的是:剪切和粘贴不仅对编辑框文字,而且对网页上的非编
               辑框文字同样有效,用得好的话,也许可以做出功能特殊的东东。获得其命令使能状
               态和执行命令的方法有两种(以复制为例,剪切、粘贴和全选分别将各自的关键字替
               换即可,分别为CUT,PASTE和SELECTALL):
   A、用TWebBrowser的QueryStatusWB方法。
     if(QueryStatusWB(OLECMDID_COPY)=OLECMDF_ENABLED) or
      OLECMDF_SUPPORTED) then
      ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT, EmptyParam,
           EmptyParam);
   B、用IHTMLDocument2的QueryCommandEnabled方法。
     var
      Doc: IHTMLDocument2;
     begin
      Doc :=WebBrowser1.Document as IHTMLDocument2;
      if Doc.QueryCommandEnabled('Copy') then
       Doc.ExecCommand('Copy',false,EmptyParam);
     end;
  查找: 参考第九条“查找”功能。
-----------------------------------------------------------------------
4、字体大小
  类似“字体”菜单上的从“最大”到“最小”五项(对应整数0~4,Largest等假设为五个菜单项的名字,Tag 属性分别设为0~4)。
   A、读取当前页面字体大小。
     var
      t: OleVariant;
     Begin
      WebBrowser1.ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
       EmptyParam,t);
      case t of
      4: Largest.Checked :=true;
      3: Larger.Checked :=true;
      2: Middle.Checked :=true;
      1: Small.Checked :=true;
      0: Smallest.Checked :=true;
      end;
     end;
   B、设置页面字体大小。
     Largest.Checked :=false;
     Larger.Checked :=false;
     Middle.Checked :=false;
     Small.Checked :=false;
     Smallest.Checked :=false;
     TMenuItem(Sender).Checked :=true;
     t :=TMenuItem(Sender).Tag;
     WebBrowser1.ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
      t,t);
-----------------------------------------------------------------------
5、添加到收藏夹和整理收藏夹
    const
     CLSID_ShellUIHelper: TGUID = '{64AB4BB7-111E-11D1-8F79-00C04FC2FBE1}';
    var
     p:procedure(Handle: THandle; Path: PChar); stdcall;
    procedure TForm1.OrganizeFavorite(Sender: Tobject);
    var
     H: HWnd;
    begin
     H := LoadLibrary(PChar('shdocvw.dll'));
     if H 0 then
     begin
    p := GetProcAddress(H, PChar('DoOrganizeFavDlg'));
      if Assigned(p) then p(Application.Handle, PChar(FavFolder));
     end;
     FreeLibrary(h);
    end;
    
    procedure TForm1.AddFavorite(Sender: TObject);
    var
     ShellUIHelper: ISHellUIHelper;
     url, title: Olevariant;
    begin
     Title := Webbrowser1.LocationName;
     Url := Webbrowser1.LocationUrl;
     if Url '' then
     begin
      ShellUIHelper := CreateComObject(CLSID_SHELLUIHELPER) as IShellUIHelper;
      ShellUIHelper.AddFavorite(url, title);
     end;
    end;
-----------------------------------------------------------------------
6、使WebBrowser获得焦点
  TWebBrowser非常特殊,它从TWinControl继承来的SetFocus方法并不能使得它所包含的文档获得焦点,从而不能立即使用Internet Explorer本身具有得快捷键,解决方法如下: />
  procedure TForm1.SetFocusToDoc;
  begin
   if WebBrowser1.Document nil then
    with WebBrowser1.Application as IOleobject do
     DoVerb(OLEIVERB_UIACTIVATE, nil, WebBrowser1, 0, Handle, GetClientRect);
  end;
  除此之外,我还找到一种更简单的方法,这里一并列出:
  if WebBrowser1.Document nil then
   IHTMLWindow2(IHTMLDocument2(WebBrowser1.Document).ParentWindow).focus
  刚找到了更简单的方法,也许是最简单的:
  if WebBrowser1.Document nil then
   IHTMLWindow4(WebBrowser1.Document).focus
  还有,需要判断文档是否获得焦点这样来做:
  if IHTMLWindow4(WebBrowser1.Document).hasfocus then
-----------------------------------------------------------------------
7、点击“提交”按钮
  如同程序里每个窗体上有一个“缺省”按钮一样,Web页面上的每个Form也有一个“缺省”按钮——即属性为“Submit”的按钮,当用户按下回车键时就相当于鼠标单击了“Submit”。但是TWebBrowser似乎并不响应回车键,并且,即使把包含TWebBrowser的窗体的 KeyPreview设为True,在窗体的KeyPress事件里还是不能截获用户向TWebBrowser发出的按键。
  我的解决办法是用 ApplicatinEvents构件或者自己编写TApplication对象的OnMessage事件,在其中判断消息类型,对键盘消息做出响应。至于点击“提交”按钮,可以通过分析网页源代码的方法来实现,不过我找到了更为简单快捷的方法,有两种,第一种是我自己想出来的,另一种是别人写的代码,这里都提供给大家,以做参考。
  A、用SendKeys函数向WebBrowser发送回车键
   在Delphi 5光盘上的Info\Extras\SendKeys目录下有一个SndKey32.pas文件,其中包含了两个函数SendKeys和 AppActivate,我们可以用SendKeys函数来向WebBrowser发送回车键,我现在用的就是这个方法,使用很简单,在 WebBrowser获得焦点的情况下(不要求WebBrowser所包含的文档获得焦点),用一条语句即可:
   Sendkeys('~',true);// press RETURN key
   SendKeys函数的详细参数说明等,均包含在SndKey32.pas文件中。
  B、在OnMessage事件中将接受到的键盘消息传递给WebBrowser。
   procedure TForm1.ApplicationEvents1Message(var Msg: TMsg; var Handled: Boolean);
   {fixes the malfunction of some keys within webbrowser control}
   const
    StdKeys = [VK_TAB, VK_RETURN]; { standard keys }
    ExtKeys = [VK_DELETE, VK_BACK, VK_LEFT, VK_RIGHT]; { extended keys }
    fExtended = $01000000; { extended key flag }
   begin
    Handled := False;
    with Msg do
    if ((Message WM_KEYFIRST) and (Message WM_KEYLAST)) and
     ((wParam in StdKeys) or
     {$IFDEF VER120}(GetKeyState(VK_CONTROL) 0) or {$ENDIF}
     (wParam in ExtKeys) and
     ((lParam and fExtended) = fExtended)) then
    try
     if IsChild(Handle, hWnd) then { handles all browser related messages }
     begin
      with {$IFDEF VER120}Application_{$ELSE}Application{$ENDIF} as
        IOleInPlaceActiveObject do
       Handled := TranslateAccelerator(Msg) = S_OK;
       if not Handled then
       begin
        Handled := True;
        TranslateMessage(Msg);
        DispatchMessage(Msg);
       end;
       end;
    except
    end;
   end; // MessageHandler
  (此方法来自EmbeddedWB.pas)
-----------------------------------------------------------------------
8、直接从TWebBrowser得到网页源码及Html
  下面先介绍一种极其简单的得到TWebBrowser正在访问的网页源码的方法。一般方法是利用TWebBrowser控件中的 Document对象提供的IPersistStreamInit接口来实现,具体就是:先检查WebBrowser.Document对象是否有效,无效则退出;然后取得IPersistStreamInit接口,接着取得HTML源码的大小,分配全局堆内存块,建立流,再将HTML文本写到流中。程序虽然不算复杂,但是有更简单的方法,所以实现代码不再给出。其实基本上所有IE的功能TWebBrowser都应该有较为简单的方法来实现,获取网页源码也是一样。下面的代码将网页源码显示在Memo1中。
   Memo1.Lines.Add(IHtmlDocument2(WebBrowser1.Document).Body.OuterHtml);
  同时,在用TWebBrowser浏览HTML文件的时候要将其保存为文本文件就很简单了,不需要任何的语法解析工具,因为TWebBrowser也完成了,如下:
   Memo1.Lines.Add(IHtmlDocument2(WebBrowser1.Document).Body.OuterText);
-----------------------------------------------------------------------
9、“查找”功能
  查找对话框可以在文档获得焦点的时候通过按键Ctrl-F来调出,程序中则调用IOleCommandTarget对象的成员函数Exec执行OLECMDID_FIND操作来调用,下面给出的方法是如何在程序中用代码来做出文字选择,即你可以自己设计查找对话框。
   var
    Doc: IHtmlDocument2;
    TxtRange: IHtmlTxtRange;
   begin
    Doc :=WebBrowser1.Document as IHtmlDocument2;
    Doc.SelectAll;    //此处为简写,选择全部文档的方法请参见第三条命令操作
                //这句话尤为重要,因为IHtmlTxtRange对象的方法能够操作的前提是
                //Document已经有一个文字选择区域。由于接着执行下面的语句,所以不会
                //看到文档全选的过程。
    TxtRange :=Doc.Selection.CreateRange as IHtmlTxtRange;
    TxtRange.FindText('Text to be searched',0.0);
    TxtRange.Select;
   end;
  还有,从Txt.Get_text可以得到当前选中的文字内容,某些时候是有用的。
-----------------------------------------------------------------------
10、提取网页中所有链接
  这个方法来自大富翁论坛hopfield朋友的对一个问题的回答,我本想自己试验,但总是没成功。
  var
   doc:IHTMLDocument2;
   all:IHTMLElementCollection;
   len,i:integer;
   item:OleVariant;
  begin
   doc:=WebBrowser1 .Document as IHTMLDocument2;
   all:=doc.Get_links;             //doc.Links亦可
   len:=all.length;
   for i:=0 to len-1 do begin
    item:=all.item(i,varempty);        //EmpryParam亦可
    memo1.lines.add(item.href);
   end;
  end;
-----------------------------------------------------------------------
11、设置TWebBrowser的编码
  为什么我总是错过很多机会?其实早就该想到的,但是一念之差,便即天壤之别。当时我要是肯再多考虑一下,多试验一下,这就不会排到第11条了。下面给出一个函数,搞定,难以想象的简单。
  procedure SetCharSet(AWebBrowser: TWebBrowser; ACharSet: String);
  var
   RefreshLevel: OleVariant;
  Begin
   IHTMLDocument2(AWebBrowser.Document).Set_CharSet(ACharSet);
   RefreshLevel :=7;              //这个7应该从注册表来,帮助有Bug。
   AWebBrowser.Refresh2(RefreshLevel);
  End;

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1601698

转载于:https://www.cnblogs.com/gbsck/archive/2007/08/20/862998.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476716.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1404. 将二进制表示减到 1 的步骤数(字符串加法)

1. 题目 给你一个以二进制形式表示的数字 s 。请你返回按下述规则将其减少到 1 所需要的步骤数: 如果当前数字为偶数,则将其除以 2 。如果当前数字为奇数,则将其加上 1 。 题目保证你总是可以按上述规则将测试用例变为 1 。 示例 1&#…

可以炸掉用户脑袋的VR设备来了!元宇宙与现实连接了?

编 | Aeneas 昕朋源 | 新智元游戏失败就杀死你的头显,就问你敢不敢戴?对于很多游戏设计者来说,游戏里的死亡根本不够刺激。在他们看来,要玩就玩真的——在游戏里死了,你就是真死了。Oculus VR创始人帕尔默洛基&#xf…

spark调用python_在MRS集群中使用Python3.7运行PySpark程序,调用RDD的take函数报错处理...

现象 如果我们安装了python3.7版本来运行spark,并且用到了RDD的take函数,就会报错:RuntimeError: generator raised StopIteration 我们可以编写一个python脚本test.py来进行测试,用spark-submit命令提交: spark-submi…

对称加密(DES)

usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Security.Cryptography;usingSystem.IO;namespaceComponent{ public class Security { public Security() { } //默认密钥向量 private static …

AI终于能替我写论文了

编 | 小舟、陈萍源 | 机器之心Meta AI 提出了一个可以总结学术文献,解决数学问题的新模型,该模型还能生成百科文章,编写科学代码,注释分子和蛋白质等等。近年来,随着各学科领域研究的进步,科学文献和数据呈…

网站访问量怎么刷_基于爬虫刷新某网站访问量!我说怎么上千万呢

前言:前一段时间看到有博友写了爬虫去刷新博客访问量一篇文章,当时还觉得蛮有意思的,就保存了一下,但是当我昨天准备复现的时候居然发现文章404了。所以本篇文章仅供学习交流,严禁用于商业用途当我在写文章的同时&…

入市

最近很忙,不是工作,是因为入市。 前天买入第一支股票开始,整个脑袋就开始忙碌起来。什么也顾不得了,时不时偷偷瞄几眼,跌了,就盯着股票曲线图,似乎自己多盯一会儿,那个曲线就会涨…

LeetCode 1405. 最长快乐字符串(贪心)

1. 题目 如果字符串中不含有任何 aaa,bbb 或 ccc 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。 给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s: s 是一个尽可能长的…

我裂开了...人类脑海中的画面,被AI解码了??

作者 | 白鹡鸰导言有没有那么几个瞬间,你要么想把自己脑子里的东西掏出来给别人看,要么想撬开别人的脑子看看里面都装了什么?虽然错过了霍格沃茨的入学时间,但如果从现在开始学习扩散模型和神经学,可能很快你就能实现这…

我的老师

他的人品,学识是对我的一生都有很大的影响,下面的内容都是事实,因为我是他的学生(1992-1995),一生中我都是他的学生 From: http://211.67.168.43/infoshow.aspx?id118 我是这样做教师的——师德标兵李九成老师先进事迹报告大家好&#xff01…

python构建二叉树_python--使用递归的方式建立二叉树

树和图的数据结构,就很有意思啦。# coding utf-8 class BinaryTree: def __init__(self, root_obj): self.key root_obj self.left_child None self.right_child None def insert_left(self, new_node): node BinaryTree(new_node) if self.left_child is None…

GPT-4要来了?传言:先进到与人类无异

编 | Cris源 | 新智元千呼万唤始出来!GPT-4,真要来了?作为史上最受期待的AI模型,GPT-4真要来了?这几天,AI分析师罗梅罗的一篇专栏文章,一经推出便迅速「引爆」了整个AI科技圈。他表示&#xff0…

LeetCode 1406. 石子游戏 III(DP)

1. 题目 Alice 和 Bob 用几堆石子在做游戏。几堆石子排成一行,每堆石子都对应一个得分,由数组 stoneValue 给出。 Alice 和 Bob 轮流取石子,Alice 总是先开始。在每个玩家的回合中,该玩家可以拿走剩下石子中的的前 1、2 或 3 堆…

[引]VS2005 之 Visual Basic 程序的结构

1.文件级编程元素 2.命名空间级编程元素 3.模块级编程元素 4.过程级编程元素 5.Main 过程 Visual Basic 程序是依据标准的构造块建立起来的。 一个解决方案由一个或多个项目组成。 一个项目又包含一个或多个程序集。 每个程序集是依据一个或多个源文件编译而来的。 源文件提供类…

python怎么安装开发版_【干货】开发板上安装python的hiai库和opencv库

Matrix是已经支持phthon接口了,但是发现目前python的hiai库并没有自动安装,需要自己安装; 话不多说下面是安装步骤: 步骤1. 开发板联网,如果已联网则跳过该步骤; 接下来需要在开发板上配置arm的源&#xff…

让AI去分割人体的心肝脾胃肺,靠谱吗?

随着医学影像设备的快速发展和重视程度的增加,医学领域可供深度学习方法所利用的图像不断增多。随着CV领域中,深度学习的复兴,其在医学成像领域的应用大幅增加,图像分割算法基于深度学习的研究已经取得了显著的进展。我们特地请来…

程序员面试金典 - 面试题 17.05. 字母与数字(哈希map+思维转换)

1. 题目 给定一个放有字符和数字的数组,找到最长的子数组,且包含的字符和数字的个数相同。 返回该子数组,若存在多个最长子数组,返回左端点最小的。若不存在这样的数组,返回一个空数组。 示例 1: 输入: ["A&qu…

有效创建Oracle dblink的两种方式

有效创建Oracle dblink的两种方式 两台不同的数据库服务器,从一台数据库服务器的一个用户读取另一台数据库服务器下的某个用户的数据,这个时候可以使用dblink。 其实dblink和数据库中的view差不多,建dblink的时候需要知道待读取数据库的ip地址…

sqlserver2008驱动_Python连接数据库两种方法,QSqlDatabase,pymmsql,驱动名

Qt中内置了好几个数据库的驱动程序,也就是说我们可以直接在PyQt中对这些数据库进行操作。这些内置的数据库包括: IBM DB2,驱动名为QDB2; Borland InterBase,驱动名为QIBASE; MySQL,驱动名为QMYS…

我们追求的泛化,竟是一条死路?

文 | 鹰钩鼻涕虫从我们刚刚接触统计学习方法开始,想必就一直在接受一个思想:相比符号算法,统计模型最重要的能力之一,即是它的泛化能力。或者,用这两年使用更加广泛的话术,则是统计模型具备想象力&#xff…