3

The default Delphi 10.4.2 TEdgeBrowser interface is currently only the original-release WebView2. However, it seems that to have flicker-free load on non-white backgrounds we need to set the background color using ICoreWebView2Controller2. How to access this (in a backwards-compatible way) from Delphi? I have tried importing the .tlb from Microsoft's updated WebView2 nuget bundle, however Delphi gives an OLE error, so I cannot find a way to generate a Delphi WebView2 interface with the new functions.

wordy
  • 539
  • 5
  • 15
  • One way is to download Microsoft C/C++ SDK, look at the header files and translate yourself to Delphi the only interface that interest you. – fpiette Mar 17 '21 at 16:14

2 Answers2

6

To call the ICoreWebView2Controller2 methods, you have to first declare the interface and then at run time use QueryInterface to get a reference on it and finally call the method.

Here after a small unit that I created starting from Microsoft header file:

unit Ovb.WebView2;

interface

uses
    WebView2;

const
    IID_ICoreWebView2Controller2: TGUID = '{C979903E-D4CA-4228-92EB-47EE3FA96EAB}';

type
    COREWEBVIEW2_COLOR = packed record
        A : BYTE;
        R : BYTE;
        B : BYTE;
        G : BYTE;
    end;
    TCOREWEBVIEW2_COLOR = COREWEBVIEW2_COLOR;
    PCOREWEBVIEW2_COLOR = ^COREWEBVIEW2_COLOR;

  ICoreWebView2Controller2 = interface(ICoreWebView2Controller)
      ['{C979903E-D4CA-4228-92EB-47EE3FA96EAB}']
      function get_DefaultBackgroundColor(backgroundColor : PCOREWEBVIEW2_COLOR) : HRESULT; stdcall;
      function put_DefaultBackgroundColor(backgroundColor : TCOREWEBVIEW2_COLOR) : HRESULT; stdcall;
  end;


implementation

end.

You can use it for example like this:

procedure TEdgeViewForm.EdgeBrowser1CreateWebViewCompleted(
    Sender  : TCustomEdgeBrowser;
    AResult : HRESULT);
var
    Ctrl2     : ICoreWebView2Controller2;
    BackColor : TCOREWEBVIEW2_COLOR;
    HR        : HRESULT;
begin
    Sender.ControllerInterface.QueryInterface(IID_ICoreWebView2Controller2, Ctrl2);
    if not Assigned(Ctrl2) then
        raise Exception.Create('ICoreWebView2Controller2 not found');
    // Select red background
    BackColor.A := 255;
    BackColor.R := 255;
    BackColor.G := 0;
    BackColor.B := 0;
    HR := Ctrl2.put_DefaultBackgroundColor(BackColor);
    if not SUCCEEDED(HR) then
        raise Exception.Create('put_DefaultBackgroundColor failed');
end;

I have tested my code using Embarcadero EdgeView demo. The red background is visible so I consider my code as correct.

fpiette
  • 11,983
  • 1
  • 24
  • 46
  • Great answer thanks, seems to work. (though unfortunately doesn't resolve my flicker issue loading dark background page in dark theme) – wordy Mar 17 '21 at 18:16
  • An alternative approach would be download/import the tlb (included in the c++ nuget package) and use the constants/interfaces as a reference instead of porting the header by hand. You would still need to use QueryInterface to get the interface. I used this approach to set a cookie (ICoreWebView2_2 and ICoreWebView2CookieManager). Thank you @fpiette for leading me on the right path. – tmjac2 Jul 27 '21 at 23:34
  • I stumbled across this as I had the exact same question as the OP. Thanks all. I just wanted to add, that I, too, got the Ole Error when trying to import the TLB via the Delphi IDE. But using the command line: tlibimp -P -Fe- -XR+ Webview2.tlb worked fine. – Greg Dawson Nov 23 '21 at 14:48
3

To get latest interfaces instead of Delphi bundled, follow the steps:

  1. Download the latest Microsoft.Web.WebView2 package.
  2. Nuget file is a zip archive, extract WebView2.tlb from it
  3. Run "C:\Program Files (x86)\Embarcadero\Studio\{Ver}\bin\tlibimp.exe" -P WebView2.tlb
    Were {Ver} is your RAD Studio version.
    It will create a WebView2_TLB.pas file with available interfaces
  4. Link TLB unit in your project where need it

Sample code usage:

var 
  WebView: ICoreWebView2_7;
  Controller: ICoreWebView2Controller3;
begin
  // May cast directly if you are sure WebView2 runtime supports it
  WebView := ICoreWebView2_7(Browser.DefaultInterface);
  // Or can check if the interface is available
  if Browser.DefaultInterface.QueryInterface(ICoreWebView2_7, WebView) = S_OK then
  // The same for WebView Controller:
  Controller := ICoreWebView2Controller3(Browser.ControllerInterface);
  // or using QueryInterface:
  if Browser.ControllerInterface.QueryInterface(ICoreWebView2Controller3, Controller) = S_OK then
  // Environment interface is accessile through
  // Browser.EnvironmentInterface
Marcodor
  • 4,578
  • 1
  • 20
  • 24