ahk2_lib

repository·master·Indexed 19 days ago

https://github.com/thqby/ahk2_lib

A collection of AutoHotkey v2 libraries providing wrappers for Microsoft Edge WebView2, LibXL for Excel manipulation, YOLOX for object detection, and wincapture for screen capture via DXGI, DWM, and WGC. It also includes NTLCalc for arbitrary-length integer arithmetic and a Detours wrapper for monitoring and instrumenting Windows API calls.

Tokens
4.2K
Snippets
9
Records
11
Agent score
67%

What's inside ahk2_lib

  1. How WebView2 API conversion works in AHK

    master

    The ahk2_lib implementation of WebView2 follows specific conversion patterns for AutoHotkey:

    • Asynchronous Methods: Methods that are asynchronous in the original API are suffixed with Async (e.g., ExecuteScriptAsync). These methods return a Promise object, which can be used with .await2() to wait for completion.
    • Event Handlers: The add_event method accepts an AHK callable object with at least two parameters. The registration object includes a .event method which, when the object is destructed, automatically cancels the event registration.
  2. Choose a window capture method in wincapture

    master

    The wincapture library provides three distinct capture technologies depending on your requirements for performance, target (window vs. monitor), and OS compatibility:

    1. DXGI: Uses DXGI desktop duplication. It is suitable for high-performance screen capture and supports multi-threaded use. Note that only one instance can exist per process.
    2. DWM: Uses DwmGetDxSharedSurface. This is designed for capturing specific windows. It supports background windows (as long as they are not minimized), though some specific windows may not be compatible.
    3. WGC: Uses Windows.Graphics.Capture via winrt. This supports both window and monitor capture and works with background windows (excluding minimized ones). Requirement: Windows 10 version 1903 or higher.
  3. Use YOLOX for object detection

    master

    YOLOX is an anchor-free version of YOLO designed for high performance. To use it within this library, you must initialize the Yolo module and provide an ONNX model file. The detect method can process images via BitmapBuffer objects, raw binary data, or file paths.

    #Include <Yolo\yolo>
    #Include <wincapture\wincapture>
    
    ; Initialize Yolo with the directory containing required dependencies (e.g., onnxruntime)
    Yolo.init(A_ScriptDir)
    
    ; Create a Yolo instance
    ; Syntax: Yolo(type, model_path, class_names_string)
    ; type: 'x' for YOLOX
    yy := Yolo('x', 'yolox.onnx', '1`n2`n3`n4`n5')
    
    ; Load an image using BitmapBuffer
    tu := BitmapBuffer.loadPicture('car.jpg')
    
    ; Perform detection
    ; r contains the detection results
    r := yy.detect(tu.info, -1, , , , , 'dst')
  4. Use Detours to monitor and instrument Windows API calls

    master

    Detours is a software package used for monitoring and instrumenting API calls on Windows. In this library, you can use it to intercept standard Windows functions (like MessageBoxW) and redirect them to a custom AutoHotkey callback.

    To use Detours in AutoHotkey:

    1. Include Detours.ahk.
    2. Load Detours.dll using DllCall('LoadLibrary', ...).
    3. Use DetourFindFunction to locate the address of the original function.
    4. Create a callback using CallbackCreate for your replacement function.
    5. Wrap the attachment process in a transaction using DetourTransactionBegin, DetourUpdateThread, DetourAttach, and DetourTransactionCommit.
    #Include 'Detours.ahk'
    
    ; Load the Detours DLL
    DllCall('LoadLibrary', 'str', (A_PtrSize * 8) 'bit\Detours.dll')
    
    g_Thread := DllCall('GetCurrentThread')
    
    ; Find the original function address
    old_msg := DetourFindFunction('user32.dll', 'MessageBoxW')
    
    ; Create a callback for the new function
    new_msg := CallbackCreate(_msg)
    
    ; Perform the detour transaction
    r := DetourTransactionBegin()
    r := DetourUpdateThread(g_Thread)
    r := DetourAttach(old_msg, new_msg)
    r := DetourTransactionCommit()
    
    MsgBox('csrer')
    
    ; The replacement function
    _msg(hwnd, text, caption, opt) {
    	DllCall(old_msg.value, 'ptr', 0, 'str', 'dvdftre', 'str', 'zvcrte', 'uint', 0)
    }
  5. Evaluate mathematical expressions with NTLCalc

    master

    The NTLCalc function is a wrapper for the NTL (Number Theory Library) designed to evaluate integer and floating-point mathematical expressions. It provides high-performance, arbitrary-length integer arithmetic, which can be used to avoid the precision limitations of standard floating-point math in AutoHotkey for specific calculations.

    ; Example: Floating-point expression evaluation
    MsgBox('0.1+0.7*0.3/0.5+0.3=' NTLCalc('0.1+0.7*0.3/0.5+0.3'))
    
    ; Example: Arbitrary-length integer multiplication
    MsgBox('99999999999999999999999911111111111111111111111*111111111111111111111111=' NTLCalc('99999999999999999999999911111111111111111111111*111111111111111111111111'))
  6. Handle New Window Requests in WebView2

    master

    When a web page requests to open a new window (e.g., clicking a link with target="_blank"), you can intercept this using the NewWindowRequested event. You can either redirect the request to a new tab in your own application or force it to open in the existing WebView2 instance.

    To force a new window request to open in the current WebView2 instance:

    1. Register a handler with wv.NewWindowRequested(HandlerFunction).
    2. In the handler, use arg.GetDeferral() to manage the asynchronous nature of the request.
    3. Assign the existing WebView2 instance to arg.NewWindow.
    4. Call deferral.Complete().
    #Include <WebView2\WebView2>
    
    main := Gui()
    main.OnEvent('Close', (*) => ExitApp())
    main.Show(Format('w{} h{}', A_ScreenWidth * 0.6, A_ScreenHeight * 0.6))
    
    wvc := WebView2.CreateControllerAsync(main.Hwnd).await2()
    wv := wvc.CoreWebView2
    nwr := wv.NewWindowRequested(NewWindowRequestedHandler)
    wv.Navigate('https://autohotkey.com')
    
    NewWindowRequestedHandler(wv2, arg) {
    	deferral := arg.GetDeferral()
    	arg.NewWindow := wv2
    	deferral.Complete()
    }
  7. Perform screen capture and image processing with wincapture

    master

    You can use the wincapture library to capture screens, wait for specific changes, and perform advanced image analysis like finding colors or pictures using a BitmapBuffer.

    Capture and Save

    Use captureAndSave() to capture the screen. You can pass a Buffer to define a specific capture range (x, y, width, height).

    Waiting for Changes

    waitScreenChange(timeout, box) allows you to pause execution until a specific region (defined by a box buffer) changes on the screen.

    Image Analysis with BitmapBuffer

    When capturing via callback, you receive raw pixel data which can be wrapped in a BitmapBuffer to perform:

    • findPic(&x, &y, picture): Search for a specific image.
    • findColor(&x, &y, color): Search for a specific pixel color.
    • findMultiColors(&x, &y, array): Search for a specific combination of multiple pixel colors and offsets.
    ; Initialize DXGI capture
    dxcp := wincapture.DXGI()
    
    ; Define a capture range (x, y, x2, y2)
    box := Buffer(16, 0)
    NumPut("uint", 0, "uint", 0, "uint", 500, "uint", 500, box)
    
    ; Wait up to 15 seconds for the screen area to change
    if dxcp.waitScreenChange(15000, box)
        MsgBox "Screen changed!"
    
    ; Capture and save to file
    dxcp.captureAndSave(box).save('capture.bmp')
    
    ; Capture via callback for real-time processing
    cb := CallbackCreate(MyCallback)
    dxcp.capture(cb)
    
    MyCallback(pdata, pitch, sw, sh, tick) {
        if tick && pdata {
            bb := BitmapBuffer(pdata, pitch, sw, sh)
            
            ; Example: Find a specific color
            targetColor := 0xFF0000
            if bb.findColor(&x, &y, targetColor)
                MsgBox "Found color at " x "," y
                
            ; Example: Find a picture
            pic := BitmapBuffer.loadPicture("template.bmp")
            if bb.findPic(&x, &y, pic)
                MsgBox "Found picture at " x "," y
        }
    }
  8. Use LibXL via the XL library

    master

    The XL library provides a high-performance interface for reading and writing Excel files (.xls, .xlsx) using the LibXL engine.

    To use it, include the library using #Include <XL\XL>. You can create new workbooks, manage sheets, handle rich text formatting, and manipulate cell values, formulas, and styles.

    #Include <XL\XL>
    
    ; Create a new XLSX workbook and add a sheet
    book := XL.New('xlsx'), sheet := book.addSheet('test')
    
    ; Set calculation mode and create rich text
    book.setCalcMode(0), rs := book.addRichString()
    
    ; Configure fonts for rich text segments
    ft1 := rs.addFont(), ft1.setColor(10), ft1.setSize(24)
    ft2 := rs.addFont(), ft2.setSize(24)
    
    ; Add text segments with specific fonts to the rich string
    rs.addText('E', ft1), rs.addText('=', ft2)
    
    ; Assign rich text to a cell
    sheet['D6'] := rs
    
    ; Write values, formulas, and booleans
    sheet['a1'] := {bool: false}
    sheet['b2'] := {expr: '3*4+2'}
    sheet['b4'] := {expr: '9*4', value: 36}
    
    ; Save the workbook
    book.save('test.xlsx')
  9. Expose AutoHotkey objects to WebView2 via AddHostObjectToScript

    master

    You can bridge AutoHotkey and JavaScript by using AddHostObjectToScript. This allows JavaScript running inside the WebView2 control to call AutoHotkey functions and access properties.

    To access the host object in JavaScript:

    • Use window.chrome.webview.hostObjects.YOUR_NAME for synchronous access.
    • Use window.chrome.webview.hostObjects.sync.YOUR_NAME for asynchronous access (where properties/methods return Promises).

    Example setup:

    #Include <WebView2\WebView2>
    
    main := Gui()
    main.Show()
    
    wvc := WebView2.CreateControllerAsync(main.Hwnd).await2()
    wv := wvc.CoreWebView2
    
    ; Expose an object named 'ahk' to the web content
    wv.AddHostObjectToScript('ahk', {str:'str from ahk', func:MsgBox})

    Corresponding JavaScript in Edge DevTools:

    // Asynchronous access
    obj = await window.chrome.webview.hostObjects.ahk;
    obj.func('call from edge\n' + (await obj.str));
    
    // Synchronous access
    obj = window.chrome.webview.hostObjects.sync.ahk;
    obj.func('call from edge\n' + obj.str);
    #Include <WebView2\WebView2>
    
    main := Gui()
    main.OnEvent('Close', (*) => (wvc := wv := 0))
    main.Show(Format('w{} h{}', A_ScreenWidth * 0.6, A_ScreenHeight * 0.6))
    
    wvc := WebView2.CreateControllerAsync(main.Hwnd).await2()
    wv := wvc.CoreWebView2
    wv.Navigate('https://autohotkey.com')
    wv.AddHostObjectToScript('ahk', {str:'str from ahk',func:MsgBox})
    wv.OpenDevToolsWindow()
  10. Manipulate cells and formulas in XL

    master

    The XL library allows for flexible cell manipulation using several patterns:

    • Direct Value Assignment: Use sheet['A1'] := value or sheet[row, col] := value.
    • Formulas: Use an object with the expr key to define a formula: {expr: 'formula_string'}. You can also provide a pre-calculated value alongside the expression: {expr: '9*4', value: 36}.
    • Booleans: Use {bool: true} or {bool: false}.
    • Rich Text: Use book.addRichString() to create a string with multiple font styles and assign it to a cell.
    • Cell Properties: You can access and modify properties like .width on a cell object.
    • Reading Content: Access cell values via .value and formula content via .content.formula.
    ; Writing a formula
    sheet['b2'] := {expr: '3*4+2'}
    
    ; Writing a value with a specific format
    ft := book.addFormat(), ft.setNumFormat(14)
    sheet['c8'] := {value: book.datePack(2010, 3, 11, 10, 25, 55), format: ft}
    
    ; Reading values and formulas
    msgbox 'K2 Cell value:' sheet['k2'].value
    msgbox 'B2 Cell formula:' sheet['b2'].content.formula
  11. Print WebView2 content to PDF

    master

    You can export the current web content to a PDF file using PrintToPdfAsync. This requires creating print settings via the WebView2 environment.

    Steps:

    1. Access the Environment from the CoreWebView2 object.
    2. Call CreatePrintSettings() to get a settings object.
    3. Configure settings like Orientation (e.g., WebView2.PRINT_ORIENTATION.LANDSCAPE).
    4. Call wv.PrintToPdfAsync(path, settings) and .await2() the result.

    Note: Ensure the web content has finished loading before attempting to print.

    #Include <WebView2\WebView2>
    
    main := Gui()
    main.Show('w800 h600')
    wvc := WebView2.CreateControllerAsync(main.Hwnd).await2()
    wv := wvc.CoreWebView2
    wv.Navigate('https://autohotkey.com')
    MsgBox('Wait for loading to complete')
    PrintToPdf(wv, A_ScriptDir '\11.pdf')
    
    PrintToPdf(wv, path) {
    	set := wv.Environment.CreatePrintSettings()
    	set.Orientation := WebView2.PRINT_ORIENTATION.LANDSCAPE
    	waitting := true, t := A_TickCount
    	try {
    		wv.PrintToPdfAsync(A_ScriptDir '\11.pdf', set).await2(5000)
    		Run(A_ScriptDir '\11.pdf')
    		MsgBox('PrintToPdf complete')
    	} catch TimeoutError
    		MsgBox('PrintToPdf timeout')
    }