Delphi 10.4.1及以上版本的TEdgeBrowser:如何捕获F12(打开DevTools窗口)?

3

我正在使用Delphi 10.4.1中的TEdgeBrowser。它运作得非常好。

唯一令人烦恼的问题是,当TEdgeBrowser获得焦点时,它会占用F12CTRL+SHIFT+C并打开DevTools窗口。这很棒,但我想在加载窗体之前更改窗体的一些最顶层属性(否则,DevTools窗口将位于主窗体后面)。

有没有办法从父窗体MainForm捕获F12?我尝试过Application和MainForm键捕获,但都无法捕获TEdgeBrowser的按键事件(当TEdgeBrowser获得焦点时)。

procedure TMainForm.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
  case Msg.Message of
    WM_KEYDOWN, WM_KEYUP:
      begin
      if Msg.WParam = VK_F11 then
         begin
         SetStatusLog(EID_KEYPRESS,'F11');
         Handled := true;
         end
      else if Msg.WParam = VK_F12 then
         begin
{ do something here and consider F12 handled, preventing F12 from going to TEdgeBrowser???}
         SetStatusLog(EID_KEYPRESS,'F12');
         Handled := true;
         end;
      end;
  end;
end;

有没有其他方法解决这个问题?

此外,我能否通过编程方式启动OpenDevToolsWindow?


