如何避免使用 TWebBrowser 刷新

发布于 2024-09-13 19:30:29 字数 538 浏览 7 评论 0原文

我有一个显示 Google 地图页面的 TWebBrowser 组件。问题是,当用户按 F5 时,页面刷新并重新加载。这会导致 javascript 变量重新初始化并与 Delphi 不同步,并出现脚本错误对话框, “未定义”为空或不是对象。

我想停止用户刷新。

我为 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;

但是当我设置断点时,它甚至没有被调用。还有别的办法吗?

I have a TWebBrowser component that show a Google maps page. The problem is that when user press F5 the page refresh and page reloads. This cause javascript variables to reinitialize and get out of sync with Delphi and a scripting error dialog appear,
'undefined' is null or not an object.

I want to stop refresh from the user.

I tried this event for 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;

But when I set a breakpoint it is not even called. Is there another way ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑红尘 2024-09-20 19:30:29

罗纳德,您可以使用 IHTMLDocument2.onkeydown 事件拦截并阻止按键。

要首先分配事件处理程序,您必须使用 IHTMLEventObj 作为参数。

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

那么您必须创建一个从InterfacedObject 和IDispatch 派生的类来传递和处理事件。

最后就可以这样处理onkeydown事件中拦截到的按键

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.

Ronald you can use the IHTMLDocument2.onkeydown event to intercept and block a key.

to assign an event handler first you must create a procedure type using the IHTMLEventObj as parameter.

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

then you must create an class descendent from InterfacedObject and IDispatch to pass and process the events .

finally you can process the intercepted key in the onkeydown event in this way

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;

//check the full source code

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.
银河中√捞星星 2024-09-20 19:30:29

我没有找到一个简单的方法来做到这一点。我在 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;

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

I did not find an easy way to do this. I could not find any event or anything similar on TWebBrowser, that would dissable refresh. Maybe you should check TEmbededWB as it has more events and is more capable than the default TWebBrowser. Otherwise they are very similar.

But I found a way to prevent refresh. Now it is funny that even with KeyPreview set to "True" on the main form I could not recieve key notifications. It seems that TWebBrowser eats them up somehow. But this worked:

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;

Not the most elegant way but at least it works. I have not found a better solution yet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文