WebView2 Control For Edge

Share the finished AutoHotkey v2 Scripts and libraries you made here. Please put the current version of AutoHotkey v2 you used in Square Brackets at the start of the topic title.
xroot
Posts: 15
Joined: 21 Jun 2019, 08:45

WebView2 Control For Edge

23 Sep 2020, 13:00

From what I read on the forum, could not get the WebView2 examples to work.
Started playing with the WebView2Loader.dll (ver:9.579.0), Win7-Edge ver:85.0.564.51, AHK ver:2.0_122:U64.

In the WebView2Loader I call "CreateCoreWebView2EnvironmentWithOptions" to get started. (see WebView2.ahk for info)
This is set up by the Function Init_WebView2(Gui variable) and make sure your Edge and WebView2Loader path are correct.

Added "IWebView2WebViewController::put_ZoomFactor" to set the ZoomFactor = 125%.

WebView2 Include

Code: Select all

/*  WebView2 for AutoHotkey v2.0-a122
 *
 *  Provides an interfaces to The Microsoft Edge WebView2 control and enables you to host web content in your applications
 *  This is a 64-bit Dll program, use AHK U64.
 *
 *  Use, modify and redistribute without limitation.
 */

winSize(controller,minMax,*){
    ; IWebView2WebViewController::get_IsVisible
    ComCall 3,controller,"int*",isVisible := 0
    If(minMax == -1){
        if(isvisible)
            ; IWebView2WebViewController::put_IsVisible
            ComCall 4,controller,"int",False
    }Else{
        If(!isVisible)
            ; IWebView2WebViewController::put_IsVisible
            ComCall 4,controller,"int",True
        Else{
            DllCall "GetClientRect","ptr",hWnd,"ptr",RECT := BufferAlloc(16)
            ; IWebView2WebViewController::put_Bounds
            ComCall 6,controller,"ptr",RECT
        }
    }
}

QueryInterface(this,riid,ppvObject){
    ; This isn't called at all...
}

AddRef(this){
    NumPut "uint",ObjAddRef(this),this,A_PtrSize
}

Release(this){
    NumPut "uint",ObjRelease(this),this,A_PtrSize
}

Invoke(this,HRESULT,iObject){
    Switch(this){
        Case WebView2Environment:
            ; ICoreWebView2Environment::CreateCoreWebView2Controller Method.
            ComCall(3,iObject,"ptr",hWnd,"ptr",WebView2Controller)
        Case WebView2Controller:
            ObjAddRef iObject
            winParent.OnEvent "Size",Func("winSize").bind(iObject)
            ; Resize WebView to fit the bounds of the parent window.
            ; IWebView2WebViewController::put_Bounds Method.
            DllCall "GetClientRect","ptr",hWnd,"ptr",RECT := BufferAlloc(16)
            ComCall 6,iObject,"ptr",RECT
            ; IWebView2WebViewController::get_CoreWebView2
            ComCall 25,iObject,"ptr*",CoreWebView2
            ; IWebView2WebViewController::put_ZoomFactor
            ComCall 8,iObject,"double",ZoomFactor
            ; ICoreWebView2::add_navigationstarting
            ComCall 7,CoreWebView2,"ptr",WebView2NavigationStartingEventArgs,"uint64",token := 0
            If HtmlSite
                ; ICoreWebView2::Navigate
                ComCall 5,CoreWebView2,"str",HtmlSite
            If HtmlStr
                ; ICoreWebView2::NavigateToString
                ComCall 6,CoreWebView2,"str",HtmlStr
            If WebView2DocumentTitleChangedEventHandler
                ; ICoreWebView2::add_DocumentTitleChanged
                ComCall 46,CoreWebView2,"ptr",WebView2DocumentTitleChangedEventHandler,"uint64",token := 0
        Case WebView2NavigationStartingEventArgs:
            ComCall 4,iObject,"int*",isUserInitiated:=False
            if(isUserInitiated)
                ComCall 3,iObject,"str*",uri := ""
        Case WebView2DocumentTitleChangedEventHandler:
            ; ICoreWebView2::get_DocumentTitle
            ComCall 48,CoreWebView2,"str*",DocTitle := ""
            If(!isfunc("On_Click")){
                MsgBox "Function On_Click Not Created....","Func Error!","iconi"
                ExitApp
            }
            Func("On_Click").Call(DocTitle)
    }
}

