Jump to content

WebView2AutoIt - AutoIt WebView2 Component (COM Interop)


Recommended Posts

Posted (edited)

WebView2AutoIt

AutoIt WebView2 Component (COM Interop)

Integrating WebView2 into AutoIt has proven to be somewhat complicated.
To simplify this process, I decided to create a COM object in C# that serves as a bridge for AutoIt, facilitating the interaction.
I must admit that I have no prior experience in this area, but I am eager to learn and am open to any comments or suggestions.
I am sharing this project publicly, in the hope that it can be improved over time to fill this notable gap left by Internet Explorer.

In today's rapidly evolving technological landscape, AutoIt - it is my vehicle - needs to evolve and be always on the go,
allowing for the integration of advanced functionality into AutoIt scripts. 
So new rims and tires
 

Purpose of this project
WebView2, based on Chromium, offers fast and secure web browsing capabilities, unlocking new opportunities for applications that desire a modern look and functionality.
As an AutoIt user, I have the desire to be able to integrate these features directly into my scripts.
 

The Approach: Creating a COM Bridge
The idea was simple but ambitious: develop a C# library that acts as an intermediary between AutoIt and WebView2.
Using COM (Component Object Model), I created an object that allows calling AutoIt functions from JavaScript code in WebView2 and vice versa.
 

This project enables you to render modern HTML5, CSS3, and JavaScript directly inside your AutoIt applications.

251222-164409-534_AutoIt3_zn0wY.png.d02f7dbbb6d0e5357a235dfd36119f24.png

Html_Gui.au3

;~ #AutoIt3Wrapper_UseX64=y
; Html_Gui.au3
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>

; Global objects
Global $oManager, $oBridge
Global $oEvtManager, $oEvtBridge

; Global error handler for COM objects
Global $oMyError = ObjEvent("AutoIt.Error", "_ErrFunc")

; Global variables for data management
Global $aMessages[0][3]
Global $sFilePath = @ScriptDir & "\messages.csv"
Global $hGUI

Main()

Func Main()
    ; Create GUI with resizing support
    $hGUI = GUICreate("WebView2 Theme Switcher", 500, 450, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN))
    GUISetBkColor(0x1E1E1E)

    Local $idBlue = GUICtrlCreateLabel("Blue Theme", 10, 10, 100, 30)
    GUICtrlSetFont(-1, 12, Default, $GUI_FONTUNDER, "Segoe UI")
    GUICtrlSetColor(-1, 0x0078D7)

    Local $idRed = GUICtrlCreateLabel("Red Theme", 120, 10, 100, 30)
    GUICtrlSetFont(-1, 12, Default, $GUI_FONTUNDER, "Segoe UI")
    GUICtrlSetColor(-1, 0xFF0000)

    ; Get the WebView2 Manager object and register events
    $oManager = ObjCreate("NetWebView2.Manager")
    $oEvtManager = ObjEvent($oManager, "Manager_", "IWebViewEvents")

    ; Get the bridge object and register events
    $oBridge = $oManager.GetBridge()
    $oEvtBridge = ObjEvent($oBridge, "Bridge_", "IBridgeEvents")

    ; ⚠️ Important: Enclose ($hGUI) in parentheses to force "Pass-by-Value".
    ; This prevents the COM layer from changing the AutoIt variable type from Ptr to Int64.
    $oManager.Initialize(($hGUI), "", 0, 50, 500, 400)

    ; Register the WM_SIZE message to handle window resizing
    GUIRegisterMsg($WM_SIZE, "WM_SIZE")

    ;GUISetState(@SW_SHOW)

    ; Main Application Loop
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                $oManager.Cleanup()
                Exit

            Case $idBlue
                ; Update CSS variables dynamically via JavaScript
                $oManager.ExecuteScript("document.documentElement.style.setProperty('--accent-color', '#4db8ff');")
                $oManager.ExecuteScript("document.documentElement.style.setProperty('--btn-color', '#0078d7');")

            Case $idRed
                ; Update CSS variables dynamically via JavaScript
                $oManager.ExecuteScript("document.documentElement.style.setProperty('--accent-color', '#ff4d4d');")
                $oManager.ExecuteScript("document.documentElement.style.setProperty('--btn-color', '#d70000');")
        EndSwitch
    WEnd

