I am using TEdgeBrowser
in Delphi 10.4.1. It works very well.
The only nagging issue is, when TEdgeBrowser
has focus, it grabs F12 and CTRL SHIFT C and presents the OpenDevToolsWindow. This is great, except I want to change some of the topmost properties of the Form before it loads (otherwise, the DevTools window will be behind the MainForm).
Is there any way to trap F12 from the parent MainForm? I have tried Application and MainForm key captures, but both fail to capture the TEdgeBrowser
key events (when TEdgeBrowser
has focus).
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;
Is there another way to tackle this?
Additionally, can I launch the OpenDevToolsWindow programmably?
CodePudding user response:
@stackman
I cannot seem to use the recommended solution because it requires changes to the page code. I would like to point EdgeBrowser to any site and still have control over keypress.
procedure TForm1.Button1Click(Sender: TObject);
{$J }
const
STEP: integer = 1;
var
Js: string;
begin
case STEP of
1: web.CreateWebView;
2: web.Navigate('https://stackoverflow.com/questions/70089520/tedgebrowser-for-delphi-10-4-1-and-later-how-to-trap-f12-opendevtoolswindow?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;
CodePudding user response:
I have used two ways to handle this. (1) You can call Set_AreBrowserAcceleratorKeysEnabled(0) to disable the browser's accelerator keys (but that might include disabling more than you want. And it requires some additional work to get access to this interface as it is not included in the current TEdgeBrowser (2) Use the AddScriptToExecuteOnDocumentCreated to inject some Javascript that will prevent the default behavior and send your app a message (which you'll pick up on OnWebMessageReceived) so you can process the event.
Option 1:
You'll need to define the following to get access to the interfaces you need as they were introduced after what TEdgeBrowser has:
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;
Then in your OnCreateWebViewCompleted event you can do
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;
Option 2:
In your OnCreateWebViewCompleted event you can do the following
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));
Note, in Option 2, see TEdgeBrowser code as example for defining the Callback. It is defined in the implementation part of TEdgeBrowser. I just replicated it in my own form's unit implementation section.