Page 1 of 1

WebView2 Control For Edge

Posted: 23 Sep 2020, 13:00
by xroot
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 27 times

Re: WebView2 Control For Edge

Posted: 23 Sep 2020, 19:36
by kczx3
You do realize I posted a complete working example of this here, right?
https://www.autohotkey.com/boards/viewtopic.php?f=83&t=79868

Re: WebView2 Control For Edge

Posted: 24 Sep 2020, 08:04
by xroot
Yes, but it did not work for me, for some reason I do not know.

Re: WebView2 Control For Edge

Posted: 24 Sep 2020, 08:36
by kczx3
I’d be open to work with you to determine why it didn’t work. We’re you getting any errors?

Re: WebView2 Control For Edge

Posted: 25 Sep 2020, 08:23
by xroot
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

Re: WebView2 Control For Edge

Posted: 25 Sep 2020, 09:08
by kczx3
Do you have at least the Beta Channel of Edge installed?

Re: WebView2 Control For Edge

Posted: 25 Sep 2020, 09:42
by kczx3
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.

Interact With Web Pages in WebView2

Posted: 29 Sep 2020, 12:11
by xroot
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 17 times