2010-08-10 64 views
1

我有一个显示Google地图页面的TWebBrowser组件。问题是,当用户按F5页面刷新和页面重新加载。这导致javascript变量重新初始化并与Delphi不同步,并出现一个脚本错误对话框, 'undefined'为空或不是对象。如何避免使用TWebBrowser刷新

我想停止从用户刷新。

我想这个事件OnBeforeNavigate2:

procedure TNewOrganizationForm.mapAddressBeforeNavigate2(ASender: TObject; 
    const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData, 
    Headers: OleVariant; var Cancel: WordBool); 
begin 
    inherited; 
    Cancel := Assigned(fMapEngine) and not fMapEngine.Loading; 
end; 

但是,当我设置一个断点,它甚至没有叫。有另一种方法吗?

回答

8

罗纳德你可以使用IHTMLDocument2.onkeydown事件来拦截和阻止一个密钥。

要首先分配事件处理程序,必须使用IHTMLEventObj作为参数创建过程类型。

THTMLProcEvent = procedure(Sender: TObject; Event: IHTMLEventObj) of object; 

,那么你必须创建InterfacedObjectIDispatch一类后代传递和处理的事件。

终于可以用这种方式

Var 
    HTMLDocument2 : IHTMLDocument2; 
begin 
    if Not Assigned(WebBrowser1.Document) then Exit; 
    HTMLDocument2:=(WebBrowser1.Document AS IHTMLDocument2); 
    if HTMLDocument2.parentWindow.event.keyCode=VK_F5 then //compare the key 
    begin 
    HTMLDocument2.parentWindow.event.cancelBubble:=True; //cancel the key 
    HTMLDocument2.parentWindow.event.keyCode  :=0; 
    end; 
end; 

//检查完整的源代码

unit Unit55; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, OleCtrls, SHDocVw, MSHTML; 

type 
    //Create the procedure type to assign the event 
    THTMLProcEvent = procedure(Sender: TObject; Event: IHTMLEventObj) of object; 

    //Create a new class for manage the event from the twebbrowser 
    THTMLEventLink = class(TInterfacedObject, IDispatch) 
    private 
    FOnEvent: THTMLProcEvent; 
    private 
    constructor Create(Handler: THTMLProcEvent); 
    function GetTypeInfoCount(out Count: Integer): HResult; stdcall; 
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall; 
    function GetIDsOfNames(const IID: TGUID; Names: Pointer; 
     NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall; 
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; 
     Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; 
    public 
    property OnEvent: THTMLProcEvent read FOnEvent write FOnEvent; 
    end; 

    TForm55 = class(TForm) 
    WebBrowser1: TWebBrowser; 
    procedure FormShow(Sender: TObject); 
    procedure WebBrowser1NavigateComplete2(ASender: TObject; const pDisp: IDispatch; var URL: OleVariant); 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    FOnKeyDownConnector: THTMLEventLink; //pointer to the event handler 
    procedure WebBrowser1OnKeyDown(Sender: TObject; EventObjIfc: IHTMLEventObj);//the event handler 
    public 
    { Public declarations } 
    end; 

var 
    Form55: TForm55; 

implementation 

{$R *.dfm} 


constructor THTMLEventLink.Create(Handler: THTMLProcEvent); 
begin 
    inherited Create; 
    _AddRef; 
    FOnEvent := Handler; 
end; 


function THTMLEventLink.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; 
begin 
    Result := E_NOTIMPL; 
end; 


function THTMLEventLink.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; 
begin 
    Result := E_NOTIMPL; 
end; 


function THTMLEventLink.GetTypeInfoCount(out Count: Integer): HResult; 
begin 
    Result := E_NOTIMPL; 
end; 


function THTMLEventLink.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; 
var 
    HTMLEventObjIfc: IHTMLEventObj; 
begin 
    Result := S_OK; 
    if Assigned(FOnEvent) then FOnEvent(Self, HTMLEventObjIfc); 
end; 



procedure TForm55.FormCreate(Sender: TObject); 
begin 
    FOnKeyDownConnector := THTMLEventLink.Create(WebBrowser1OnKeyDown); //assign the address of the event handler 
end; 


procedure TForm55.WebBrowser1NavigateComplete2(ASender: TObject; const pDisp: IDispatch; var URL: OleVariant); 
var 
    HTMLDocument2  : IHTMLDocument2; 
begin 
    HTMLDocument2:=(WebBrowser1.Document AS IHTMLDocument2); 
    HTMLDocument2.onkeydown := FOnKeyDownConnector as IDispatch; //assign the event handler 
end; 

procedure TForm55.WebBrowser1OnKeyDown(Sender: TObject; EventObjIfc: IHTMLEventObj); 
Var 
    HTMLDocument2 : IHTMLDocument2; 
begin 
    //finally do your stuff here, in this case we will intercept and block the F5 key. 
    if Not Assigned(WebBrowser1.Document) then Exit; 
    HTMLDocument2:=(WebBrowser1.Document AS IHTMLDocument2); 
    if HTMLDocument2.parentWindow.event.keyCode=VK_F5 then 
    begin 
    HTMLDocument2.parentWindow.event.cancelBubble:=True; 
    HTMLDocument2.parentWindow.event.keyCode  :=0; 
    end; 
end; 



procedure TForm55.FormShow(Sender: TObject); 
begin 
WebBrowser1.Navigate('www.google.com'); 
end; 



end. 
+0

我认识一个很好的解决方案必须存在处理的onKeyDown事件截获的关键。 +1 – Runner 2010-08-10 10:43:46

+0

我还没有时间来测试这个,但它看起来不错,你会得到复选标记:) – 2010-08-12 06:09:45

+0

+1;完美作品 – 2011-04-26 21:08:06

0

我没有找到一个简单的方法来做到这一点。我无法在TWebBrowser上找到任何事件或任何类似的事件,这会导致无法刷新。也许你应该检查TEmbededWB,因为它有更多的事件,并且比默认的TWebBrowser更有能力。否则它们非常相似。

但我找到了一种防止刷新的方法。现在有趣的是,即使将KeyPreview设置为主窗体上的“True”,我也无法收到关键通知。 TWebBrowser似乎以某种方式吃掉了它们。但这工作:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Application.OnMessage := OnAppMessage; 
end; 

procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean); 
begin 
    if Msg.message = WM_KEYDOWN then 
    if Msg.wParam = VK_F5 then 
     Handled := True; 
end; 

不是最优雅的方式,但至少它的作品。我还没有找到更好的解决方案。