Jump to content

Recommended Posts

  • Replies 45
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

I've made a library, based on AutoItObject UDF with the goal of implementing getter and setter functionality and make it possible to define new object properties in as few steps as possible. Than

version: 4.0.0 changes Most notable changes: speed and readability. When testing speed i found a minimum increase in speed by ~20%

version: 3.0.0 changes Most notable change: ROT¹ support! 🎊 ¹ Running Object Table

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 post
Share on other sites
Posted (edited)

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 post
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 post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By sylremo
      I tried to implement the code in this topic:
      Firstly, i have no idea how these lines of code work but meanwhile i noticed that:
      ; Everytime autoit wants to call a method, get or set a property in a object it needs to go to ; IDispatch::GetIDsFromNames. This is our version of that function, note that by defining this ourselves ; we can fool autoit to believe that the object supports a lot of different properties/methods. Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId) ... EndFunc The problem is i ran into is that some object calls didn't go through IDispatch::GetIDsFromNames.
      Here is the code to replicate what i'm mentioning:
      I followed the example in the topic and tried to do the same thing with method .Documents (line 193) and .Open (line 194) but didn't get the same result because .Documents was being passed through __IDispatch_GetIDsFromNames while .Open didn't.
      $Au3_CallByName = 'Documents' Local $oDoc = $oAppl.Au3_CallByName $Au3_CallByName = 'Open' $oDoc = $oDoc.Au3_CallByName($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat) Console outputs:
      ==> The requested action with this object has failed.: $oDoc = $oDoc.Au3_CallByName($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat) $oDoc = $oDoc^ ERROR Is there any workarounds to solve this?

      Thank you!
    • By SEuBo
      Hi there,
      while I created an example script to generate and execute a function during runtime, I stumbled across a neat way to share data between running autoit scripts.
      This is done using the amazing magic of  AutoItObject_Internal . (You'll need at least Version 3.0.0 of AutoItObject_Internal)
      Using this UDF, you can create a shared data storage, basically an empty "AutoitObject_Internal-"Object which you can then use to write / read data Inline. no set/get methods, just
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") $oShare.some_data = 'foo' and you're done. any other script accessing this data will have to do:
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") ConsoleWrite($oShare.some_data & @LF)  
      Basically it's Larsj's Implementing IRunningObjectTable Interface, but you dont have a Dictionary, but an IDIspatch Object instead.
      There are already a bunch of IPC options available - and this is another one.
      AutoItSharedData.au3
       
      Example Script 1
       
      Example Script 2
      Output: 
      To test: run Example Script 1, Then run example Script 2.. or the other way around.
      Example Script 3
      Example_sharedata3.au3
      Example_sharedata3_Controlsend.au3
      Example_sharedata3_Tooltip.au3
      To test: run Example_sharedata3.au3.
      Output: 
       
       Example SharedData4:
      Output: 
      /Edit: Please note that there's a limitation with the Running object table :
      The Script accessing a variable first, will be the "server" for this variable. This means, access to that variable from other scripts should only be possible, as long the "server" script is running! Use appropriate Object Error handlers in case you don't want the surviving "clients" to crash.
      Feedback and/or improvements appreciated
       
      changelog
      version 2.0
      Removed need for AutoItObject, as AutoItObject_Internal now comes with ROT support Added UDF Header Fixed typo on "#include AutoItObjectInternal.au3" -> "#include AutoItObject_Internal.au3" Added ObjGet() after registering the object fails (in case 2 programs tried to register the same ID simultaneously) Updated Examples & zip archive. Cheers,
       
      AutoItSharedData.zip
    • By nacerbaaziz
      hello autoit team
      please
      i tried to create a SPVoice object 
      when i create the object and tried to use this function SetAlertBoundary
      it gave me an error
      please where is the problem?
      here is the code
      local $o_Sapi_OBJ = ObjCreate("SAPI.SpVoice") if IsObj($o_Sapi_OBJ) then $o_Sapi_OBJ.SetAlertBoundary("SPEI_PHONEME") endIf note i got the function name from microsoft web site
       
      https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms719784(v=vs.85)
      i have windows10
    • By Colduction
      Hi AutoIt Programmers!

      I've seen a code that gives Name of Group by writing it's group's SID, but this one response very slower than Windows Command-Line WMIC
       
      Func _GetLocalGroupName($sSID = 'S-1-5-18') $objWMIService = ObjGet ("winmgmts:\\" & @ComputerName & "\root\cimv2") $colItems = $objWMIService.ExecQuery('SELECT Name FROM Win32_Group where SID="' & $sSID & '"') For $GroupNames in $colItems MsgBox (0,"",$GroupNames.Name) ExitLoop Next EndFunc I don't want call and use any third-party programs even CMD, i just want use from Windows API, netapi32.dll or AutoIt Functions (Standalone).
      Do you have any idea to improve speed/performance of this code? I'll happy of your comments
       
       
       
      ====================== SOLOUTION by @Subz ======================
       
    • By xiantez
      This script used to work on an older version of AutoIT. Currently I am running AutoIT v3.3.14.5 and it's failing.
      Func PublicIP() ;Post public facing IP address Local $url = 'https://www.google.com/search?client=opera&q=what+is+my+ip&sourceid=opera&ie=UTF-8&oe=UTF-8' Local $getIPaddress = BinaryToString(InetRead($url)) Local $sStart = 'clamp:2">' Local $sEnd = '</div>' Local $ipaddress = _StringBetween($getIPaddress, $sStart, $sEnd For $i In $ipaddress MsgBox(0, 'External IP', "Your public IP address is " & $i) Next EndFunc ;==>PublicIP The console output shows:
      "C:\Users\user\Documents\AutoIT\Scripts\WSI Tools.au3" (197) : ==> Variable must be of type "Object".: For $i In $ipaddress For $i In $ipaddress^ ERROR ->14:12:16 AutoIt3.exe ended.rc:1 +>14:12:16 AutoIt3Wrapper Finished. >Exit code: 1 Time: 9.811
×
×
  • Create New...