Code: Select all
; #Requires AutoHotkey v2.0-a112
#Warn
#SingleInstance Force
; DllCall("User32.dll\SetProcessDpiAwarenessContext", "Ptr", 0xFFFFFFFC) ; not sure if this is needed. Works fine without it.
main := gui.new()
main.OnEvent("Close", (main) => main.Hide())
main.Show("w1000 h800")
HotKey("F3", (*) => main.Show("w1000 h800"))
; IWebView2CreateWebView2EnvironmentCompletedHandler.
; https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler#interface_i_web_view2_create_web_view2_environment_completed_handler.
vtbl := BufferAlloc(4*A_PtrSize) ; https://www.autohotkey.com/boards/viewtopic.php?t=37142#p170967
for Each, Method in ["QueryInterface", "AddRef", "Release", "Invoke"]
NumPut("UPtr", CallbackCreate(Method), vtbl, (A_Index-1)*A_PtrSize)
ptr := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 0, "Ptr", A_PtrSize+4, "UPtr")
NumPut("UPtr", vtbl.ptr, ptr)
NumPut("UInt", 1, ptr, A_PtrSize)
; ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.
; https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler#invoke.
vtbl2 := BufferAlloc(4*A_PtrSize)
for Each, Method in ["QueryInterface", "AddRef", "Release", "Invoke_2"]
NumPut("UPtr", CallbackCreate(Method), vtbl2, (A_Index-1)*A_PtrSize)
ptr2 := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 0, "Ptr", A_PtrSize+4, "UPtr")
NumPut("UPtr", vtbl2.ptr, ptr2)
NumPut("UInt", 1, ptr2, A_PtrSize)
; IWebView2NavigationCompletedEventHandler.
; https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2navigationcompletedeventhandler
vtbl3 := BufferAlloc(4*A_PtrSize)
for Each, Method in ["QueryInterface", "AddRef", "Release", "Invoke_3"]
NumPut("UPtr", CallbackCreate(Method), vtbl3, (A_Index-1)*A_PtrSize)
ptr3 := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 0, "Ptr", A_PtrSize+4, "UPtr")
NumPut("UPtr", vtbl3.ptr, ptr3)
NumPut("UInt", 1, ptr3, A_PtrSize)
if R := DllCall(A_ScriptDir . "\WebView2Loader.dll\CreateCoreWebView2Environment", "Ptr", ptr, "UInt") {
MsgBox("ERROR " . Format("{:08X}",R))
}
return
QueryInterface(this, riid, ppvObject) {
local IID_IUnknown := BufferAlloc(16)
local ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler := BufferAlloc(16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{00000000-0000-0000-C000-000000000046}", "Ptr", IID_IUnknown)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{86EF6808-3C3F-4C6F-975E-8CE0B98F70BA}", "Ptr", ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler)
tooltip("TEST")
if DllCall("Ole32.dll\IsEqualGUID", "Ptr", riid, "Ptr", IID_IUnknown)
|| DllCall("Ole32.dll\IsEqualGUID", "Ptr", riid, "Ptr", ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler)
{
NumPut("UPtr", this, ppvObject)
AddRef(this)
return 0 ; S_OK.
}
NumPut("UPtr", 0, ppvObject)
return 0x80004002 ; E_NOINTERFACE.
} ; https://docs.microsoft.com/en-us/windows/desktop/api/unknwn/nf-unknwn-iunknown-queryinterface%28refiid_void%29
AddRef(this) {
local RefCount := NumGet(this,A_PtrSize,"UInt") + 1
; ToolTip("add count = " . RefCount)
NumPut("UInt", RefCount, this, A_PtrSize)
return RefCount
} ; https://docs.microsoft.com/en-us/windows/desktop/api/unknwn/nf-unknwn-iunknown-addref
Release(this) {
local RefCount := NumGet(this,A_PtrSize,"UInt")
if (RefCount > 0)
{
NumPut("UInt", --RefCount, this, A_PtrSize)
; ToolTip("released count = " . RefCount)
if (RefCount == 0)
DllCall("Kernel32.dll\GlobalFree", "Ptr", this)
}
return RefCount
} ; https://docs.microsoft.com/en-us/windows/desktop/api/unknwn/nf-unknwn-iunknown-release
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2createcorewebview2environmentcompletedhandler#invoke
Invoke(this, HRESULT, ICoreWebView2Environment) {
global main, ptr2
; ICoreWebView2Environment::CreateCoreWebView2Controller Method.
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2environment#createcorewebview2controller
ComCall(3, ICoreWebView2Environment, "Ptr", main.hwnd, "Ptr", ptr2)
return 0 ; S_OK.
}
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2createcorewebview2controllercompletedhandler#invoke
Invoke_2(this, HRESULT, IWebView2WebViewController) {
global main, ptr3
ObjAddRef(IWebView2WebViewController) ; This was key to retain a reference to the Controller
webViewController := IWebView2WebViewController
main.OnEvent("Size", Func("mainSize").bind(IWebView2WebViewController))
; Resize WebView to fit the bounds of the parent window.
; IWebView2WebViewController::put_Bounds Method.
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2controller#put_bounds
DllCall("User32.dll\GetClientRect", "Ptr", main.hWnd, "Ptr", RECT := BufferAlloc(16))
ComCall(6, IWebView2WebViewController, "Ptr", RECT)
; IWebView2WebViewController::get_CoreWebView2
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2controller#get_corewebview2
ComCall(25, IWebView2WebViewController, "Ptr*", webView := 0)
; ICoreWebView2::add_navigationstarting
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2#add_navigationstarting
ComCall(7, webview, "Ptr", ptr3, "Ptr", token := BufferAlloc(8))
; ICoreWebView2::Navigate
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2#navigate
; ComCall(5, webview, "Str", "https://www.google.com/")
ComCall(5, webview, "Str", "file:///" A_ScriptDir "/index.html")
return 0 ; S_OK.
}
; https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/0-9-538/icorewebview2navigationstartingeventhandler#invoke
Invoke_3(this, IWebView2WebView, IWebView2NavigationStartingEventArgs) {
ComCall(4, IWebView2NavigationStartingEventArgs, "Int*", isUserInitiated := 0)
ComCall(5, IWebView2NavigationStartingEventArgs, "Int*", isRedirected := 0)
if (isUserInitiated && !isRedirected) {
ComCall(3, IWebView2NavigationStartingEventArgs, "Str*", uri := "")
if (MsgBox("You are about to navigate to: " . uri . "`n`nDo you want to continue?", "Navigation warning", "YN Icon!") = "No") {
; IWebView2NavigationStartingEventArgs::put_Cancel
ComCall(8, IWebView2NavigationStartingEventArgs, "Int", true)
; ICoreWebView2::NavigateToString
ComCall(6, IWebView2WebView, "Str", "<h1>Navigation Canceled</h1><p>You chose to cancel navigation to the following URL: " . uri . "</p>")
}
}
return 0 ; S_OK
}
mainSize(controller, win, minMax, *) {
; for performance reasons, you should make the webview2 not visible when the parent window is minimized/hidden.
ComCall(3, controller, "Int*", isVisible := 0)
if (minMax == -1 && isVisible) {
ComCall(4, controller, "Int", false)
}
else if (minMax == 0 && !isVisible) {
ComCall(4, controller, "Int", true)
}
}
class IUnknown {
__New() {
}
}