WebView2(Invoke){
    vtbl.Push BufferAlloc(4*A_PtrSize)
    For Each,Method In ["QueryInterface","AddRef","Release","Invoke"]
        NumPut "uptr",CallbackCreate(Method),vtbl[Invoke],(A_Index-1)*A_PtrSize
    ptr := DllCall("GlobalAlloc","uint",64,"ptr",A_PtrSize+4,"uptr")
    NumPut "uptr",vtbl[Invoke].ptr,ptr
    NumPut "uint",1,ptr,A_PtrSize
    Return ptr
}

ClickEvents_WebView2(){
    WebView2DocumentTitleChangedEventHandler := WebView2(4)  ; ICoreWebView2DocumentTitleChangedEventHandler.
}

Init_WebView2(parent){
    hWnd                                  := parent.hWnd
    winParent                             := parent
    WebView2Environment                   := WebView2(1)     ; IWebView2CreateWebView2EnvironmentCompletedHandler.
    WebView2Controller                    := WebView2(2)     ; ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.
    WebView2NavigationStartingEventArgs   := WebView2(3)     ; IWebView2NavigationCompletedEventHandler.

    EdgePath := "c:\Program Files (x86)\Microsoft\Edge\Application\85.0.564.63\"
    dllPath  := "WebView2Loader"

    DllCall dllPath "\CreateCoreWebView2EnvironmentWithOptions","str",EdgePath,"str","","ptr",0,"uptr",WebView2Environment

    If(a_lasterror){
        buf := BufferAlloc(8,0)
        DllCall "FormatMessage","uint",256|4096,"ptr",0,"uint",a_lasterror,"uint",0,"ptr",buf.ptr,"uint",0,"ptr",0
        msgbox "Error " a_lasterror " = " StrGet(NumGet(buf,"ptr"))
        exitapp
    }
}

global WebView2Environment                      := 0
global WebView2Controller                       := 0
global WebView2NavigationStartingEventArgs      := 0
global WebView2DocumentTitleChangedEventHandler := 0

global hWnd := 0,winParent := {},vtbl := [],CoreWebView2 := 0,HtmlSite := "",HtmlStr := "",ZoomFactor := 1.25 ; =125%
My example from the forum example, uses index.html,index.js, or the bing web site.

Code: Select all

#include WebView2.ahk

; try a web site (Navigate)
; HtmlSite := "https www.bing.com /"  Broken Link for safety

; try a local html file (Navigate)
HtmlSite := A_ScriptDir "/index.html"

win := Gui.New("+resize","Test WebView2")
win.OnEvent("Close","ExitApp")

Init_WebView2(win)

win.Show "w" A_ScreenWidth//2 " h" A_ScreenHeight//2

Esc::ExitApp
The next example uses "HtmlStr" (NavigateToString) for inline html,CSS,Javascript,whatever.
Edge will put in the basic Html tags for you.(html,head,etc.)

AHK needs to know when an element is Clicked. I created a Function called ClickEvents_WebView2,(see WebView2.ahk)
along with the Function On_Click. (see AHK prg.)

I used "add_DocumentTitleChanged" to trigger the Clicks.

Button Example (all javascript)

Code: Select all

#include WebView2.ahk
#include imagedata.ahk

On_Click(iClick){
    Switch(iClick){
        Case 1,2,3,4: MsgBox "Button " iClick " Clicked","Round Buttons","Iconi t2"
        Case 5,6,7: ExitApp
    }
}