EndFunc   ;==>Main

; Handles data received from the WebView2 Manager
Func Manager_OnMessageReceived($sMessage)
    Local Static $bIsInitialized = False
    If $sMessage = "INIT_READY" And Not $bIsInitialized Then
        $bIsInitialized = True ; We note that we are finished.
        Local $sHTML = "<html><head><meta charset='UTF-8'>" & _FormCSS() & "</head><body>" & _FormHTML() & "</body></html>"
        $oManager.NavigateToString($sHTML)
        GUISetState(@SW_SHOW, $hGUI)
    EndIf
EndFunc   ;==>Manager_OnMessageReceived

; Handles data received from the JavaScript 'postMessage'
Func Bridge_OnMessageReceived($sMessage)
    ConsoleWrite("$sMessage=" & $sMessage & @CRLF)

    ; Check for the specific form submission prefix
    If StringLeft($sMessage, 12) = "SUBMIT_FORM:" Then
        ; Extract the JSON portion from the message
        Local $sJsonRaw = StringTrimLeft($sMessage, 12)
        Local $oJson = ObjCreate("NetJson.Parser")

        ; Parse the raw JSON string
        If $oJson.Parse($sJsonRaw) Then
            ; Extract values using their JSON keys
            Local $sName = $oJson.GetTokenValue("name")
            Local $sEmail = $oJson.GetTokenValue("email")
            Local $sMsg = $oJson.GetTokenValue("message")

            If $sName <> "" And $sEmail <> "" Then
                ; Add data to global array for internal tracking
                _ArrayAdd($aMessages, $sName & "|" & $sEmail & "|" & $sMsg)

                ; Append data to CSV file safely
                Local $hFile = FileOpen($sFilePath, 9) ; 1 (Write) + 8 (Create Path)
                If $hFile <> -1 Then
                    ; Clean the message string for CSV compatibility (remove line breaks)
                    Local $sCleanMsg = StringReplace($sMsg, @CRLF, " ")
                    FileWriteLine($hFile, $sName & "," & $sEmail & "," & $sCleanMsg)
                    FileClose($hFile)
                EndIf

                ShowWebNotification("Data Saved Successfully!")
            Else
                ; Trigger a visual notification inside the WebView
                ShowWebNotification("Please enter valid data", '#d70000')
            EndIf
        EndIf
    EndIf
EndFunc   ;==>Bridge_OnMessageReceived

; Generates the CSS block with dynamic variables
Func _FormCSS()
    Local $sTxt = "<style>" & @CRLF & _
            ":root {" & @CRLF & _
            "  --bg-color: #1e1e1e; --form-bg: #2d2d2d;" & @CRLF & _
            "  --accent-color: #4db8ff; --btn-color: #0078d7; --txt-color: #e0e0e0;" & @CRLF & _
            "}" & @CRLF & _
            "body { background-color: var(--bg-color); color: var(--txt-color); font-family: 'Segoe UI', sans-serif; padding: 20px; margin: 0; }" & @CRLF & _
            "#contactForm { max-width: 400px; background-color: var(--form-bg); padding: 20px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); }" & @CRLF & _
            "label { display: block; margin-bottom: 5px; font-weight: bold; color: var(--accent-color); }" & @CRLF & _
            "input, textarea { width: 100%; padding: 10px; background-color: #3d3d3d; border: 1px solid #555; border-radius: 4px; color: #fff; box-sizing: border-box; margin-bottom: 15px; }" & @CRLF & _
            "button { background-color: var(--btn-color); color: white; border: none; padding: 12px 20px; border-radius: 4px; cursor: pointer; width: 100%; font-size: 16px; }" & @CRLF & _
            "</style>"
    Return $sTxt
EndFunc   ;==>_FormCSS

