Как я могу избежать обновления с TWebBrowser - PullRequest
1 голос
/ 10 августа 2010

У меня есть компонент TWebBrowser, который показывает страницу карт Google. Проблема в том, что когда пользователь нажимает клавишу F5, страница обновляется и страница перезагружается. Это приводит к повторной инициализации переменных javascript и их синхронизации с Delphi, и появляется диалоговое окно ошибок сценариев, 'undefined' является нулем или не является объектом.

Я хочу остановить обновление от пользователя.

Я пробовал это событие для 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;

Но когда я устанавливаю точку останова, она даже не вызывается. Есть ли другой способ?

Ответы [ 2 ]

8 голосов
/ 10 августа 2010

Рональд, вы можете использовать событие 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.
1 голос
/ 10 августа 2010

Я не нашел простой способ сделать это.Я не смог найти ни одного события или чего-то подобного на 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;

Не самый элегантный способ, но по крайней мере это работает.Я еще не нашел лучшего решения.

...