1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| function HRESULTToStr(hr: HRESULT): string;
begin
Result := Format('0x%x (%d)', [hr, hr]);
end;
function CreateHostWindowOverTarget(TargetHWND: HWND): HWND;
var
r: TRect;
begin
Result := 0;
if not IsWindow(TargetHWND) then Exit;
GetWindowRect(TargetHWND, r);
Result := CreateWindowEx(
WS_EX_TOOLWINDOW,
'STATIC',
nil,
WS_POPUP or WS_VISIBLE,
r.Left, r.Top,
r.Right - r.Left, r.Bottom - r.Top,
0, 0, HInstance, nil
);
if Result = 0 then
begin
ShowMessage(Format('Échec CreateWindowEx : code %d', [GetLastError]));
raise Exception.CreateFmt('CreateWindowEx failed: %d', [GetLastError]);
end;
SetWindowPos(Result, TargetHWND, r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top,
SWP_NOACTIVATE or SWP_SHOWWINDOW);
ShowMessage(Format('Fenêtre hôte créée à %d,%d taille %dx%d', [r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top]));
end;
procedure EnsureCOMandThread;
var
res: HRESULT;
begin
if TThread.CurrentThread.ThreadID <> MainThreadID then
raise Exception.Create('CreateWebView doit être exécuté sur le thread UI principal');
res := CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
if Failed(res) and (res <> RPC_E_CHANGED_MODE) then
raise Exception.CreateFmt('CoInitializeEx a échoué : %s', [HRESULTToStr(res)]);
ShowMessage('CoInitializeEx (STA) effectué');
end;
function CreateWebView(aDest: HWND): Pointer; stdcall;
var
hostHWND: HWND;
pid, curPid: DWORD;
styles: LongInt;
hr: HRESULT;
begin
Result := nil;
try
if aDest = 0 then
raise Exception.Create('aDest = 0');
if not IsWindow(aDest) then
raise Exception.Create('Handle invalide (IsWindow = FALSE)');
GetWindowThreadProcessId(aDest, @pid);
curPid := GetCurrentProcessId;
styles := GetWindowLong(aDest, GWL_STYLE);
ShowMessage(Format('HWND cible OK. PID=%d, PID courant=%d, Styles=0x%x', [pid, curPid, styles]));
if pid <> curPid then
begin
ShowMessage('La fenêtre cible appartient à un autre processus -> création d''une fenêtre hôte locale');
hostHWND := CreateHostWindowOverTarget(aDest);
end
else
begin
if (styles and WS_CHILD) = 0 then
begin
ShowMessage('La fenêtre cible n''a pas WS_CHILD -> création d''une fenêtre hôte locale');
hostHWND := CreateHostWindowOverTarget(aDest);
end
else
hostHWND := aDest;
end;
EnsureCOMandThread;
// Créer le parent VCL parented sur hostHWND
WVWindowParent1 := TWVWindowParent.CreateParented(hostHWND);
if WVWindowParent1.Handle = 0 then
raise Exception.Create('Handle de WVWindowParent invalide après CreateParented');
WVWindowParent1.SetBounds(0, 0, 1000, 600);
WVWindowParent1.Show;
ShowMessage(Format('WVWindowParent créé. Handle=0x%x', [WVWindowParent1.Handle]));
// Créer le browser
WVBrowser1 := TWVBrowser.Create(WVWindowParent1);
WVBrowser1.DefaultURL := 'https://google.fr';
WVBrowser1.OnAfterCreated := TDummy.AfterCreated;
WVWindowParent1.Browser := WVBrowser1;
// Vérifier le loader WebView2
if GlobalWebView2Loader.InitializationError then
raise Exception.Create('Erreur du loader WebView2 : ' + GlobalWebView2Loader.ErrorMessage);
if not GlobalWebView2Loader.Initialized then
raise Exception.Create('Le loader WebView2 n''est pas initialisé');
// CreateBrowser retourne un HRESULT ; on l'affiche
hr := WVBrowser1.CreateBrowser(WVWindowParent1.Handle);
ShowMessage('CreateBrowser a retourné ' + HRESULTToStr(hr));
if Failed(hr) then
raise Exception.CreateFmt('CreateBrowser a échoué : %s', [HRESULTToStr(hr)]);
Result := Pointer(WVWindowParent1);
ShowMessage('CreateWebView réussi');
except
on E: Exception do
begin
ShowMessage('Exception dans CreateWebView : ' + E.Message);
try
if Assigned(WVBrowser1) then FreeAndNil(WVBrowser1);
if Assigned(WVWindowParent1) then FreeAndNil(WVWindowParent1);
except end;
raise;
end;
end;
end;
exports
CreateWebView;
end. |
Partager