使用 ExecuteScript (JS) 可以在浏览器中插入 JavaScript 并执行它。通过这种方式,您可以放置一个 EventListener。例如 不带括号的 <script> </script> (https://stackoverflow.com/questions/34241258/microsoft-edge-keydown-eventhttps://stackoverflow.com/questions/34241258/microsoft-edge-keydown-event) 描述了一个 KeyDown 的示例。您需要使用 window.chrome.webview.postMessage (Key) 将键值从 JavaScript 返回到 Delphi(这是理论)。为此,您必须在 Delphi 中连接 WebMessageReceived 事件。 - USauter
@USauter,您提供的链接似乎已经失效了。不过还是感谢您提供的建议。 - stackman
(https://stackoverflow.com/questions/34241258/microsoft-edge-keydown-event) - USauter
我可以轻松地在ExecuteScript中连接一个post消息。我已经测试过了,并且在WebMessageReceived事件中运行良好。不幸的是,我似乎无法使用推荐的解决方案,因为它需要更改页面代码。我希望将EdgeBrowser指向任何站点并仍然控制按键。看起来我需要更改页面元素。也许我误解了解决方案。 - stackman
在Webview中阅读有关AcceleratorKeyPressed事件的内容。是否有人尝试捕获此事件? - stackman
如果您想使用Javascript添加监听器,我建议考虑使用AddScriptToExecuteOnDocumentCreated而不是ExecuteScript。此函数是TEdgeBrowser.DefaultInterface接口的一部分。 - Greg Dawson
3个回答

3
我已经使用了两种方法来处理这个问题。(1) 您可以调用Set_AreBrowserAcceleratorKeysEnabled(0)来禁用浏览器的加速键(但这可能包括您不想要禁用的内容,而且这并不是您要求的) 。并且需要一些额外的工作来访问此接口,因为它没有包含在当前的TEdgeBrowser中。另外,我在某个地方读到,即使在EdgeBrowser中禁用了快捷键,加速键事件仍然会触发,所以如果您使用这种方法,您可以处理它们。(2) 使用AddScriptToExecuteOnDocumentCreated来注入一些Javascript代码,可以防止默认行为(如果需要)并向您的应用程序发送一条消息(您将在OnWebMessageReceived上接收该消息),以便您可以处理该事件。
选项1:
您需要定义以下内容以访问所需的接口,因为它们是在TEdgeBrowser之后引入的:
const
  IID_ICoreWebview2Settings2: TGUID = '{EE9A0F68-F46C-4E32-AC23-EF8CAC224D2A}'; //Introduced: SDK  1.0.864.35
  IID_ICoreWebview2Settings3: TGUID = '{FDB5AB74-AF33-4854-84F0-0A631DEB5EBA}'; //Introduced: SDK  1.0.864.35

type
  ICoreWebView2Settings2 = interface(ICoreWebView2Settings)
    ['{EE9A0F68-F46C-4E32-AC23-EF8CAC224D2A}']
    function Get_UserAgent(out UserAgent: PWideChar): HResult; stdcall;
    function Set_UserAgent(UserAgent: PWideChar): HResult; stdcall;
  end;

  ICoreWebView2Settings3 = interface(ICoreWebView2Settings2)
    ['{FDB5AB74-AF33-4854-84F0-0A631DEB5EBA}']
    function Get_AreBrowserAcceleratorKeysEnabled(out AreBrowserAcceleratorKeysEnabled: Integer): HResult; stdcall;
    function Set_AreBrowserAcceleratorKeysEnabled(AreBrowserAcceleratorKeysEnabled: Integer): HResult; stdcall;
  end;

然后在你的 OnCreateWebViewCompleted 事件中,可以执行以下操作:

var
  Settings3: ICoreWebView2Settings3;
  HR: HRESULT;
begin
  Sender.SettingsInterface.QueryInterface(IID_ICoreWebView2Settings3, Settings3);
  if Assigned(Settings3) then
  begin
    HR := Settings3.Set_AreBrowserAcceleratorKeysEnabled(0);
    if not SUCCEEDED(HR) then
      {Do something - Set_AreBrowserAcceleratorKeysEnabled failed};
  end
  else
    {Do something - ICoreWebView2Settings3 interface not found.};
  end;  

选项2:

在您的OnCreateWebViewCompleted事件中,您可以执行以下操作

const
  JavaScript =
    '  document.addEventListener(''keydown'', function(event){' + sLineBreak +
    '    if (event.code == "F12") {' + sLineBreak +
    '      Result = "#KEY_EVENT#" + event.code;' + sLineBreak +
    '      event.preventDefault();' + sLineBreak +
    '      window.chrome.webview.postMessage(Result);' + sLineBreak +
    '    };' + sLineBreak +
    '  });'; 

{...}                                                                       
begin
  Sender.DefaultInterface.AddScriptToExecuteOnDocumentCreated(JavaScript,
    Callback<HResult, PChar>.CreateAs<ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler>(
    function(ErrorCode: HResult; Id: PWideChar): HResult stdcall
    begin
      if not(Succeeded(ErrorCode)) then
        {Do something if this function failed.  It gets called later when a document id created.  Or you can pass nil for the Callback};
      Result := 1;
    end));

注意,在选项2中,可以参考TEdgeBrowser代码作为定义回调的示例。它在TEdgeBrowser的实现部分中定义。我只是在我的表单单元的实现部分中复制了它。

感谢您详细的回复。您的解决方案很好用。我能够禁用所有键或根据需要启用它们。这个后续问题有点不相关。我能否将控制台日志条目重定向到Delphi处理程序? - stackman
很高兴你把它弄好了。我不知道如何重新定向控制台日志条目,但我忘了提到,你可以使用类似 EdgeBrowser1.DefaultInterface.OpenDevToolsWindow 这样的东西以编程方式打开 DevTools 窗口。 - Greg Dawson

2
您可以在OnCreateWebViewCompleted事件中使用ASender.DevToolsEnabled := False;来禁用开发者工具。

这对我来说很有效,似乎是最简单的解决方案! - MichaSchumann

0

@stackman

我似乎无法使用推荐的解决方案,因为它需要更改页面代码。我想让 EdgeBrowser 指向任何站点,并仍然控制按键。

procedure TForm1.Button1Click(Sender: TObject);
{$J+}
const
  STEP: integer = 1;
var
 Js: string;
begin
  case STEP of
    1: web.CreateWebView;
    2: web.Navigate('https://dev59.com/x8Lra4cB1Zd3GeqPStZJ?noredirect=1#comment123929534_70089520');
    3: begin //Step 2 must have finished!
         Js := Concat('aaa = new Object; ',
                      'aaa.Message = function(Msg) ',
                      '{ ',
                      '   alert(Msg); ',
                      '}');
                      //DevTools-->Console: type aaa
                      web.ExecuteScript(Js);

        end;
     else
        begin
          Js := 'aaa.Message("Hallo Welt!")';
          web.ExecuteScript(Js);
        end;
   end;
   STEP := STEP + 1;
 end;

控制台 源代码


1
感谢@USauter上面的概念代码正是我一直在做的,以便在导航完成后执行脚本。该脚本检查keydown/keypress事件。对于主页面来说,它似乎工作得“还行”。但是,一旦用户开始选择不同的选项卡(没有页面刷新、导航完成、文档标题更改),我就无法注入相同的JS到后续页面的页脚中,因为没有事件被生成,我也无法捕获。我只是试图拦截tedgebrowser的按键,这样F12就不会在我的窗口下方呈现。 - stackman
也许你需要给它一些东西。window.addEventListener("beforeunload", function (event) { //your code goes here on location change }); [https://dev59.com/A3A75IYBdhLWcg3wAUF9] 看起来很有前途。 - USauter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接