HtmlStr := format("
(
    <body background="{1}" style="overflow:hidden">
    <img src="{2}" style="visibility:hidden">
    <script>
        function On_Click(num){
            document.title = num;
            // Reset Title For Same Click
            document.title = 0;
        }

        for(var i=1;i<6;i++){
            var rButton = document.createElement("button");
            if(i == 5){
                 rButton.textContent = "Over EXIT";
                 rButton.setAttribute("onmouseover","On_Click("+i+")");
            }else{
                rButton.textContent = "Button "+i;
                rButton.setAttribute("onclick","On_Click("+i+")");
                rButton.setAttribute("onmouseover","style.color='cyan';style.border='3px solid red';style.boxShadow='none';style.zIndex=1;style.transform='scale(1.3)';style.transition='all .4s'");
                rButton.setAttribute("onmouseout","style.color='yellow';style.border='none';style.boxShadow='1px 1px 30px white';style.zIndex=0;style.transform='scale(1.0)';style.transition='all .4s'");
            }
            rButton.style.left         = 5;
            rButton.style.top          = 5;
            rButton.style.width        = 60;
            rButton.style.height       = 60;
            rButton.style.position     = "relative";
            rButton.style.font         = "bold 12px arial";
            rButton.style.color        = "yellow";
            rButton.style.cursor       = "pointer";
            rButton.style.background   = "navy";
            rButton.style.border       = "none";
            rButton.style.outline      = "none";
            rButton.style.boxShadow    = "1px 1px 30px white";
            rButton.style.borderRadius = "35px";
            rButton.style.float        = "left";
            rButton.style.transition   = "all .2s";
            document.body.appendChild(rButton);
        }

        rButton = document.createElement("button");
        rButton.setAttribute("onclick","On_Click("+i+++")");
        rButton.setAttribute("onmouseover","style.color='yellow';style.boxShadow='none'");
        rButton.setAttribute("onmouseout","style.color='cyan';style.boxShadow='5px 5px 20px white'");
        rButton.textContent           = "Beam Me Up!";
        rButton.style.left            = 25;
        rButton.style.top             = 125;
        rButton.style.width           = 200;
        rButton.style.height          = 55;
        rButton.style.position        = "absolute";
        rButton.style.textDecoration  = "underline";
        rButton.style.backgroundImage = "linear-gradient(to left,blue,red)";
        rButton.style.font            = "bold 24px times new roman";
        rButton.style.color           = "cyan";
        rButton.style.cursor          = "pointer";
        rButton.style.borderStyle     = "none";
        rButton.style.outline         = "none";
        rButton.style.borderRadius    = "40px";
        rButton.style.boxShadow       = "5px 5px 20px white";
        rButton.style.transition      = "all .2s";
        document.body.appendChild(rButton);

        var img = document.getElementsByTagName("img")[0];
        img.style.visibility = 'visible';
        img.style.float      = "left";
        rButton.appendChild(img);

        rButton = document.createElement("button");
        rButton.setAttribute("onclick","On_Click("+i+")");
        rButton.setAttribute("onmouseover","style.color='yellow';style.boxShadow='1px 1px 30px white';style.border='3px solid red'");
        rButton.setAttribute("onmouseout","style.color='red';style.boxShadow='none';style.border='3px solid yellow'");
        rButton.textContent          = "I Quit!";
        rButton.style.left           = 185;
        rButton.style.top            = 230;
        rButton.style.width          = 100;
        rButton.style.height         = 40;
        rButton.style.position       = "absolute";
        rButton.style.textDecoration = "underline";
        rButton.style.font           = "bold 18px arial";
        rButton.style.color          = "red";
        rButton.style.cursor         = "pointer";
        rButton.style.background     = "blue";
        rButton.style.border         = "3px solid yellow";
        rButton.style.outline        = "none";
        rButton.style.borderRadius   = "10px";
        document.body.appendChild(rButton);
    </script>
)",steel,badge)

win := gui.new(,"WebView2 Button Testing")
win.OnEvent "Close",(*) => ExitApp()

Init_WebView2(win)

ClickEvents_WebView2

win.Show "w400 h400"

Esc::ExitApp
Hope this is helpful for any interested in WebView2 Control for Edge.
webview2.zip
(85.63 KiB) Downloaded 20 times
Last edited by xroot on 26 Sep 2020, 08:58, edited 1 time in total.
User avatar
kczx3
Posts: 1166
Joined: 06 Oct 2015, 21:39

Re: WebView2 Control For Edge

23 Sep 2020, 19:36

You do realize I posted a complete working example of this here, right?
https://www.autohotkey.com/boards/viewtopic.php?f=83&t=79868
xroot
Posts: 15
Joined: 21 Jun 2019, 08:45

Re: WebView2 Control For Edge

24 Sep 2020, 08:04

Yes, but it did not work for me, for some reason I do not know.
User avatar
kczx3
Posts: 1166
Joined: 06 Oct 2015, 21:39

Re: WebView2 Control For Edge

24 Sep 2020, 08:36

I’d be open to work with you to determine why it didn’t work. We’re you getting any errors?
xroot
Posts: 15
Joined: 21 Jun 2019, 08:45

Re: WebView2 Control For Edge

25 Sep 2020, 08:23

In your program I changed CreateCoreWebView2Environment to CreateCoreWebView2EnvironmentWithOptions and it works.
With CreateCoreWebView2Environment in your code I get Error 127 = The specified procedure could not be found.
Your codes say ERROR 80070002
User avatar
kczx3
Posts: 1166
Joined: 06 Oct 2015, 21:39

Re: WebView2 Control For Edge

25 Sep 2020, 09:08

Do you have at least the Beta Channel of Edge installed?
User avatar
kczx3
Posts: 1166
Joined: 06 Oct 2015, 21:39

Re: WebView2 Control For Edge

25 Sep 2020, 09:42

I was able to get it to work with both CreateCoreWebView2Environment and CreateCoreWebView2EnvironmentWithOptions. Using the WithOptions variation, I was able to pass both the normal Edge install path and the Beta Edge path and it worked for both. I think that you were getting that error with CreateCoreWebView2Environment because you don't have the Beta Channel installed and I think that it won't automatically use the normal channel.
xroot
Posts: 15
Joined: 21 Jun 2019, 08:45

Interact With Web Pages in WebView2

29 Sep 2020, 12:11

Added new functionality to WebView2.ahk.

1. WebView2NavigationCompletedEventHandler
2. WebView2ExecuteScriptCompletedHandler
3. jsCode Variable
4. ExecuteScript_WebView2 Fucntion

I wanted to see if I could Fade Out the Google Logo.

Fade Google Logo Example:

Code: Select all

#include WebView2.ahk

HtmlSite := "https www.google.com "  Broken Link for safety

jsCode := "
(
    function Sleep(ms){
        return new Promise(resolve => setTimeout(resolve,ms));
    }
    async function InterAct(){
        // Load jQuery
        var jq = document.createElement("script");
        jq.src = "https ajax.googleapis.com /ajax/libs/jquery/3.5.1/jquery.min.js";  Broken Link for safety
        document.head.appendChild(jq);

        // Load SweetAlert
        var msg = document.createElement("script");
        msg.src = "https unpkg.com /sweetalert/dist/sweetalert.min.js";  Broken Link for safety
        document.head.appendChild(msg);

        // Wait for jQuery & SweetAlert to Load
        await Sleep(500);

        // Show Cool MsgBox SweetAlert
        await swal("Watch Google Logo Fade Out...","jQuery Version = "+$.fn.jquery,"info");

        $("#hplogo").fadeOut(3000);
    }
    InterAct();
)"

win := Gui.new(,"WebView2 Fade Google Logo")
win.OnEvent "Close",(*) => ExitApp()

Init_WebView2(win)

ExecuteScript_WebView2

win.Show "w" A_ScreenWidth//2 " h" A_ScreenHeight//2

Esc::ExitApp
WebView2.zip
(1.94 KiB) Downloaded 9 times

Return to “AutoHotkey v2 Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 2 guests