单击 TWebBrowser 组件时模拟 OnEnter

问题描述

我有一个包含一些组件的表单,包括一个显示一些网页的 TWebbrowser,我希望能够使用 Tab 键在它们之间移动。

我已经能够在 Web 浏览器中 capture key presses,因此当 Web 浏览器获得焦点并按下 Tab 键时,它会被捕获,并且焦点会跳转到表单中的下一个控件。

这是我的样品单元。这是一个包含三个按钮的简单表单:

simple unit

unit WebbrowserOnEnter;

interface

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

type
  // https://stackoverflow.com/questions/3446440/how-can-i-avoid-refresh-with-twebbrowser/3447422#3447422 
  //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;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Webbrowser1: TWebbrowser;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Webbrowser1NavigateComplete2(Sender: TObject;
      const pdisp: Idispatch; var URL: OleVariant);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Webbrowser1Enter(Sender: TObject);
    procedure Webbrowser1Exit(Sender: TObject);
  private
    FOnKeyDownConnector:  THTMLEventLink; //pointer to the event handler
    procedure browserIHTMLDocument2OnKeyDown(Sender: TObject; Event: IHTMLEventObj);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

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,ArgErr: Pointer): HResult;
var
  HTMLEventObjIfc: IHTMLEventObj;
begin
  Result := S_OK;
  if Assigned(FOnEvent) then FOnEvent(Self,HTMLEventObjIfc);
end;

procedure TForm1.browserIHTMLDocument2OnKeyDown(Sender: TObject;
  Event: IHTMLEventObj);
var
  HTMLDocument2 : IHTMLDocument2;
begin
  if Not Assigned(Webbrowser1.Document) then  Exit;
  HTMLDocument2:=(Webbrowser1.Document AS IHTMLDocument2);
  // VK_F5,VK_TAB
  if HTMLDocument2.parentwindow.event.keyCode = VK_TAB then
  begin
    HTMLDocument2.parentwindow.event.cancelBubble:=True; //cancel the key
    HTMLDocument2.parentwindow.event.keyCode     :=0;
    SendMessage(Form1.Handle,WM_NEXTDLGCTL,0);
    //SendMessage(GetParentForm(Webbrowser1).Handle,0);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin  
  FOnKeyDownConnector := THTMLEventLink.Create(browserIHTMLDocument2OnKeyDown); //assign the address of the event handler
  Webbrowser1.Navigate('https://en.wikipedia.org');
end;

procedure TForm1.Webbrowser1NavigateComplete2(Sender: TObject;
  const pdisp: Idispatch; var URL: OleVariant);
var
  HTMLDocument2      : IHTMLDocument2;
begin
  HTMLDocument2:=(Webbrowser1.Document AS IHTMLDocument2);
  if (HTMLDocument2 <> nil) and (FOnKeyDownConnector <> nil) then
    HTMLDocument2.onkeydown := FOnKeyDownConnector as Idispatch; //assign the event handler
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Button1Click');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMessage('Button2Click');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ShowMessage('Button3Click');
end;

procedure TForm1.Webbrowser1Enter(Sender: TObject);
begin
  ShowMessage('Webbrowser1Enter');
end;

procedure TForm1.Webbrowser1Exit(Sender: TObject);
begin
  ShowMessage('Webbrowser1Exit');
end;

end.

它使用 MSHTML_TLB unit generated using the Delphi IDE

我想在进入或退出浏览器时做一些事情。我可以使用 OnEnter 和 OnExit 方法来做到这一点,而且效果很好。我的问题是当我点击 TWebbrowser 时,我没有保持标签流。如果我单击浏览器并然后按 Tab 键,则会触发 OnEnter 方法

如何模拟 OnEnter 行为,以便单击浏览器,然后在按下 Tab 键时跳转到 Button3?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)