; Generates the HTML form and JavaScript logic
Func _FormHTML()
    Local $sTxt = "<form id='contactForm'>" & @CRLF & _
            "  <label>Name:</label><input type='text' id='name'>" & @CRLF & _
            "  <label>Email:</label><input type='email' id='mail'>" & @CRLF & _
            "  <label>Message:</label><textarea id='msg'></textarea>" & @CRLF & _
            "  <button type='button' onclick='submitToAutoIt()'>Send Message</button>" & @CRLF & _
            "</form>" & @CRLF & _
            "<script>" & @CRLF & _
            "  function submitToAutoIt() {" & @CRLF & _
            "    const formData = {" & @CRLF & _
            "      name: document.getElementById('name').value," & @CRLF & _
            "      email: document.getElementById('mail').value," & @CRLF & _
            "      message: document.getElementById('msg').value" & @CRLF & _
            "    };" & @CRLF & _
            "    " & @CRLF & _
            "    // postMessage to autoit" & @CRLF & _
            "    window.chrome.webview.postMessage('SUBMIT_FORM:' + JSON.stringify(formData));" & @CRLF & _
            "    " & @CRLF & _
            "    document.getElementById('contactForm').reset();" & @CRLF & _
            "  }" & @CRLF & _
            "</script>"
    Return $sTxt
EndFunc   ;==>_FormHTML

; Injects a temporary notification box into the web page
Func ShowWebNotification($sMessage, $sBgColor = "#4CAF50", $iDuration = 3000)
    ; We use a unique ID 'autoit-notification' to find and replace existing alerts
    Local $sJS = _
            "var oldDiv = document.getElementById('autoit-notification');" & _
            "if (oldDiv) { oldDiv.remove(); }" & _
            "var div = document.createElement('div');" & _
            "div.id = 'autoit-notification';" & _ ; Assign the ID
            "div.style = 'position:fixed; top:20px; left:50%; transform:translateX(-50%); padding:15px; background:" & $sBgColor & _
            "; color:white; border-radius:8px; z-index:9999; font-family:sans-serif; box-shadow: 0 4px 6px rgba(0,0,0,0.2); transition: opacity 0.5s;';" & _
            "div.innerText = '" & $sMessage & "';" & _
            "document.body.appendChild(div);" & _
            "setTimeout(() => {" & _
            "   var target = document.getElementById('autoit-notification');" & _
            "   if(target) { target.style.opacity = '0'; setTimeout(() => target.remove(), 500); }" & _
            "}, " & $iDuration & ");"

    $oManager.ExecuteScript($sJS)
EndFunc   ;==>ShowWebNotification

; Synchronizes WebView size with the GUI window
Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam)
    If $wParam = 1 Then Return $GUI_RUNDEFMSG
    Local $iW = BitAND($lParam, 0xFFFF), $iH = BitShift($lParam, 16) - 50
    If IsObj($oManager) Then $oManager.Resize(($iW < 10 ? 10 : $iW), ($iH < 10 ? 10 : $iH))
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_SIZE

; User's COM error function. Will be called if COM error occurs
Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc

 

:idea:  I hope someone with more knowledge
can shed some light on the thread.

 

WebView2AutoIt_v0.1.zip

 

Please, every comment is appreciated!
leave your comments and experiences here!
Thank you very much  :)

Edited by ioa747

I know that I know nothing

Posted
27 minutes ago, ioa747 said:

This project enables you to render modern HTML5, CSS3, and JavaScript directly inside your AutoIt applications.

---------------------------
Error
---------------------------
Could not create WebView2 Manager. Please register the DLL.
---------------------------
OK
---------------------------

😭

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

:lol:  There are two ways
either you will load "NetWebView2\WebView2AutoIt_v0.1\NetWebView2Lib\NetWebView2Lib.sln"
into Visual Studio and build
or you will run "\WebView2AutoIt_v0.1\NetWebView2Lib\WebView2AutoIt\register_web2.au3"

ah! there is also a "WebView2AutoIt_v0.1\README.md"

Edited by ioa747

I know that I know nothing

Posted

If MsgBox(36, "Confirm", "Exit Application?", 0, $hGUI) = 6 Then Exit  is better because it will disable the GUI while MsgBox() is active.

Is there a way to do all these without registering a DLL ?
- I hope someone with more knowledge can shed some light on the thread.
Ok, but, it would be nicer, even if not better than this way.

Thanks for the code :) 
 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Nice thanks.

Will look into it, hope in next 2 month. My january schedule is full as always from 20years.

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 *

 

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE * IE on Windows 11

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...