Jump to content

AutoItObject Pure AutoIt


genius257
 Share

Recommended Posts

Thanks for the update! Glad to speed you have made some speed improvements as that was holding me back from using this on a couple projects.

I've been wondering for a while now... Is it possible to create a GUI control AND assign the event handler "inside" of an object? I am trying to make a sort of button template which has extra properties and its own event handler when clicked. Unfortunately, I haven't found a way to make this work. I suspect it may not be possible due to internal AutoIt event handling expecting no function arguments, but I am interested to see if you had some sort of clever workaround/solution.

Here is a stripped down example of the idea. As it is, the click function is executed once when the object is created, but never on the actual click event.

#include "AutoItObject_Internal.au3"
#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)

Global $hGUI = GUICreate("MyGUI", 400, 350, 763, 317)
GUISetOnEvent($GUI_EVENT_CLOSE, "_onExitMain")

Global $Button_1 = _objButton("Button 1", 140, 100, 91, 41)
;~ GUICtrlSetOnEvent($Button_1.hwnd, _button1ClickEvent)

_main()

Func _main()
    GUISetState(@SW_SHOWNORMAL)

    While 1
        Sleep(100)
    WEnd
EndFunc   ;==>_main

;'traditional' event function
Func _button1ClickEvent()
    $Button_1.click()
EndFunc

Func _onExitMain()
    GUIDelete()
    Exit
EndFunc   ;==>_onExitMain

Func _objButton($sCaption, $iLeft, $iTop, $iWidth, $iHeight)
    Local $oIDispatch = IDispatch()

    $oIDispatch.caption = $sCaption
    $oIDispatch.hwnd = GUICtrlCreateButton($sCaption, $iLeft, $iTop, $iWidth, $iHeight)
    $oIDispatch.__defineGetter("click", _objButton_click)
    GUICtrlSetOnEvent($oIDispatch.hwnd, $oIDispatch.click)

    Return $oIDispatch
EndFunc

;event function built into the button object
Func _objButton_click($oSelf)
    ConsoleWrite("Click Caption: " & $oSelf.parent.caption & @CRLF)
EndFunc

 

Link to comment
Share on other sites

Hi @kurtykurtyboy :)

You are welcome :D Feedback always helps me know where to focus my efforts on a project ;)

 

So the most direct approach to your goal is not possible.

AutoIt3 only accepts user functions with it's event functions. I tried setting a getter on the main object and giving the object itself as the second argument to GUICtrlSetOnEvent, to no avail.

I did find a workaround though, let me know what you think :)

#include "AutoItObject_Internal.au3"
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>

Opt("GUIOnEventMode", 1)

Global $hGUI = GUICreate("MyGUI", 400, 350, 763, 317)
GUISetOnEvent($GUI_EVENT_CLOSE, "_onExitMain")

Global $Button_1 = _objButton("Button 1", 140, 100, 91, 41)
;~ GUICtrlSetOnEvent($Button_1.hwnd, _button1ClickEvent)

_main()

Func _main()
    GUISetState(@SW_SHOWNORMAL)

    While 1
        Sleep(100)
    WEnd
EndFunc   ;==>_main

;'traditional' event function
Func _button1ClickEvent()
    $Button_1.click()
EndFunc

Func _onExitMain()
    $Button_1 = 0
    GUIDelete()
    Exit
EndFunc   ;==>_onExitMain

Func _objButton($sCaption, $iLeft, $iTop, $iWidth, $iHeight)
    Local $oIDispatch = IDispatch()

    $oIDispatch.caption = $sCaption
    $oIDispatch.hwnd = GUICtrlCreateButton($sCaption, $iLeft, $iTop, $iWidth, $iHeight)
    ConsoleWrite($oIDispatch.hwnd&@CRLF)
    ;$oIDispatch.__defineGetter("click", _objButton_click)
    GUICtrlSetOnEvent($oIDispatch.hwnd, _objButton_click2)

    _WinAPI_SetProp(GUICtrlGetHandle($oIDispatch.hwnd), "IDispatch", Ptr($oIDispatch))

    Return $oIDispatch
EndFunc

;event function built into the button object
Func _objButton_click($oSelf)
    ConsoleWrite("Click Caption: " & $oSelf.parent.caption & @CRLF)
EndFunc

;event function for the button object
Func _objButton_click2()
    $pIDispatch = _WinAPI_GetProp(@GUI_CtrlHandle, "IDispatch"); Retrive IDispatch pointer
    If $pIDispatch = 0 Then Return; Pointer not available, return from function
    Local $oIDispatch = ObjCreateInterface($pIDispatch, $__AOI_IID_IDispatch, Default, True); Convert pointer back to object
    __AOI_AddRef($pIDispatch);When using ObjCreateInterface multiple times on the same ptr, AutoIt3 seems to not AddRef +1 (or it may be a bug in AutoItObject_Internal)
    ConsoleWrite("Click Caption: " & $oIDispatch.caption & @CRLF)
EndFunc

;From https://www.autoitscript.com/forum/topic/207492-help-needed-image-viewer-with-zoom-and-translate/
Func _WinAPI_SetProp($hWnd, $sProp, $pData)
    Return DllCall("user32.dll", "bool", "SetPropW", "hwnd", $hWnd, "wstr", $sProp, "ptr", $pData)[0]
EndFunc

;From https://www.autoitscript.com/forum/topic/207492-help-needed-image-viewer-with-zoom-and-translate/
Func _WinAPI_GetProp($hWnd, $sProp)
    Return DllCall("user32.dll", "ptr", "GetPropW", "hwnd", $hWnd, "wstr", $sProp)[0]
EndFunc

I did originally try to use _WinAPI_SetWindowLong with $GWL_USERDATA, but it seems AutoIt3 uses that itself 😡

edit:

you COULD call $oIDispatch.click() within _objButton_click2, if you want custom functions associated with the click getter.

Edited by genius257
Link to comment
Share on other sites

Thanks @genius257

That is indeed a clever solution! I had never thought of using window properties..
My previous working solution involved passing the parent object to the event handler to keep as a static variable and then looping through all the controls on each event to find the one that was clicked. Your solution should speed things up tremendously.

Link to comment
Share on other sites

version: 4.0.1

changes

  • Fixed crash when creating too many objects (f86a0c4)
  • Fixed could not modify the default object method property $oIDispatch() (58fa551)
Link to comment
Share on other sites

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
 Share

×
×
  • Create New...