在Delphi / C ++ Builder中使用WebView(EdgeHTML)

问题描述 投票:5回答:2

我是否正确理解EdgeHTML现在可用于Windows 10中的桌面(Win32 / Win64应用程序)?根据这些博客文章:

https://blogs.windows.com/msedgedev/2018/05/09/modern-webview-winforms-wpf-apps/ https://blogs.windows.com/msedgedev/2018/10/04/edgehtml-18-october-2018-update/ https://docs.microsoft.com/en-us/windows/communitytoolkit/controls/wpf-winforms/webview

看来微软已经为Windows桌面(Win32)应用添加了EdgeHTML WebViewControl,这些应用到目前为止还没有桌面应用程序可用(只有基于Trident的MSHTML控件可用于桌面应用程序)。

如果这是真的,是否有可能在Delphi / C ++ Builder中使用它,或者我们是否必须在RAD Studio的新更新中等待新的TWebView控件?如果可能 - 是否有任何代码示例(C ++ Builder或Delphi)? .NET的要求是否意味着它无法在RAD Studio生产的常规Win32 / Win64应用程序中使用?

delphi webview microsoft-edge c++builder
2个回答
7
投票

WebView控件通过WinRT提供,不依赖于.net。您可以从普通的Win32应用程序中使用它。

WinRT(Windows运行时),现在在Windows 10中更名为UWP(通用Windows平台),类似于COM的继承者。

与COM类似,它主要基于接口,可用接口在类型库中定义。对于WinRT,类型库存储在Windows系统目录中的* .WinMD文件中。包含我们嵌入Edge浏览器所需功能的类型库是Windows.Web.winmd

Delphi支持使用WinRT组件,它附带了一些类型库的翻译以及一些辅助函数和类来与WinRT一起使用。

但是,目前没有工具可以自动将WinMD文件或从WinMD文件派生的IDL文件转换为Delphi代码。如果要使用Delphi不附带的WinRT功能,则必须手动将类型定义转换为Delphi代码。

WinRT大量使用通用接口(带有类型参数的接口),这些接口与通用接口在Delphi中的工作方式不兼容。在翻译类型定义时,这需要一些手动调整。

如果安装Windows Platform SDK,则可以在Drive:\Windows Kits\10\Include\10.0.17134.0\winrt等目录中找到WinRT类型库的IDL和C ++转换。

我已经使用这些文件作为模板来创建一个非常基本的Proof of Concept Delphi项目(适用于Delphi 10.2),该项目使用嵌入式Edge浏览器。你可以在下面找到代码。为了测试这个,只需创建一个新的VCL项目,粘贴代码并将FormCreateFormDestroyFormResize事件与表单连接起来。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  System.Types,
  Winapi.Winrt,
  System.Win.WinRT,
  WinAPI.Foundation,
  WinAPI.Foundation.Types;

const
  SWebViewControlProcess = 'Windows.Web.UI.Interop.WebViewControlProcess';

