在Delphi/C ++ Builder中使用WebView(EdgeHTML) [英] Using WebView (EdgeHTML) in Delphi / C++ Builder

查看:206
本文介绍了在Delphi/C ++ Builder中使用WebView(EdgeHTML)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Am I understanding correctly that EdgeHTML is now available to desktop (Win32/Win64 applications) now in Windows 10? According to these blog posts:

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/zh-CN /windows/communitytoolkit/controls/wpf-winforms/webview

Microsoft似乎为Windows桌面(Win32)应用程序添加了EdgeHTML WebViewControl,到目前为止,该应用程序尚不适用于桌面应用程序(仅基于Trident的MSHTML控件适用于桌面应用程序).

It appears that Microsoft has added EdgeHTML WebViewControl for Windows desktop (Win32) apps which hasn't been available for desktop apps so far (only Trident based MSHTML control was available for desktop apps).

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

If this is true, is there a possibility to utilize this in Delphi/C++ Builder or do we have to wait for a new TWebView control in the new update of RAD Studio? If possible - are there any code samples to look at (C++ Builder or Delphi that is)? And does the requirement of .NET means it can't be utilized in regular Win32/Win64 app as produced by RAD Studio?

推荐答案

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

The WebView control is offered via WinRT and does not depend on .net. You can use it from normal Win32 applications.

WinRT(Windows运行时)现在已在Windows 10中更名为UWP(通用Windows平台),类似于COM的后继产品.

WinRT (Windows Runtime), now in Windows 10 rebranded as UWP (Universal Windows Platform), is something like the successor of COM.

像COM一样,它很大程度上基于接口,并且可用接口在类型库中定义.对于WinRT,类型库存储在Windows系统目录中的* .WinMD文件中.包含我们需要嵌入Edge浏览器的功能的类型库是Windows.Web.winmd.

Like COM it is heavily based on interfaces and the available interfaces are defined in type libraries. For WinRT, the type libraries are stored in *.WinMD files in the Windows system directory. The type library which contains the functionality we need to embed the Edge browser is Windows.Web.winmd.

Delphi确实支持使用WinRT组件,并且随附一些类型库的翻译以及一些其他与WinRT一起使用的辅助函数和类.

Delphi does support using WinRT components and it comes with translations of some of the type libraries and some additional helper functions and classes to work with WinRT.

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

However, there is currently no tool to automatically translate WinMD files or IDL files derived from WinMD files to Delphi code. If you want to use WinRT functionality that does not ship with Delp you have to manually translate the type definitions to Delphi code.

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

WinRT heavily uses generic interfaces (interfaces with type parameters) that are not compatible with the way generic interfaces work in Delphi. This requires some manual adjustments when translating the type definitions.

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

If you install the Windows Platform SDK, you find IDL and C++ translations of the WinRT type libraries in a directory like Drive:\Windows Kits\10\Include\10.0.17134.0\winrt.

我已使用这些文件作为模板来创建一个非常基本的概念验证Delphi项目(用于Delphi 10.2),该项目使用嵌入式Edge浏览器.您可以在下面找到代码.为了对此进行测试,只需创建一个新的VCL项目,粘贴代码并将FormCreateFormDestroyFormResize事件与表单连接即可.

I have used these files as templates to create a very basic Proof of Concept Delphi project (for Delphi 10.2) which uses an embedded Edge browser. You can find the code below. In order to test this, just create a new VCL project, paste the code and connect the FormCreate, FormDestroy and FormResize events with the form.

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.

这篇关于在Delphi/C ++ Builder中使用WebView(EdgeHTML)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