Использование WebView (EdgeHTML) в Delphi / C++ Builder
Правильно ли я понимаю, что EdgeHTML теперь доступен для рабочего стола (приложения Win32/Win64) в Windows 10? Согласно этим сообщениям в блоге:
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
Похоже, что Microsoft добавила EdgeHTML WebViewControl для настольных приложений Windows (Win32), которые до сих пор не были доступны для настольных приложений (для настольных приложений был доступен только элемент управления MSHTML на основе Trident).
Если это правда, есть ли возможность использовать это в Delphi/C++ Builder или нам нужно ждать нового элемента управления TWebView в новом обновлении RAD Studio? Если возможно - есть ли примеры кода для просмотра (C++ Builder или Delphi)? И означает ли требование.NET, что его нельзя использовать в обычном приложении Win32/Win64, разработанном RAD Studio?
2 ответа
Элемент управления WebView предлагается через WinRT и не зависит от.net. Вы можете использовать его из обычных приложений Win32.
WinRT (среда выполнения Windows), которая теперь иногда рассматривается как часть UWP (универсальная платформа Windows), является чем-то вроде преемника COM.
Как и COM, он в значительной степени основан на интерфейсах, а доступные интерфейсы определены в библиотеках типов. Для WinRT библиотеки типов хранятся в файлах *.WinMD в системном каталоге Windows. Библиотека типов, которая содержит функциональность, необходимую для встраивания браузера Edge: Windows.Web.winmd
,
Delphi поддерживает использование компонентов WinRT и поставляется с переводами некоторых библиотек типов и некоторых дополнительных вспомогательных функций и классов для работы с WinRT.
Однако в настоящее время нет инструмента для автоматического перевода файлов WinMD или IDL, полученных из файлов WinMD, в код Delphi. Если вы хотите использовать функциональность WinRT, которая не поставляется с Delphi, вы должны вручную перевести определения типов в код Delphi.
Если вы устанавливаете Windows Platform SDK, вы найдете переводы IDL и C++ библиотек типов WinRT в таком каталоге, как Drive:\Windows Kits\10\Include\10.0.17134.0\winrt
,
Я использовал эти файлы в качестве шаблонов для создания базового проекта Proof of Concept Delphi (для Delphi 10.2), в котором используется встроенный браузер Edge. Вы можете найти код ниже. Чтобы проверить это, просто создайте новый проект VCL, вставьте код и подключите FormCreate
, FormDestroy
а также FormResize
события с формой.
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.
RAD Studio 10.4 Sydney поставляется с расширенной поддержкой нового браузера Edge на основе Chromium от Microsoft.
Есть как новый Control TEdgeBrowser
который можно использовать для непосредственного использования движка браузера Edge, а также возможность разрешить классический TWebBrowser
для автоматического использования нового движка рендеринга Edge, если он доступен через TWebBrowser.SelectedEngine
свойство.
Подробное объяснение в этой записи блога Embarcadero:
Насколько я знаю, сейчас мы не можем получить доступ к EdgeHtml из C++. Кто-то отправил предложение на сайт uservoice. Я предлагаю вам проголосовать. Разоблачить EdgeHTML C++ API