type
  // Interface with functionality to interact with WebBrowser Control
  // https://docs.microsoft.com/en-us/uwp/api/windows.web.ui.iwebviewcontrol
  IWebViewControl = interface(IInspectable)
  ['{3F921316-BC70-4BDA-9136-C94370899FAB}']
    procedure Placeholder_SourceGet; safecall;
    procedure Placeholder_SourcePut; safecall;
    procedure Placeholder_DocumentTitle; safecall;
    procedure Placeholder_CanGoBack; safecall;
    procedure Placeholder_CanGoForward; safecall;
    procedure Placeholder_DefaultBackgroundColorPut; safecall;
    procedure Placeholder_DefaultBackgroundColorGet; safecall;
    procedure Placeholder_ContainsFullScreenElement; safecall;
    procedure Placeholder_Settings; safecall;
    procedure Placeholder_DeferredPermissionRequests; safecall;
    procedure Placeholder_GoForward; safecall;
    procedure Placeholder_GoBack; safecall;
    procedure Placeholder_Refresh; safecall;
    procedure Placeholder_Stop; safecall;
    procedure Navigate(source: IUriRuntimeClass); stdcall;
    procedure NavigateToString(text: HString); stdcall;
    // TODO: Declare further properties and functions of IWebViewControl
  end;

  IWebViewControlProcess = interface;

  // Declare  IWebViewControlSite
  IWebViewControlSite = interface(IInspectable)
  ['{133F47C6-12DC-4898-BD47-04967DE648BA}']
    function get_Process: IWebViewControlProcess; safecall;
    procedure put_Scale(value: Double); safecall;
    function get_Scale: Double; safecall;
    procedure put_Bounds(value: TRectF); safecall;
    function get_Bounds: TRectF; safecall;
    procedure put_IsVisible(value: Boolean); safecall;
    function get_IsVisible: Boolean; safecall;

    // TODO: Declare further properties and functions of IWebViewControlSite

    property Process: IWebViewControlProcess read get_Process;
    property Scale: Double read get_Scale write put_Scale;
    property Bounds: TRectF read get_Bounds write put_Bounds;
    property IsVisible: Boolean read get_IsVisible write put_IsVisible;
  end;

  // types for reacting to when the WebView has finished initialization
  IAsyncOperation_1__IWebViewControl = interface;

  IAsyncOperationCompletedHandler_1__IWebViewControl = interface(IUnknown)
  ['{d61963d6-806d-50a8-a81c-75d9356ad5d7}']
    procedure Invoke(asyncInfo: IAsyncOperation_1__IWebViewControl; asyncStatus: AsyncStatus); safecall;
  end;

  IAsyncOperation_1__IWebViewControl = interface(IInspectable)
  ['{ac3d28ac-8362-51c6-b2cc-16f3672758f1}']
    procedure put_Completed(handler: IAsyncOperationCompletedHandler_1__IWebViewControl); safecall;
    function get_Completed: IAsyncOperationCompletedHandler_1__IWebViewControl; safecall;
    function GetResults: IWebViewControl; safecall;
    property Completed: IAsyncOperationCompletedHandler_1__IWebViewControl read get_Completed write put_Completed;
  end;

  TWebViewControlCompleted = procedure(asyncInfo: IAsyncOperation_1__IWebViewControl; aasyncStatus: AsyncStatus) of object;

  TWebViewControlCompletedHandler = class(TInspectableObject,
      IAsyncOperationCompletedHandler_1__IWebViewControl
      )
  private
    FEvent: TWebViewControlCompleted;
  public
    procedure Invoke(asyncInfo: IAsyncOperation_1__IWebViewControl; aasyncStatus: AsyncStatus); safecall;
    constructor Create(AEvent: TWebViewControlCompleted);
  end;

   // The interface for interacting with the process hosting the web view control
   // https://docs.microsoft.com/en-us/uwp/api/windows.web.ui.interop.webviewcontrolprocess
  [WinRTClassNameAttribute(SWebViewControlProcess)]
  IWebViewControlProcess = interface(IInspectable)
  ['{02C723EC-98D6-424A-B63E-C6136C36A0F2}']
    function get_ProcessId: Cardinal; safecall;
    function get_EnterpriseId: HSTRING; safecall;
    function get_IsPrivateNetworkClientServerCapabilityEnabled: Boolean; safecall;
    function CreateWebViewControlAsync(hostWindowHandle: Int64; bounds: TRectF): IAsyncOperation_1__IWebViewControl; safecall;
    procedure Placeholder_GetWebViewControls; safecall;
    procedure Terminate; safecall;

    property ProcessId: Cardinal read get_ProcessId;
    property EnterpriseId: HSTRING read get_EnterpriseId;
    property IsPrivateNetworkClientServerCapabilityEnabled: Boolean read get_IsPrivateNetworkClientServerCapabilityEnabled;

    // TODO:
    //[eventadd] HRESULT ProcessExited([in] Windows.Foundation.TypedEventHandler<Windows.Web.UI.Interop.WebViewControlProcess*, IInspectable*>* handler, [out] [retval] EventRegistrationToken* token);
    //[eventremove] HRESULT ProcessExited([in] EventRegistrationToken token);
  end;

  // The CoClass to create an IWebViewControlProcess instance
  TWebViewControlProcess = class(TWinRTGenericImportI<IWebViewControlProcess>)
  end;

type

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    FProcess: IWebViewControlProcess;
    FBrowser: IWebViewControl;
    FBrowserSite: IWebViewControlSite;
    procedure WebViewCompleted(asyncInfo: IAsyncOperation_1__IWebViewControl; aasyncStatus: AsyncStatus);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Rect: TRectF;
  AsyncOperation: IAsyncOperation_1__IWebViewControl;
    CompletedHandler: IAsyncOperationCompletedHandler_1__IWebViewControl;
begin
  CompletedHandler:=TWebViewControlCompletedHandler.Create(WebViewCompleted);

  // Size for browser
  Rect:= TRectF.Create(0, 0, ClientWidth, ClientHeight);

  // Create hosting process
  FProcess:= TWebViewControlProcess.Create();

  // Create WebView Control
  AsyncOperation:= FProcess.CreateWebViewControlAsync(self.Handle, Rect);

  // We will get notified when the control creation is finished
  AsyncOperation.Completed:= CompletedHandler;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // If there is a hosting process, then terminate it
  if Assigned(FProcess) then
  begin
    FProcess.Terminate;
  end;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  if Assigned(FBrowserSite) then
  begin
    FBrowserSite.Bounds := TRectF.Create(0,0,ClientWidth, ClientHeight);
  end;
end;

procedure TForm1.WebViewCompleted(
  asyncInfo: IAsyncOperation_1__IWebViewControl;
  aasyncStatus: AsyncStatus);
var
  WinS: TWindowsString;
  Uri: IUriRuntimeClass;
begin
  // Initializing the WebView control was successful

  // Remember reference to control
  FBrowser:= asyncInfo.GetResults();
  FBrowserSite := FBrowser as IWebViewControlSite;

  // Load web page into control
  WinS:= TWindowsString.Create('http://www.whatismybrowser.com');
  Uri:= TUri.CreateUri(WinS);
  FBrowser.Navigate(Uri);
end;

{ TWebViewControlCompletedHandler }

constructor TWebViewControlCompletedHandler.Create(
  AEvent: TWebViewControlCompleted);
begin
  FEvent := AEvent;
end;

procedure TWebViewControlCompletedHandler.Invoke(
  asyncInfo: IAsyncOperation_1__IWebViewControl;
  aasyncStatus: AsyncStatus);
begin
  FEvent(asyncInfo, aasyncStatus);
end;

end.

enter image description here


0
投票

据我所知,我们现在无法从C ++访问EdgeHtml,有人在uservoice网站上提交了一个建议。我建议你可以投票。 Expose EdgeHTML C++ API

© www.soinside.com 2019 - 2024. All rights reserved.