trancexx Posted January 13, 2013 Posted January 13, 2013 Oh my! You know that game - show me yours, I'll show you mine? You saw mine, you turn now. ...go on, don't be shy. ♡♡♡ . eMyvnE
AdmiralAlkex Posted January 13, 2013 Posted January 13, 2013 I think that's enough edits. Jon disallowed exe-files so I'm only attaching the zip.Try this version D4RKON3.AutoItObject 1.2.8.3.zip jaberwacky 1 .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
AdmiralAlkex Posted January 13, 2013 Posted January 13, 2013 Oh my!You know that game - show me yours, I'll show you mine? You saw mine, you turn now....go on, don't be shy.It used to be private. Something that only me and my closest friends could comprehend. Then my forum-persona took over.C:\Users\Admiral\autoitobject\trunk .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
trancexx Posted January 13, 2013 Posted January 13, 2013 It used to be private. Something that only me and my closest friends could comprehend. Then my forum-persona took over.C:UsersAdmiralautoitobjecttrunk And that's it? It's not as big as I expected. AdmiralAlkex 1 ♡♡♡ . eMyvnE
FaridAgl Posted January 13, 2013 Posted January 13, 2013 @AdmiralAlkex Well done. AdmiralAlkex 1 http://faridaghili.ir
AdmiralAlkex Posted January 14, 2013 Posted January 14, 2013 And that's it? It's not as big as I expected. .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
trancexx Posted January 14, 2013 Posted January 14, 2013 Whatever you say Reverend Admiral. ♡♡♡ . eMyvnE
MachinistProgrammer Posted March 3, 2013 Posted March 3, 2013 what are the com objects for autoit e.g. autoit.error All my projects live on github
eimhym Posted March 18, 2013 Posted March 18, 2013 Hi, I've made a little test if we can register AutoItObject into ROT. For in-process server it works fine, the AutoItObject returned by _GetActiveObject is the one registered via _RegisterActiveObject. But, invoked via out-of-process, it crash! If you compare the output of inProc vs outProc - with IUnknown debugger turned on - you can see the problem start when external process invoking QueryInterface for IDispatch. A pointer returned, but then it seems OLE stop working, cuz Release never arrived (though successfully invoked). Ain't the default marshaler should handle IDispatch automatically? I hope we can do it proxy-stub-less, if the problem is TypeLib, well I can't find any TLB in AutoItObject.dll Here's the test code, set $OutOfProcessTest and $IUnknownDebugger to alter the test. They are initially set for debugged in-process test: expandcollapse popupGlobal Const $OutOfProcessTest = False ; TRUE = out-of-process, FALSE = in-process Global Const $IUnknownDebugger = True ; TRUE = use IUnknown stub, FALSE = pass AutoItObject directly #include "WinAPI.au3" #include "AutoItObject.au3" _AutoItObject_Startup() Global $_ActiveObject, $_pActiveObject, _ $_tActiveObject_Factory = DllStructCreate("ptr;" & _ "ptr QueryInterface;" & _ "ptr AddRef;" & _ "ptr Release" ), _ $_ActiveObject_Factory = DllStructGetPtr($_tActiveObject_Factory), _ $_ActiveObject_QueryInterface = DllCallbackRegister("_ActiveObject_QueryInterface", "INT", "ptr;ptr;ptr"), _ $_ActiveObject_AddRef = DllCallbackRegister("_ActiveObject_AddRef", "ULONG", "ptr"), _ $_ActiveObject_Release = DllCallbackRegister("_ActiveObject_Release", "ULONG", "ptr"), _ $_SizeOfPtr = DllStructGetSize(DllStructCreate('ptr')) DllStructSetData($_tActiveObject_Factory, 1, $_ActiveObject_Factory + $_SizeOfPtr) DllStructSetData($_tActiveObject_Factory, 'QueryInterface', DllCallbackGetPtr($_ActiveObject_QueryInterface)) DllStructSetData($_tActiveObject_Factory, 'AddRef', DllCallbackGetPtr($_ActiveObject_AddRef)) DllStructSetData($_tActiveObject_Factory, 'Release', DllCallbackGetPtr($_ActiveObject_Release)) #Region >>> Win32 ActiveObject API #cs HRESULT CoLockObjectExternal( _In_ LPUNKNOWN pUnk, _In_ BOOL fLock, _In_ BOOL fLastUnlockReleases ); Ole32.dll #ce Func _CoLockObjectExternal ( $pIUnknown, $fLock, $fLastUnlockReleases ) $aCall = DllCall('Ole32.DLL', 'INT', 'CoLockObjectExternal', _ 'ptr', $pIUnknown, _ 'bool', $fLock, _ 'bool', $fLastUnlockReleases ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) EndFunc #cs HRESULT RegisterActiveObject( IUnknown *punk, REFCLSID rclsid, DWORD dwFlags, // ACTIVEOBJECT_STRONG 0 // ACTIVEOBJECT_WEAK 1 DWORD *pdwRegister ); OleAut32.dll #ce Func _RegisterActiveObject ( ByRef $_IDispatch, $sGUID ) $tGUID = _GuidFromString($sGUID) $tHandle = DllStructCreate('dword') If $IUnknownDebugger Then $pIUnknown = $_ActiveObject_Factory Else $pIUnknown = _AutoItObject_IDispatchToPtr($_IDispatch) EndIf $aCall = DllCall('OleAut32.DLL', 'INT', 'RegisterActiveObject', _ 'ptr', $pIUnknown, _ 'ptr', DllStructGetPtr($tGUID), _ 'dword', 0x0, _ 'ptr', DllStructGetPtr($tHandle) ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) If NOT $IUnknownDebugger Then _CoLockObjectExternal($pIUnknown, True, True) If @error Then Return SetError(2, @extended, 0) EndIf _Log( "_RegisterActiveObject: " & $pIUnknown & " " & $sGUID ) Return DllStructGetData($tHandle, 1) EndFunc #cs HRESULT GetActiveObject( _In_ REFCLSID rclsid, _Reserved_ void *pvReserved, _Out_ IUnknown **ppunk ); OleAut32.dll #ce Func _GetActiveObject ( $sGUID ) Static Local _ $tagIUnknown = "ptr QueryInterface;" & _ "ptr AddRef;" & _ "ptr Release", _ $IID_IDispatch = _GuidFromString("{00020400-0000-0000-C000-000000000046}"), _ $pIID_IDispatch = DllStructGetPtr($IID_IDispatch), _ $E_NOINTERFACE = 0x80004002, _ $E_POINTER = 0x80004003 $tGUID = _GuidFromString($sGUID) $tIUnknown = DllStructCreate('ptr') $aCall = DllCall('OleAut32.DLL', 'INT', 'GetActiveObject', _ 'ptr', DllStructGetPtr($tGUID), _ 'ptr', 0, _ 'ptr', DllStructGetPtr($tIUnknown) ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) $pIUnknown = DllStructGetData($tIUnknown, 1) If $IUnknownDebugger Then ; Retreive IUnknown's VTable $tIUnknown = DllStructCreate('ptr', $pIUnknown) $vtIUnknown = DllStructCreate($tagIUnknown, DllStructGetData($tIUnknown, 1)) ; Does MSDN mean the returned IUnknown is not our object because we need ; to QueryInterface for IDispatch? ; How To Attach to a Running Instance of an Office Application ; [http://support.microsoft.com/kb/238975/en-us] ; How to get IDispatch of an Excel or Word document from an OCX ; [http://support.microsoft.com/kb/190985] $aCall = DllCallAddress("INT", DllStructGetData($vtIUnknown, 'QueryInterface'), _ "ptr", $pIUnknown, _ "ptr", $pIID_IDispatch, _ "ptr", DllStructGetPtr($tIUnknown) ) If @error OR $aCall[0] Then If @error Then Return SetError(2, @error, 0) If $aCall[0] = $E_POINTER Then Return SetError(2, 0, 0) ; Invalid IUnknown If $aCall[0] = $E_NOINTERFACE Then Return SetError(3, 0, 0) ; IID not recognized Return SetError(4, $aCall[0], 0) EndIf DllCallAddress("INT", DllStructGetData($vtIUnknown, 'Release'), "ptr", $pIUnknown) ; This call never arrived in out-of-process case (watch the log) ; which is weird because previous AddRef and QueryInterface call ; are arrived safely. (Marshalling failure crash Ole handler?) ; Now we should have the IDispatch right? $pIUnknown = DllStructGetData($tIUnknown, 1) ; Below is required if registered with ACTIVEOBJECT_WEAK flag: ; _AutoItObject_IUnknownAddRef($pIUnknown) EndIf _Log("_GetActiveObject IDispatch acquired " & $pIUnknown & " " & $sGUID) Return _AutoItObject_PtrToIDispatch($pIUnknown) ; Nah, this will crash in out-of-process case EndFunc Func _PtrToIDispatch($pIDispatch) Static Local $PTR_SIZE = DllStructGetSize(DllStructCreate('ptr')) Local $aCall = DllCall('Kernel32.DLL', "none", "RtlMoveMemory", "idispatch*", 0, "ptr*", $pIDispatch, "dword", $PTR_SIZE) If @error Then Return SetError(1, 0, 0) Return $aCall[1] EndFunc #cs HRESULT RevokeActiveObject( _In_ DWORD dwRegister, _Reserved_ void *pvReserved ); OleAut32.dll #ce Func _RevokeActiveObject ( ByRef $_IDispatch, $iHandle ) If NOT $IUnknownDebugger Then $pIDispatch = _AutoItObject_IDispatchToPtr($_IDispatch) _CoLockObjectExternal($pIDispatch, False, True) If @error Then Return SetError(2, @extended, 0) EndIf $aCall = DllCall('OleAut32.DLL', 'INT', 'RevokeActiveObject', _ 'dword', $iHandle, _ 'ptr', 0 ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) Return 1 EndFunc #EndRegion <<< Win32 ActiveObject API #Region >>> Win32 GUID API (CLSIDFromString may return E_CLASSNOTREG for unregistered ClsId) Func _GuidFromString ( $sUUID, $ptGUID=0 ) Static Local $RPC_S_INVALID_STRING_UUID = 0x6A9 ; Use passed GUID struct by pointer or create new Local $tGUID If $ptGUID = 0 Then $tGUID = DllStructCreate($tagGUID) Else $tGUID = DllStructCreate($tagGUID, $ptGUID) EndIf ; Strip '{}' If StringLeft($sUUID, 1) = '{' Then $sUUID = StringMid($sUUID, 2, StringLen($sUUID) - 2) Local $aCall = DllCall("Rpcrt4.DLL", 'INT', 'UuidFromStringW', 'wstr', $sUUID, 'ptr', DllStructGetPtr($tGUID)) If @error OR $aCall[0] Then If $aCall[0] = $RPC_S_INVALID_STRING_UUID Then Return SetError(2, 0, 0) ; Invalid Uuid String Return SetError(3, @error, 0) ; UuidFromString call failed EndIf Return $tGUID EndFunc ;==> _DllCOM_GuidFromString Func _StringFromGuid ( $tGUID, $fCompat=1 ) If IsPtr($tGUID) Then $tGUID = DllStructCreate($tagGUID, $tGUID) Local $aCall = DllCall("Rpcrt4.DLL", 'INT', 'UuidToStringW', 'ptr', DllStructGetPtr($tGUID), 'wstr*', 0) If @error OR $aCall[0] Then Return SetError(2, $aCall[0], 0) ; UuidToString call failed If $fCompat Then Return "{" & StringUpper($aCall[2]) & "}" Return $aCall[2] EndFunc ;==> _DllCOM_StringFromGuid #EndRegion <<< Win32 GUID API ; AutoItObject test method Func _ActiveObject_Hello ( $_Self, $msg ) MsgBox(0, @AutoItPID, "After all that had happened: " & $msg) EndFunc ; Server & Client Main If $CmdLine[0] Then Opt('TrayIconHide', 1) $sGUID = $CmdLine[1] If $sGUID = EnvGet("ActiveObjectGUID") AND $sGUID = ConsoleRead() Then ; verify GUID _Log("Out-of-process fetching ActiveObject: " & $sGUID) MsgBox(0, @AutoItPID, "Fasten your seatbelt," & @CRLF & "we are going to CRASH!") $_out_proc_object = _Critical( _GetActiveObject($sGUID) ) _Log("Out-of-process object test: " & $_out_proc_object.Data) Else _Log("ActiveObject GUID missmatch!") EndIf ; make sure stdout flushed Sleep(500) Else $_ActiveObject = _AutoItObject_Create() _AutoItObject_AddProperty($_ActiveObject, "Data", $ELSCOPE_PUBLIC, "I'm alive!") _AutoItObject_AddMethod($_ActiveObject, "Hello", "_ActiveObject_Hello") If $IUnknownDebugger Then $_pActiveObject = _AutoItObject_IDispatchToPtr($_ActiveObject) $sGUID = ObjCreate("Scriptlet.TypeLib") $sGUID = $sGUID.GUID $hActiveObject = _Critical( _RegisterActiveObject($_ActiveObject, $sGUID) ) If $OutOfProcessTest Then EnvSet("ActiveObjectGUID", $sGUID) $pid = Run('"' & @AutoItExe & '" "' & @ScriptFullPath & '" ' & $sGUID, @ScriptDir, @SW_HIDE, 0x3) StdInWrite($pid, $sGUID) While ProcessExists($pid) $log = StdoutRead($pid) If @extended Then ConsoleWrite($log) Else Sleep(100) EndIf WEnd Else _Log("In-process fetching ActiveObject: " & $sGUID) $_in_proc_object = _Critical( _GetActiveObject($sGUID) ) _Log("In-process object test: " & $_in_proc_object.Data) EndIf ; Prove that object still valid $_ActiveObject.Hello($_ActiveObject.Data) _Critical( _RevokeActiveObject($_ActiveObject, $hActiveObject) ) EndIf #Region >>> IUnknown Stub Func _ActiveObject_AddRef ( $_Self ) _Log("_ActiveObject_AddRef") Return 0; EndFunc Func _ActiveObject_Release ( $_Self ) _Log("_ActiveObject_Release") Return 0; EndFunc ; IID_IUnknown {00000000-0000-0000-C000-000000000046} ; IID_IMarshal {00000003-0000-0000-C000-000000000046} ; IID_IProxyManager {00000008-0000-0000-C000-000000000046} ; IID_IStdMarshalInfo {00000018-0000-0000-C000-000000000046} ; IID_IExternalConnection {00000019-0000-0000-C000-000000000046} ; ? {0000001B-0000-0000-C000-000000000046} <-- IdentityUnmarshal's GUID ; {4C1E39E1-E3E3-4296-AA86-EC938D896E92} <-- proxy-stub request, handled by default? Func _ActiveObject_QueryInterface ( $_Self, $pIID, $ppObject ) Static Local $E_NOTIMPL = 0x80004001 $sIID = _StringFromGuid($pIID) If $sIID = "{00000000-0000-0000-C000-000000000046}" Then $tOut = DllStructCreate('ptr', $ppObject) DllStructSetData($tOut, 1, $_ActiveObject_Factory) _Log("_ActiveObject_QueryInterface IUnknown Requested") Return 0; ElseIf $sIID = "{00020400-0000-0000-C000-000000000046}" Then $tOut = DllStructCreate('ptr', $ppObject) DllStructSetData($tOut, 1, $_pActiveObject) _Log("_ActiveObject_QueryInterface IDispatch Requested") Return 0; Else _Log("_ActiveObject_QueryInterface Unhandled: " & _StringFromGuid($pIID)) Return $E_NOTIMPL EndIf EndFunc #EndRegion <<< IUnknown Stub #Region >>> Debugging Func _Log ( $msg ) ConsoleWrite($msg & @CRLF) EndFunc Func _Error ( $msg ) ConsoleWriteError($msg & @CRLF) EndFunc Func _Critical ($ret, $rel=0, $msg="Fatal Error", $err=@error, $ext=@extended, $ln = @ScriptLineNumber) If $err Then $ln += $rel Local $LastError = _WinAPI_GetLastError(), _ $LastErrorMsg = _WinAPI_GetLastErrorMessage(), _ $LastErrorHex = Hex($LastError) $LastErrorHex = "0x" & StringMid($LastErrorHex, StringInStr($LastErrorHex, "0", 1, -1)+1) $msg &= @CRLF & "at line " & $ln & @CRLF & @CRLF & "AutoIt Error: " & $err & " (0x" & Hex($err, 8) & ") Extended: " & $ext & " (0x" & Hex($ext, 8) & ")" If $LastError Then $msg &= @CRLF & "WinAPI Error: " & $LastError & " (" & $LastErrorHex & ")" & @CRLF & $LastErrorMsg _Error($msg) ClipPut($msg) MsgBox(270352, "Fatal Error - " & @ScriptName, $msg) Exit EndIf Return $ret EndFunc #EndRegion <<< Debugging Please help to make it work, it would be cool if we can use AutoItObject for IPC!
trancexx Posted March 18, 2013 Posted March 18, 2013 Why can't you use _AutoItObject_RegisterObject() function? Objects registered with that function are accessible throughout the system, not only inproc. ♡♡♡ . eMyvnE
eimhym Posted March 18, 2013 Posted March 18, 2013 (edited) Why can't you use _AutoItObject_RegisterObject() function?Objects registered with that function are accessible throughout the system, not only inproc.Whoa, silly me totally miss that spot! Thank you trancexx!Btw, is there any way to get the object outside autoit? cuz cbi: header is not known and guid not found using the regular GetActiveObject.Edit:OK, found nice example here and in Geez, only a handfull of them in google, these RegisterObject series should get more spotlight, cuz they are the star! Edited March 18, 2013 by eimhym
trancexx Posted March 18, 2013 Posted March 18, 2013 (edited) "cbi:" moniker is just for the AutoItObject's implementation of the calling function. You can use built-in ObjGet() to create the object from AutoIt scripts or GetObject() from VBS/JS, or System.Runtime.InteropServices.Marshal.BindToMoniker() from .NET based languages, or simple CoGetObject() WinAPI call for C/C++/... languages, or MkParseDisplayName(). All that without "cbi:" of course. Edited March 18, 2013 by trancexx ♡♡♡ . eMyvnE
SkinnyWhiteGuy Posted April 19, 2013 Posted April 19, 2013 I spent some time looking on the forums for this, but didn't see where any one else was doing it. Is there a way, with this, to create COM Objects that respond to events? I was hoping to use trancexx's earlier example of how to create your own com server to make a plugin for a program, and just register for events that come from it so it can scan/do what it needs, and send back events when something interesting occurs, but I can't find any examples or hints as to how to do so with COM events (using ObjEvent() ).
RafaelMaciel Posted July 3, 2013 Posted July 3, 2013 (edited) Hi guys, First, you are stupendous. This object are wonderfull. I'm start use AutoitObject and Koda at one script, and the situation is: The next code works perfect and the window opens normaly. -------------------------------------------------------------------------- ;Includes das telas #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Func _Telas_Analista_main() #Region ### START Koda GUI section ### $AnalistaFormMain = GUICreate("Analista", 224, 438, 10, 10, BitOR($WS_SYSMENU, $WS_BORDER, $WS_CAPTION)) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() ConsoleWrite("!...Tela travada'" & @CRLF) Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd EndFunc _Telas_Analista_main() -------------------------------------------------------------------------------------------------------------------------------------------------------- but, the next code are the up code with AutoitObject, and this, when I execute, his open the window but this stop!! -------------------------------------------------------------------------------------------------------------------------------------------------------- expandcollapse popup#comments-start AutoIt Version: 0.1 Author: Rafael Scolari Maciel Objetivo: Gestão da execução das rotinas de analise #comments-end #include "AutoitObject.au3" #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> _AutoItObject_StartUp() Global $C_Analista = _Analista_create();global detentora do objeto ANALISTA Func _Analista_create() Local $oClassObject = _AutoItObject_Class() $oClassObject.Create() $oClassObject.AddMethod("formMain", "_Analista_main") $oClassObject.AddDestructor("_DestructorForAnalista") Return $oClassObject.Object EndFunc Func _Analista_main($oSelf) #Region ### START Koda GUI section ### $AnalistaFormMain = GUICreate("Analista", 224, 438, 10, 10, BitOR($WS_SYSMENU, $WS_BORDER, $WS_CAPTION)) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() ConsoleWrite("!...Tela travada'" & @CRLF) Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd EndFunc Func _DestructorForAnalista($oSelf) ConsoleWrite("!...destructing... 'Analista'" & @CRLF) EndFunc $C_Analista.formMain -------------------------------------------------------------------------------------------------------------------------------------------------------- At another post, Martin makes a great code to show this situation: expandcollapse popup;Includes das telas #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include "C:\Program Files\Autoit3\include\AutoitObject.au3" Dim $doexit _AutoItObject_StartUp() extern2("Window 1") ;create window without using objects Global $C_Analista = _Analista_create();global detentora do objeto ANALISTA $C_Analista.formMain $C_Analista = 0;destroy th eobject _AutoItObject_Shutdown();don't forget this line although the examples do Func _Analista_create() Local $oClassObject = _AutoItObject_Class() $oClassObject.Create() $oClassObject.AddMethod("formMain", "_Analista_main") $oClassObject.AddDestructor("_DestructorForAnalista") Return $oClassObject.Object EndFunc ;==>_Analista_create Func _Analista_main($oSelf) extern2("window from object") EndFunc func extern2($title) AutoItSetOption("guioneventmode",1) $doexit = 0 #region ### START Koda GUI section ### $AnalistaFormMain = GUICreate($title, 224, 438, 10, 10);, BitOR($WS_SYSMENU, $WS_BORDER, $WS_CAPTION)) GUISetState(@SW_SHOW) #endregion ### END Koda GUI section ### ConsoleWrite("step 4" & @LF) GUISetOnEvent($GUI_EVENT_CLOSE, "CloseGui") While $doexit = 0 sleep(30) WEnd EndFunc ;==>_Analista_main Func CloseGui() ConsoleWrite("close gui?" & @LF) $doexit = 1 EndFunc Func _DestructorForAnalista($oSelf) ConsoleWrite("!...destructing... 'Analista'" & @CRLF) EndFunc ;==>_DestructorForAnalista () More infos: From the Windows Event Viewer the AutoIt register two events, first: Fault bucket , type 0 Event Name: AppHangB1 Response: Not available Cab Id: 0 Problem signature: P1: AutoIt3.exe P2: 3.3.8.1 P3: 4f25baec P4: 1435 P5: 0 P6: P7: P8: P9: P10: Attached files: These files may be available here: C:\Users\<<<<<>>>>>>\AppData\Local\Microsoft\Windows\WER\ReportArchive\AppHang_AutoIt3.exe_8aa79b99642e5abe8fef93464a12724dbc1d31c_406e79d5 Analysis symbol: Rechecking for solution: 0 Report Id: cffc3b89-e378-11e2-83c1-0024e8b38737 Report Status: 0 Error event: The program autoit3.exe version 3.3.8.1 stopped interacting with Windows and was closed. To see if more information about the problem is available, check the problem history in the Action Center control panel. Process ID: 5ca8 Start Time: 01ce77858450d018 Termination Time: 14 Application Path: C:\Program Files (x86)\AutoIt3\autoit3.exe Report Id: cffc3b89-e378-11e2-83c1-0024e8b38737 Please, someone can help me? Edited July 3, 2013 by RafaelMaciel
MarkRobbins Posted July 7, 2013 Posted July 7, 2013 I love objects, but having to declare them like _SomeBulkyFunctionName(...) grates on my nerves (as I am used to C++ style classes), so I wrote a small function "_ObjCreate" to create objects for AutoItObject with somewhat cleaner syntax. Here it is for anybody else interested in using it. Is something more native feeling a possibility for the future? You give me bright ideas See what you think about this Widget.au3... expandcollapse popup#include-once ;this is your magic include, your mission is to design it #include "ClassMaker.au3" ;This is the cache for the string that would be passed to your Func _ObjCreate($sText) ;Note: This could be encapsulated into ClassMaker as an associative array Local $NewWidgetCache='' ;Here is the Constructor Func NewWidget($p1,$p2) ;These Comments end up as properties (ie fields) for ClassMaker to read #cs Public publicField; publicFieldWithAssignment="String"; Private privateField; ReadOnly readonlyField; #ce ;Call ClassMaker now... ;; begin packaging ; Next set of statements could be packaged in ClassMaker, but are exposed here to demonstrate whats happening. ; In packaged form the statements would be condensed in a call that would look like: ; Local $me=ClassMaker($NewWidgetCache, <file>) ; which does... If $NewWidgetCache=='' Then ;ClassMaker now analyzes this file to compile the string for _ObjCreate() ; IMPORTANT: For compiled scripts, ClassMaker is creating/reading a <mainscript>Classes.ini to hold data for ; when script files are not present to analyze $NewWidgetCache=ClassMaker('C:\scripts\classes\Widget.au3'); EndIf ; And here we call Create Local $me=_ObjCreate($NewWidgetCache) ;; end packaging ; ;All Done Return $me.Object EndFunc ;Now we use comment decorations to indicate our functions to ClassMaker Func _Widget__publicFn($me,$p1);PUBLIC EndFunc Func _Widget__privateFn($me,$p1);PRIVATE EndFunc What do you think?
MarkRobbins Posted July 8, 2013 Posted July 8, 2013 Ok, I have been playing around with AutoItObject library a bit now. My experiments have been in the context of making user-defined classes (not messing with predefined COM or trying to inherit from them or what have you). The docs on this are rather sparse, but what I have been able to determine is that AIO 'objects' are not objects that perform well as an OO design tool. What I mean is that these objects appear to be flat when it comes to 'inheritance' -- they are like Xeroxed on top of each other and there is no way to get to members that have been masked by inheritance. How can you have real OO without 'protected' and when 'private' really means 'protected' all down the tree? I don't want to sound like a super-critic, I am just stating these things to make sure I understand the situation correctly. For instance, I do not see a way to access 'this.base' in a single inheritance, or something akin to 'this.bases.classname.member' in the case of multiple inheritance. Is this correct? Where can I get a list of this.__<special>__ members? I think I saw one a while back, I dont recall what it was though. I am sure this package is exciting in accessing COM, but I feel I am missing out on something as far as using it for OO design, except in a very limited sense. Nonetheless, I have built a helper for the AIO library called ClassMaker. It is a syntax cheat that will wire up an AIO object to its methods automtically by reading the script file. This could be extended further but I am apprehensive now that I am discovering limitations that I described above. The best way to explain it is to start with a AIO ClassMaker enabled file, first a comment-free base that we will inherit, WidgetBase.au3: #include-once ; See Widget.au3 for explaination, barebones commenting here Func NewWidgetBase() #cs Public publicFieldBase="This field has been set in WidgetBase Constructor"; #ce Local $me=$ClassMaker.Produce('C:\batch\borg\WidgetBase.au3') Return $me EndFunc Func _WidgetBase__publicFn($me,$p1);PUBLIC Msg('_WidgetBase__publicFn') Msg('_WidgetBase__publicFn calling $me.privateFn...') $me.privateFn(1) EndFunc Func _WidgetBase__publicFn2Bases($me,$p1);PUBLIC Msg('_WidgetBase__publicFn2Bases') Msg('_WidgetBase__publicFn2Bases trying to call $me.publicFnVirt...') $me.publicFnVirt(1) EndFunc Func _WidgetBase__privateFn($me,$p1);PRIVATE Msg('_WidgetBase__privateFn') EndFunc Func _WidgetBase__privateFnBase($me,$p1);PRIVATE Msg('_WidgetBase__privateFnBase') EndFunc Func _WidgetBase__destructor($me) ;$me.___inheritor=0 Msg('_WidgetBase__destructor'); EndFunc Now a commented class that will explain the fundamentals of how ClassMaker works, Widget.au3 expandcollapse popup#include-once ; This is an example class file to be fed into ClassMaker ; ; No need for this include, Main.au3 will include and initiate ClassMaker ;#include "ClassMaker.au3" ; ; We will inherit #include "WidgetBase.au3" #include "WidgetBase2.au3" ; The Constructor for the Widget Class, must use New<classname> signature for ClassMaker to recognize Func NewWidget($p1,$p2) ; The first #cs or #comments-start in a New<classname> constructor will be made into fields by ClassMaker #cs ;comments are allowed here, ignored by ClassMaker ; [<colon><baseclass>[,<baseclass>]...] declares our bases, applied in reverse order to handle overwrites logically ; this line can be omitted if not inheriting :WidgetBase,WidgetBase2 ; declare public section, case insensitive, can also be Public: ; if left off, ClassMaker will start in public. Also, indentation ignored by ClassMaker Public ;name a field, semicolon optional publicField; ;name another field, with assignment. Right now only primitive assignments work, cannot access variables yet. publicFieldWithAssignment="This field has been assigned in Widget constructor"; ;more of the same Private privateField; ReadOnly readonlyField; ; Can switch back or do classifiers in any order, or even leave one empty as below Public #ce ; Let ClassMaker do its magic now, pass in full path of file, classname derived from filename, but must be in synch ; with our constuctor and our method names ; ; IMPORTANT: Change this to reflect actual file location. Also do same with WidgetBase.au3, and WidgetBase2.au3 Local $me=$ClassMaker.Produce('C:\batch\borg\Widget.au3') ;IMPORTANT: can still do specialty work here, set property values to variables or expressions, ; add new properties, or methods, or even further inheritance. ; Though further inheritance is not recommended since ClassMaker is trying to give helpers on inheritance, such as: ; THESE LIKELY WORK... ; $me.___type = <classname> ; $me.___basesnames = array of <baseclassnames> ; $base.___inheritor = <objthatinheritedme> ; $base.___final = <obj at end of inheritance tree> ; ; NOT SURE IF THESE WORK YET BUT... ; $me.___base = first base class ; $me.___bases.<baseclassname> = <baseclassobject> ; $me.___basesarray = array of <baseclassobjects> ; ;All Done Return $me EndFunc ; ClassMaker will wire up any methods in the file with the proper signature to the object created ; Signatures by default are <prefix><classname><separator><functionname><suffix> ; Where prefix defaults to _ ; suffix defaults to "" ; separator defaults to __ ; ; These defaults can be set in ClassMaker on a global level currently ; ; Storage Class For Methods: public, private ; Determined by one of three things: Regions, Decorators, or Case of Method Name ; ; Regions lines look like "#region public" or ";public" (and "#endregion") ; ; Decorations are appended to right of function signatures and look like ";PUBLIC" (but are case insensitive) ; ; Method Names (see <functionname> above) are public if first letter is uppercase, else private ; ; Who wins? Regions override decorations which override Case Based determination ; ; ; Auto Property Backers... ; Certain function signatures will trigger the creation of a private property backer ; Any qualifiying (as above) function, should it also have a parameter declaration in the form of: ; $value='PROPERTY' ; will have a property backer field created for it with the name _<functionname> ; Thus far, these created backers are only initialized to "" ; ; Destructors... ; Any <functionname>=destructor will be registered as a destructor ; ; The following code has a bit of experimental twiddling going on in it, but you can get the idea ; A typical public function whose <functionname> is publicFn, it is public because of its decorator ;PUBLIC ; without the decoration it would be private due to the lowercase p as the first letter of its name Func _Widget__publicFn($me,$p1);PUBLIC Msg('_Widget__publicFn') ;Msg('_Widget__publicFn trying to call $me.privateFnBase') ;$me.privateFnBase(1) EndFunc ; This is something that is called from one of the bases, even though it is not declared in them. Cool. Func _Widget__publicFnVirt($me,$p1);PUBLIC Msg('_Widget__publicFnVirt') EndFunc ; This is how to declare an assignable property (not a field), and have its backer auto-created by ClassMaker ; due to the $value='PROPERTY' in the signature. ; The internal code shows how to handle the workings of an assignable property ; Leaving out the signature trigger will allow you to create assignables that don't need backers Func _Widget__prop($me,$value='PROPERTY');PUBLIC If @NumParams = 2 Then $me._prop=$value Else return $me._prop EndIf ;Msg('_Widget__publicFn') EndFunc ; An Example of a private region, comment form ;Private ; This decorator will be ignored since we are in a private region Func _Widget__privateFn($me,$p1);PRIVATE Msg('_Widget__privateFn') EndFunc ; We are still in private, there is no EndPrivate currently ; Another... Func _Widget__privateFn2($me,$p1) Msg('_Widget__privateFn') EndFunc ;Switch to public using other region form #region public ; Decorator and case ignored in favor of region Func _Widget__publicFn2($me,$p1);PRIVATE Msg('_Widget__publicFn') Msg('_Widget__publicFn trying to call $me.privateFnBase') $me.privateFnBase(1) EndFunc #endregion ; Still in public despite #endregion, since public is default ; The Destructor. Decorations, Regions and Case do not have any effect. This guy is always private Func _Widget__destructor($me) Msg('_Widget__destructor'); EndFunc Throw in the code for the other base we will inherit, WidgetBase2.au3: #include-once ; See Widget.au3 for explaination, barebones commenting here Func NewWidgetBase2() #cs Public publicFieldBase="pubBase2"; #ce Local $me=$ClassMaker.Produce('C:\batch\borg\WidgetBase2.au3') ;All Done Return $me EndFunc Func _WidgetBase2__publicFn($me,$p1);PUBLIC Msg('_WidgetBase2__publicFn') EndFunc Func _WidgetBase2__publicFn2Bases($me,$p1);PUBLIC Msg('_WidgetBase2__publicFn2Bases') EndFunc Func _WidgetBase2__privateFn($me,$p1);PRIVATE Msg('_WidgetBase2__privateFn') EndFunc Func _WidgetBase2__destructor($me) ;$me.___inheritor=0 ;Msg('_WidgetBase2__destructor'); EndFunc Now a look at the Client: expandcollapse popupGlobal $thisfile='C:\batch\borg\ClassMakerTester.au3' #include <AutoItObject.au3> ; Include ClassMaker before any ClassFiles, ie Widget #include "ClassMaker.au3" ; Include this because I want to make some Widget AutoItObjects via ClassMaker #include "Widget.au3" ; Debug setup Global $logg="C:\batch\borg\ClassMakerTester-log.txt"; ;e C:\batch\borg\ClassMakerTester-log.txt Global $timestamp=@YEAR&"."&@MON&"."&@MDAY&"."&@HOUR&"."&@MIN&"."&@SEC&"."&@MSEC logclear() ; Do this for AutoItObject Lib OnAutoItExitRegister("EvtScriptExit") _AutoItObject_Startup() Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") ; Do once, before we make any ClassMaker dependent AutoItObjects ClassMaker() ; Now we can make the ClassMaker dependent AutoItObject "Widget" Global $widget1=NewWidget(1,2) ; STAND BACK!, WIDGET TEST AREA!! ;================================ If false Then ; Test: Call a Public Function If false Then $widget1.publicFn(1) ; Test: Call a Private Function If false Then $widget1.privateFn(1) ; Success, 2013.07.08.04.44.24.626:[COM Error]: ScriptLine(29) : Number 0x80020003 - Member not found. ; Test: Set A Public Field If false Then $widget1.publicField='Assignment to public field ok' ; Test: Read A Public Field If false Then Msg($widget1.publicField) ; Test: Read A Public Field Set in the Constuctor If false Then Msg($widget1.publicFieldWithAssignment) ; Test: Set A Public Assignable Property with automatically created backer field If false Then $widget1.prop="Assigning a assignable property" ; Test: Read a Public Assignable Property If false Then Msg($widget1.prop) ; Test: Read a Base Public Field that has been assigned in constructor If false Then Msg($widget1.publicFieldBase) ; Test: Set a Base Public Field that has been assigned in constructor If false Then $widget1.publicFieldBase="$widget1.publicFieldBase has been reset" ; Test: Read a Base Public Field that has been assigned in constructor and reset If false Then Msg($widget1.publicFieldBase) ; Test: Check the ___base.publicFieldBase to see if it has changed If false Then Msg($widget1.___base.publicFieldBase) ; Fail, are objects disconnected? or am I just writing to this. ; Objects are disconnected, writing to .___base does not show up in this. EndIf If false Then ; We need more widgets Global $widget2=NewWidget(1,2) ; Test: See the .___base.___type If True Then Msg($widget2.___base.___type) ; Test: Set ___base.publicFieldBase and see if it shows up in this $widget2.___base.publicFieldBase="$widget2.___base.publicFieldBase set from main" If True Then Msg($widget2.publicFieldBase) EndIf ;e C:\batch\borg\ClassMakerTester-log.txt $widget1=0 Exit ; AutoItObject Exit Function Func EvtScriptExit() ;Msg("EvtScriptExit") _AutoItObject_Shutdown() EndFunc ; AutoItObject DEBUG FUNCTION Func _ErrFunc() ;ConsoleWrite("COM Error, ScriptLine(" & $oError.scriptline & ") : Number 0x" & Hex($oError.number, 8) & " - " & $oError.windescription & @CRLF) Local $line="[COM Error]: ScriptLine(" & $oError.scriptline & ") : Number 0x" & Hex($oError.number, 8) & " - " & $oError.windescription Local $line2="" & $oError.scriptline & ":" & $oError.windescription logerr($line) ;Msg($line2) snarl(10,"COM ERROR"&":0x" & Hex($oError.number, 8),$line2) EndFunc ; DEBUG FUNCTION BELOW Func Msg($s) MsgBox(0,$thisfile,$s) EndFunc Func ts() Return @YEAR&"."&@MON&"."&@MDAY&"."&@HOUR&"."&@MIN&"."&@SEC&"."&@MSEC EndFunc Func logclear() FileDelete($logg) EndFunc Func logline($line) Local $fh1=FileOpen($logg,1); If $fh1<>-1 Then FileWriteLine($fh1,$line) FileClose($fh1) EndIf EndFunc Func logerr($line) Local $fh1=FileOpen($logg,1); Local $t=ts() If $fh1<>-1 Then FileWriteLine($fh1,$t&':'&$line) FileClose($fh1) EndIf EndFunc ;If you have Snarl_CMD.exe, hook it up here for debugging ; I think the right source is ; http://sourceforge.net/projects/mozillasnarls/files/Snarl_CMD/ Func snarl($i,$t,$s) $snarl="C:\batch\Snarl_CMD.exe"; If Not FileExists($snarl) Then Return $s1=StringReplace($s,'"',"'") $t1=StringReplace($t,'"',"'") $cmd=$snarl&' snShowMessage '&$i&' "'&$t1&'" "'&$s1&'"'; Run($cmd) EndFunc And Finally the ClassMaker itself, ClassMaker.au3: expandcollapse popup; #INDEX# ======================================================================================================================= ; Title .........: ClassMaker v1.0.0.0 ; AutoIt Version : 3.3 ; Language ......: English (language independent) ; Description ...: Wires AutoItObjects by reading script files, attempts to make them more like true objects. ; Author(s) .....: MarkRobbins ; Copyright .....: Copyright (C) Mark C Robbins. All rights reserved. ; License .......: Artistic License 2.0, see Artistic.txt ; ; ClassMaker is free software; you can redistribute it and/or modify ; it under the terms of the Artistic License as published by Larry Wall, ; either version 2.0, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ; See the Artistic License for more details. ; ; You should have received a copy of the Artistic License with this Kit, ; in the file named "Artistic.txt". If not, you can get a copy from ; <http://www.perlfoundation.org/artistic_license_2_0> OR ; <http://www.opensource.org/licenses/artistic-license-2.0.php> ; ; =============================================================================================================================== ; #OVERVIEW# =========================================================================================================== ; SOURCE_______________________________________________________________________________________________________________ ; Organization ..: Mark Robbins and Associates ; Author ........: Mark Robbins ; LOG__________________________________________________________________________________________________________________ ; Created .......: 2013.07.08 ; Modified ......: 2013.07.08 ; Entries........: yyyy.mm.dd.hh.mm.ss Comments ; HEADER_______________________________________________________________________________________________________________ ; Type ..........: Class ; Subtype .......: Helper ; Name ..........: ClassMaker ; Summary .......: Class construction framework for AutoItObject Classes. ; Description ...: Provides formalized syntax for class declaration, uses that syntax in construction of the class by ; dynamically reading the script source file. Currently not to be used in compiled scripts. ; Remarks .......: This is a work in progress. ; DEVELOPMENT__________________________________________________________________________________________________________ ; Issues ........: Need to implement mechanism for working with compiled scripts. ; Need Error handling. ; Need more investigation into how inheritance works and how to enhance it ; Status ........: [ ] New ; [ ] Open ; [X] InProgress ; [ ] Resolved ; [ ] Closed ; OTHER________________________________________________________________________________________________________________ ; Related .......: AssocArrays.au3, ; Related Links .: http://www.autoitscript.com/forum/topic/110379-autoitobject-udf/ ; Resources......: ; ===================================================================================================================== #include-once #include <AssocArrays.au3> #include <File.au3> #include <Array.au3> ; #CURRENT# ===================================================================================================================== ;NewClassMaker ;$ClassMaker.Produce ; =============================================================================================================================== ; #HELPERS# ===================================================================================================================== ;ArrayDisp ; =============================================================================================================================== ; #INTERNAL# ==================================================================================================================== ;$ClassMakerCache ;$ClassMaker.classfirst ;$ClassMaker.fields_a ;$ClassMaker.re_pfx ;$ClassMaker.re_sfx ;$ClassMaker.sep ;cacheGet__ClassMaker ;cacheHas__ClassMaker ;cachePut__ClassMaker ;cacheZap__ClassMaker ;Produce__ClassMaker ;collectFieldString__ClassMaker ;collectFunctionString__ClassMaker ;findNewLine__ClassMaker ;findNewLineCommentStart__ClassMaker ;findNewLineCommentEnd__ClassMaker ;make__ClassMaker ; =============================================================================================================================== ; Singleton Handle. Every Class File must include ClassMaker.au3 and Main must call ClassMaker() Global $ClassMaker;=NewClassMaker() ; Data cache <classname>:<dataarrays> Global $ClassMakerCache ; Initialize the singleton Func ClassMaker() If Not IsObj($ClassMaker) Then $ClassMaker=NewClassMaker() If Not IsObj($ClassMaker) Then Msg('ClassMaker():forgot _AutoItObject_Startup() in Main?') EndIf EndIf Return $ClassMaker EndFunc ; ClassMakers Constuctor Func NewClassMaker() Local $me = _AutoItObject_Create() AssocArrayCreate($ClassMakerCache,1); ;do function signatures have classname first or last _AutoItObject_AddProperty($me,"classfirst",$ELSCOPE_PUBLIC,True) ;used as a temp cludge for now _AutoItObject_AddProperty($me,"fields_a",$ELSCOPE_PRIVATE,'') ;a non-capturing regex that will match fn sig prefix _AutoItObject_AddProperty($me,"re_pfx",$ELSCOPE_PUBLIC,'_') ;a non-capturing regex that will match fn sig suffix _AutoItObject_AddProperty($me,"re_sfx",$ELSCOPE_PUBLIC,'') ;a string literal that separates the classname from the function name in function signatures _AutoItObject_AddProperty($me,"sep",$ELSCOPE_PUBLIC,'__') ;Main Method, pass filepath and recieve new class instance _AutoItObject_AddMethod($me,"Produce","Produce__ClassMaker") ;cache utils _AutoItObject_AddMethod($me,"cacheHas","cacheHas__ClassMaker",True) _AutoItObject_AddMethod($me,"cachePut","cachePut__ClassMaker",True) _AutoItObject_AddMethod($me,"cacheGet","cacheGet__ClassMaker",True) _AutoItObject_AddMethod($me,"cacheZap","cacheZap__ClassMaker",True) ;get an array of fields to be created _AutoItObject_AddMethod($me,"collectFieldString","collectFieldString__ClassMaker",True) ;get an array of functions to be created _AutoItObject_AddMethod($me,"collectFunctionString","collectFunctionString__ClassMaker",True) ;discover location of New<classname> function in file _AutoItObject_AddMethod($me,"findNewLine","findNewLine__ClassMaker",True) ;discover location of #cs directive that is after New<classname> function in file _AutoItObject_AddMethod($me,"findNewLineCommentStart","findNewLineCommentStart__ClassMaker",True) ;discover location of #ce directive that is after New<classname> function in file _AutoItObject_AddMethod($me,"findNewLineCommentEnd","findNewLineCommentEnd__ClassMaker",True) ;make actual class from data arrays _AutoItObject_AddMethod($me,"make","make__ClassMaker",True) Return $me EndFunc ;new class object instance is created, classname derived from filename of fullpath parameter $fn Func Produce__ClassMaker($me,$fn);PUBLIC If Not FileExists($fn) Then MsgBox(0,'ClassMaker.Produce','File not found:'&$fn) Exit EndIf ;compute classname Local $szDrive, $szDir, $szFName, $szExt; _PathSplit($fn, $szDrive, $szDir, $szFName, $szExt) Local $n=$szFName; ;our data arrays Local $fields_a; Local $funs_a; ;maybe use cache If $me.cacheHas($n) Then Local $aaa=$me.cacheGet($n) $fields_a=$aaa[0] $funs_a=$aaa[1] ;make the instance Return $me.make($n,$fields_a,$funs_a) EndIf ;cache not present, read the script file Local $a ;TODO: fileexists _FileReadToArray($fn,$a) ;get field data $fields_a=$me.collectFieldString($n,$a) ;func data getter will need access, so cludge $me.fields_a=$fields_a ;get function data $funs_a=$me.collectFunctionString($n,$a) ;recieve the cludge $fields_a=$me.fields_a ;store in cache Local $bbb[2] $bbb[0]=$fields_a $bbb[1]=$funs_a $me.cachePut($n,$bbb) ;make the instance Return $me.make($n,$fields_a,$funs_a) EndFunc ;cache utils Func cacheHas__ClassMaker($me,$key);PRIVATE Return AssocArrayExists($ClassMakerCache,$key) EndFunc Func cachePut__ClassMaker($me,$key,$val);PRIVATE Return AssocArrayAssign($ClassMakerCache,$key,$val) EndFunc Func cacheGet__ClassMaker($me,$key);PRIVATE Return AssocArrayGet($ClassMakerCache,$key) EndFunc Func cacheZap__ClassMaker($me,$key);PRIVATE Return AssocArrayDelete($ClassMakerCache,$key) EndFunc ;discover "Func New<classname> in file, ignore commented out lines via #cs etc Func findNewLine__ClassMaker($me,$classname,$a) ;TODO:condense all finders into one function Local $to=UBound($a)-1 Local $i Local $it Local $in_cs=False ;TODO: account for space before parens? or other space anomalies Local $tgt='func new'&StringLower($classname)&'(' ;each line For $x=1 To $to $i=$a[$x] $it=StringStripWS($i,3);lead and trail $it=StringLower($it) ;filters... If StringMid($it,1,1)==';' Then ContinueLoop If $it=='' Then ContinueLoop ;in comment toggle If $in_cs Then If ($it=='#ce' Or $it=='#comments-end') Then $in_cs=False EndIf ContinueLoop EndIf If $it=='#cs' Or $it=='#comments-start' Then $in_cs=True ContinueLoop EndIf ;candidate line If StringMid($it,1,StringLen($tgt))==$tgt Then ;found! Return $x EndIf Next Return -1 EndFunc ;find first #cs or #comments-start after Func New<classname> Func findNewLineCommentStart__ClassMaker($me,$classname,$a) Local $beg=$me.findNewLine($classname,$a) If $beg==-1 Then Return -1 EndIf Local $to=UBound($a)-1 Local $i Local $it Local $in_cs=False For $x=$beg To $to $i=$a[$x] $it=StringStripWS($i,3);lead and trail $it=StringLower($it) ;filter If StringMid($it,1,1)==';' Then ContinueLoop If $it=='' Then ContinueLoop ;candidate If $it=='#cs' Or $it=='#comments-start' Then ;found! Return $x EndIf Next Return -1 EndFunc ;find first #ce or #comments-end after #cs or #comments-start after Func New<classname> Func findNewLineCommentEnd__ClassMaker($me,$classname,$a) Local $beg=$me.findNewLineCommentStart($classname,$a) If $beg==-1 Then Return -1 EndIf Local $to=UBound($a)-1 Local $i Local $it Local $in_cs=False For $x=$beg To $to $i=$a[$x] $it=StringStripWS($i,3);lead and trail $it=StringLower($it) ;filter If StringMid($it,1,1)==';' Then ContinueLoop If $it=='' Then ContinueLoop ;candidate If $it=='#ce' Or $it=='#comments-end' Then ;found! Return $x EndIf Next Return -1 EndFunc ;scan field section for declarations Func collectFieldString__ClassMaker($me,$classname,$a) Local $ra[4] $ra[0]='' $ra[1]='' $ra[2]='' $ra[3]='' Local $d=Chr(9) ;Local $d='.'; Local $s1='' Local $s2='' Local $s3='' Local $s4='' Local $beg=$me.findNewLineCommentStart($classname,$a) Local $end=$me.findNewLineCommentEnd($classname,$a) If $beg==-1 Then Return $ra If $end==-1 Then Return $ra Local $i,$it,$it2 ;default to public storage Local $t='public' For $x=$beg+1 To $end-1 $i=$a[$x] $it=StringStripWS($i,3);lead and trail $it2=$it ;filter... If StringMid($it,1,1)==';' Then ContinueLoop If $it=='' Then ContinueLoop ;handle base class list If StringMid($it,1,1)==':' Then $s4=StringMid($it,2) ContinueLoop EndIf ;handle storage declarations $it=StringLower($it) ;remove trailing colon if exists If StringMid($it,StringLen($it),1)==':' Then $it=StringMid($it,1,StringLen($it)-1) EndIf ;handle switch of storage declaration If $it=='public' Or $it=='private' Or $it=='readonly' Then $t=$it ContinueLoop EndIf ;revert to non-lowercase line $it=$it2 ;slot and append declaration into proper delimited string based on storage declaration If $t=='public' Then If $s1=='' Then $s1=$it Else $s1&=$d&$it EndIf ElseIf $t=='private' Then If $s2=='' Then $s2=$it Else $s2&=$d&$it EndIf ElseIf $t=='readonly' Then If $s3=='' Then $s3=$it Else $s3&=$d&$it EndIf EndIf Next ;fill the return array $ra[0]=$s1 $ra[1]=$s2 $ra[2]=$s3 $ra[3]=$s4 Return $ra EndFunc ;debug helper, sometimes _ArrayDisplay Hangs - is this an AutoItObject problem? Func ArrayDisp($a) Local $s='' Local $x,$i,$to=UBound($a)-1 For $x=0 To $to If $s=='' Then $s=$a[$x] Else $s&=@CRLF&$a[$x] EndIf Next Msg($s) EndFunc ;scan entire file for function declarations with proper signature Func collectFunctionString__ClassMaker($me,$classname,$a) ;cludge, we need this for property backers Local $fa=$me.fields_a ;Signatures look like: <pfx><classname><separator><functionname><suffix> or ; <pfx><functionname><separator><classname><suffix> depending on ClassMaker.classfirst ; ;Region: ;<storage> or ; #region <storage> ; ;Decorator: Func <name>();<storage> ; ;ProperCase: Function names (see sig <functionname>) starting with uppercase are public, else private ; ;Storage determination overrides: ; Regions override Decorators which override ProperCase ; ; ;Property Backers: Always private, sig: _<functionname> ; Created for functions with 2 params where second param sig: $value='PROPERTY' ; ; Local $d=Chr(9) Local $s1='' Local $s2='' Local $s3='' Local $i,$it,$it2,$it3 Local $in_cs ;undef is assumed public Local $t='undef' Local $end=UBound($a)-1 Local $fn,$re_pfx,$re_sfx,$sep,$aa,$pt1,$pt2,$cls,$fnn,$sc For $x=1 To $end $i=$a[$x] $it=StringStripWS($i,3);lead and trail $it2=$it ;filters... If StringMid($it,1,1)==';' Then ContinueLoop If $it=='' Then ContinueLoop $it=StringLower($it) ;handle comment section toggle If $in_cs Then If ($it=='#ce' Or $it=='#comments-end') Then $in_cs=False EndIf ContinueLoop EndIf If $it=='#cs' Or $it=='#comments-start' Then $in_cs=True ContinueLoop EndIf ;check for our types of region declarations $it3=StringStripWS($i,4+2+1);lead and trail and spans If $it3=='#region public' Or $it3==';public' Then $t='public' ContinueLoop EndIf If $it3=='#region private' Or $it3==';private' Then $t='public' ContinueLoop EndIf If $it3=='#endregion' Then $t='undef' ContinueLoop EndIf ;filter... want functions If StringMid($it,1,5)<>'func ' Then ContinueLoop EndIf ;is it a function? then parse it $aa=StringRegExp($it2, "(?i:Func) ([^ \(]+)\(", 2) If @Error<>0 Then; no match?? ;Msg('nomatch1:'&$it2) ContinueLoop EndIf ;save the full function name $fn=$aa[1] ;prepare to parse it into name parts... $re_pfx=$me.re_pfx;'_' $re_sfx=$me.re_sfx;'' $sep=$me.sep;'__' Local $re=$re_pfx&"([A-Za-z0-9_]+)"&$sep&"([A-Za-z0-9_]+)"&$re_sfx; $aa=StringRegExp($fn, $re_pfx&"([A-Za-z0-9_]+)"&$sep&"([A-Za-z0-9_]+)"&$re_sfx, 2) If @Error<>0 Then; no match?? ;Msg('nomatch2:'&$fn) ContinueLoop EndIf ;save the name parts $pt1=$aa[1] $pt2=$aa[2] $cls=$pt1 $fnn=$pt2 If Not $me.classfirst Then $cls=$pt2 $fnn=$pt1 EndIf ;filter for not right classname in function name part If StringLower($cls)<>StringLower($classname) Then ContinueLoop EndIf ;decide storage class, public or pvt $sc='public';default If $t=='undef' Then ;look for decorators $aa=StringRegExp($it2, "; *(?i)(PUBLIC|PRIVATE)", 2) If @Error<>0 Then;not found ;determine using propercase If StringMid($fnn,1,1)==StringUpper(StringMid($fnn,1,1)) Then $sc='public' Else $sc='private' EndIf Else ;decorator given $sc=StringLower($aa[1]) EndIf Else ;use region $sc=$t EndIf ;handle creating a field backer If StringInStr($it3,',$value="property")')<>0 Or StringInStr($it3,",$value='property')")<>0 Then ;use the cludge here If $fa[1]=='' Then $fa[1]='_'&$fnn Else $fa[1]&=$d&'_'&$fnn EndIf ;continue on since we have to recognize the fn too EndIf ;data stored as <functionname for obj> <functionname in code> $it=$fnn&' '&$fn ;slot and append to proper string based on storage If $sc=='public' Then If $s1=='' Then $s1=$it Else $s1&=$d&$it EndIf ElseIf $sc=='private' Then If $s2=='' Then $s2=$it Else $s2&=$d&$it EndIf EndIf Next ;put the cludge back where we got it $me.fields_a=$fa Local $ra[3] ;fill our return array $ra[0]=$s1 $ra[1]=$s2 $ra[2]=$s3 Return $ra EndFunc ;make the object according to data Func make__ClassMaker($me,$classname,$ap,$af) ;ap is the array of field data ;af is the array of function data Local $o;the object to be returned ;do we have base classes If $ap[3]<>'' Then ;Msg('$ap[3]:'&$ap[3]) ;parse the data to array Local $bases=StringStripWS($ap[3],8) Local $basea=StringSplit($bases,' ,;',2) ;flip the array so we can inherit from the last item first to handle overwrite logically _ArrayReverse($basea) ;ArrayDisp($basea) Local $z,$basect=UBound($basea)-1 Local $baseoa[UBound($basea)] Local $sb,$basename,$constructor,$baseo Local $okct=0 ;for each base declaration, create and assume it onto our object For $z=0 To $basect $basename=$basea[$z] $constructor='New'&$basename ;Msg('creating base:'&$constructor) ;TODO:here maybe call other forms (without New prefix) on fail? $baseo=Call($constructor) ;TODO:Error reporting everywhere If IsObj($baseo) Then $o=_AutoItObject_Create($baseo); ;add it to stuff we made for later $baseoa[$z]=$baseo $okct+=1 EndIf Next ;get back to normal _ArrayReverse($basea) _ArrayReverse($baseoa) ;tack this data onto our object: an array of our bases, and an array of their names _AutoItObject_AddProperty($o,'___basesarray', $ELSCOPE_PUBLIC, $baseoa) _AutoItObject_AddProperty($o,'___basesnames', $ELSCOPE_PUBLIC, $basea) ;if we successfully made any bases If $okct>0 Then ;make a ___bases property on our object to tack the bases instances onto Local $_baseso=_AutoItObject_Create(); _AutoItObject_AddProperty($o,'___bases', $ELSCOPE_PUBLIC, $_baseso) ;the first base in list gets to be ___base Local $first=False For $z=0 To $basect If Not IsObj($baseoa[$z]) Then ContinueLoop If $first==False Then $first=True _AutoItObject_AddProperty($o,'___base', $ELSCOPE_PUBLIC, $baseoa[$z]) EndIf ;TODO:figure out how inheritance is suppose to work when you dont have protected storage ; and you cannot really privatize to the inheritor the things that are inherited and private ; ;add ___bases.<name>=<baseobj> _AutoItObject_AddProperty($_baseso,$basea[$z], $ELSCOPE_PUBLIC, $baseoa[$z]) ; Cannot do this, circular refs mean destructor won't be called If False Then ;add ___inheritor to each of those we inherited ;TODO: are these inherits really present? if I change base.field will this.field be changed? ; I suspect these are just flattened objects and bases are orphaned _AutoItObject_AddProperty($baseoa[$z],'___inheritor', $ELSCOPE_PUBLIC, $o) ;this is an attempt at a base calling a fn only defined in final, but this build-in behavior ;SEEMS to work thus far _AutoItObject_AddProperty($baseoa[$z],'___final', $ELSCOPE_PUBLIC, $o) EndIf Next EndIf Else ;no bases $o=_AutoItObject_Create(); EndIf ;object typing _AutoItObject_AddProperty($o,'___type', $ELSCOPE_READONLY, $classname) ;prepare to do fields Local $x,$i,$a,$y,$p Local $scope,$n,$za,$fn,$sc ;data array is public, private, readonly ;TODO: private+readonly?? ugh, didn't think about that For $x=0 to 2 $i=$ap[$x] ;which storage If $x==0 Then $scope=$ELSCOPE_PUBLIC $sc='public' ElseIf $x==1 Then $scope=$ELSCOPE_PRIVATE $sc='private' ElseIf $x==2 Then $scope=$ELSCOPE_READONLY $sc='readonly' EndIf ;empty string for these storage items If $i=='' Then If $x==0 Then ;Msg('No Public Fields') ElseIf $x==1 Then ;Msg('No Private Fields') Else ;Msg('No ReadOnly Fields') EndIf ContinueLoop EndIf ;split the string $a=StringSplit($i,Chr(9),1) ;each field For $y=1 To $a[0] $p=$a[$y] ;remove trailing semicolon If StringMid($p,StringLen($p),1)==';' Then $p=StringLeft($p,StringLen($p)-1) EndIf ;handle string has assignment ;TODO:how does Execute() work, can I get at locals somehow? If StringInStr($p,"=")>0 Then ;get the name part $n = StringReplace(StringLeft($p,StringInStr($p,"=")-1)," ","") ;add the evaluated field _AutoItObject_AddProperty($o,$n, $scope, Execute(StringTrimLeft($p,StringInStr($p,"=")))) ContinueLoop EndIf ;handle declarations without assignments If StringLen($p)>0 Then ;get the name $n = StringReplace($p," ","") ;Msg('making field for:"'&$n&'" as '&$sc); ;add the field and set to a empty string _AutoItObject_AddProperty($o,$n, $scope, '') ContinueLoop EndIf Next Next ;prepare to gather iterator declarations (Enums) Local $enums[3] $enums[0]='' $enums[1]='' $enums[2]='' ;function data array is public,private For $x=0 to 1 $i=$af[$x] ;set scope If $x==0 Then $scope=False ElseIf $x==1 Then $scope=True EndIf ;split data $a=StringSplit($i,Chr(9),1) ;for each function For $y=1 To $a[0] $p=$a[$y] ;split into <functionname for object> and <functionname in code> $za=StringSplit($p,' ',3) $n=$za[0] $fn=$za[1] ;handle destructor If $n=='destructor' Then ;Msg('adding destructor') ;$o.AddDestructor($n, $fn) _AutoItObject_AddDestructor($o,$fn) Else ;handle iterator (enums) If $n=='EnumNext' Then $enums[0]=$p ElseIf $n=='EnumReset' Then $enums[1]=$p ElseIf $n=='EnumSkip' Then $enums[2]=$p Else ;handle normal _AutoItObject_AddMethod($o,$n,$fn,$scope) EndIf EndIf Next Next ;now build iterators (enums) If $enums[0]<>'' Then ;TODO:error handling If $enums[1]<>'' Then If $enums[2]<>'' Then _AutoItObject_AddEnum($o,$enums[0],$enums[1],$enums[2]) Else _AutoItObject_AddEnum($o,$enums[0],$enums[1]]) EndIf EndIf EndIf Return $o EndFunc Any feedback is welcome, especially information on the limits of AIO.
martin Posted July 8, 2013 Posted July 8, 2013 (edited) RafaelMaciel, I think I did warn you when I gave a reply to you original post that it looked like a bug but that I could be wrong. And I was absolutely right, I was wrong. What we should have done was to read the manual! If you look at the first post that Prog@ndy made, he stated, amongst other things, Q. My GUI freezes! Why and how do I fix it? All methods are essentially dllcallbacks. Unfortunately this means that messages are not processed while your methods are being executed. As long as you keep your main loop outside any method, you'll be fine. So I modified the example I produced as below, and lo and behind, we are fine! expandcollapse popup#include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include "C:\Program Files\Autoit3\include\AutoitObject.au3" Dim $doexit dim $AnalistaFormMain _AutoItObject_StartUp() extern2("Window 1") ;create window without using objects While $doexit = 0 Sleep(30) WEnd Global $C_Analista = _Analista_create();global detentora do objeto ANALISTA $C_Analista.formMain While $doexit = 0 Sleep(30) WEnd $C_Analista = 0;destroy the object _AutoItObject_Shutdown();don't forget this line although the examples do Func _Analista_create() Local $oClassObject = _AutoItObject_Class() $oClassObject.Create() $oClassObject.AddMethod("formMain", "_Analista_main") $oClassObject.AddDestructor("_DestructorForAnalista") Return $oClassObject.Object EndFunc ;==>_Analista_create Func _Analista_main($oSelf) extern2("window from object") EndFunc ;==>_Analista_main Func extern2($title) AutoItSetOption("guioneventmode", 1) $doexit = 0 #region ### START Koda GUI section ### $AnalistaFormMain = GUICreate($title, 224, 438, 10, 10);, BitOR($WS_SYSMENU, $WS_BORDER, $WS_CAPTION)) GUISetState(@SW_SHOW) #endregion ### END Koda GUI section ### ConsoleWrite("step 4" & @LF) GUISetOnEvent($GUI_EVENT_CLOSE, "CloseGui") EndFunc ;==>extern2 Func CloseGui() ConsoleWrite("close gui?" & @LF) GUIDelete($AnalistaFormMain) $doexit = 1 EndFunc ;==>CloseGui Func _DestructorForAnalista($oSelf) ConsoleWrite("!...destructing... 'Analista'" & @CRLF) GUIDelete($AnalistaFormMain) EndFunc ;==>_DestructorForAnalista Edited July 8, 2013 by martin Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
LateArrival Posted July 9, 2013 Posted July 9, 2013 Cross-Posting from here:'?do=embed' frameborder='0' data-embedContent>> "Hi (probably replying to late to this but I just came across it whilst looking for something else) It is not a good idea to put your main loop inside a method. Basically the code will run inside the method and it doesn't get a chance to process your input. Here is an alternative approach (hope it helps)" expandcollapse popup#include 'AutoitObject.au3' #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> _AutoItObject_StartUp() #region Form Class ======================================== Func Form() Local $this = _AutoItObject_Class() ; field properties $this.AddProperty('Handle', $ELSCOPE_READONLY) $this.AddProperty('IsInitialised', $ELSCOPE_READONLY, False) ; get/set propeties $this.AddMethod('Visible', '___Form_Visible') ; methods $this.AddMethod('Load', '___Form_Load') ; destructors $this.AddDestructor('_Analista_Finalise') Return $this.Object EndFunc ;==>Form ;------------------------------------------------------- Func ___Form_Load($self, $iCaption = 'Form', $iLeft = Default, $iTop = Default, $iWidth = Default, $iHeight = Default, $iStyle = Default, $iStyleEx = Default) $self.Handle = String(GUICreate($iCaption, $iWidth, $iHeight, $iLeft, $iTop, $iStyle, $iStyleEx)) $self.IsInitialised = True EndFunc ;==>___Form_Load ;------------------------------------------------------- Func ___Form_Visible($self, $iVisible = Default) If Not $self.IsInitialised Then Return SetError(1) Switch @NumParams Case 1 ; get Return (BitAND(WinGetState(HWnd($self.Handle), ''), 2) = 1) ; 2 = Window is visible Case 2 ; set If Not IsBool($iVisible) Then Return SetError(2) Switch $iVisible Case True Return WinSetState(HWnd($self.Handle), '', @SW_SHOW) Case False Return WinSetState(HWnd($self.Handle), '', @SW_HIDE) EndSwitch EndSwitch EndFunc ;==>___Form_Visible ;------------------------------------------------------- Func ___Form_Finalise($self) If Not $self.IsInitialised Then Return SetError(1) GUIDelete(HWnd($self.Handle)) EndFunc ;==>___Form_Finalise #endregion Form Class ======================================== ; Main Program Global $C_Analista = Form() ;~ $C_Analista.Load('Analista', 10, 10, 224, 438, BitOR($WS_SYSMENU, $WS_BORDER, $WS_CAPTION)) $C_Analista.Load('Analista') $C_Analista.Visible = True While 1 $nMsg = GUIGetMsg() ConsoleWrite('!...Tela travada' & @CRLF) Switch $nMsg Case $GUI_EVENT_CLOSE $C_Analista.Visible = False $C_Analista = 0 _AutoItObject_Shutdown() Exit EndSwitch WEnd
MarkRobbins Posted July 10, 2013 Posted July 10, 2013 About Ptrs and Hwnds in AIO The docs weren't so clear on this, so I am posting my little goose chase here for posterity. expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <AutoItObject.au3> ; =============================================================================================================================== ; Background: In attempting to use AutoItObject, I discover neither fields nor function return types can be Ptr. ; Though the docs say Ptrs cannot be params, and we cannot pass ByRef, it does not say anything about ; field types and return types. ; Ptr values will be converted to Int32, making it impossible to create an assignable hwnd property on ; an AutoItObject. ; This means you can create the assignable, but every time you use it you must wrap it in an HWnd(). ; This holds true whether you are inside the object or a client ; Here is an example of the code to assign as a method, which will create an assignable: #cs Func Hwnd__FormObj($me,$value='0') If @NumParams = 2 Then ;am assigning ;could store it in backer as Int32 auto-not-magically via simple assignment, but doing it as string here $me._Hwnd='0x'&hex($value) Else ;am being read ;this returns an Int32, not an Hwnd. See below Return hwnd(int($s)) EndIf EndFunc #ce ; This is the usage inside the object #cs Func WinMove__FormObj($me,$x,$y) ;note the conversion, same applies when you are client of class, ie HWnd($obj.Hwnd) Return WinMove(HWnd($me.Hwnd),"",$x,$y) EndFunc #ce ; =============================================================================================================================== ; debug util, can be anything, has no external effect Global $thisfile='C:\batch\borg\BadHwndTest.au3' Global $hGui ; setup for AIO _AutoItObject_Startup() OnAutoItExitRegister("EvtScriptExit") Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") ; spec Global $wintitle="TargetWindow" ; create our AIO Global $AIO=AutoItObjCtor() ; globals for testing Global $hgui_as_str Global $hgui_as_hwnd Global $hgui_as_str_from_aio Global $hgui_as_hwnd_from_aio ; debug testing var Global $inform_step=0 ;Make it Example1() Exit ; Main Func Example1() Local $msg $hGui=GUICreate($wintitle) GUISetState(@SW_SHOW) ; BEGIN TESTING $hgui_as_str='0x'&hex($hGui) Inform('With $hgui_as_str="0x"&hex($hGui), we have a valid str', _ "Using $hgui_as_str. Is typical and will show hwnd in hex form 0x????????:"&@CRLF&$hgui_as_str) ; $hgui_as_hwnd=Hwnd(Int($hgui_as_str)) Inform('With $hgui_as_hwnd=Hwnd(Int($hgui_as_str)), we convert $hgui_as_str to hwnd', _ "Using $hgui_as_hwnd. Is typical and will show window title '"&$wintitle&"':"&@CRLF&WinGetTitle($hgui_as_hwnd,"")); all is well ; $AIO.hwnd_as_str=$hgui_as_str Inform('With $AIO.hwnd_as_str=$hgui_as_str, we prepare to let the AutoItObject do the conversion...', _ "Using $AIO.GetHwnd(). Will Fail with 0, should show title '"&$wintitle&"':"&@CRLF&WinGetTitle($AIO.GetHwnd())); ; Inform('But, We ARE getting a handle', _ "Using hex($AIO.GetHwnd()). Will Succeed and show hwnd in hex form 0x????????:"&@CRLF&'0x'&hex($AIO.GetHwnd())) ; Inform('Compare Object Types with VarGetType()', _ "Using $hGui, $AIO.GetHwnd(). Aha, is returning Int32 not Ptr:"&@CRLF&'$hGui:'&VarGetType($hGui)&@CRLF&'$AIO.GetHwnd():'&VarGetType($AIO.GetHwnd())) ; Inform('Try Convering the Int32 to Hwnd', _ "Using $AIO.GetHwnd(). Will Succeed and should show title '"&$wintitle&"':"&@CRLF&WinGetTitle(Hwnd($AIO.GetHwnd()))); ; $AIO.hwnd_as_hwnd=$hGui Inform('With $AIO.hwnd_as_hwnd, Can a field be a hwnd?', _ "Using VarGetType($AIO.hwnd_as_hwnd). No, it cannot:"&@CRLF&'$hGui:'&VarGetType($hGui)&@CRLF&'$AIO.hwnd_as_hwnd:'&VarGetType($AIO.hwnd_as_hwnd)) While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete() EndFunc ;==>Example1 ; Begin AIO stuff Func AutoItObjCtor() Local $me = _AutoItObject_Create() _AutoItObject_AddProperty($me,"hwnd_as_str",$ELSCOPE_PUBLIC,'') _AutoItObject_AddProperty($me,"hwnd_as_hwnd",$ELSCOPE_PUBLIC,'') _AutoItObject_AddMethod($me,"GetHwnd","_AutoItObj_GetHwnd") _AutoItObject_AddMethod($me,"ProveCanReturnHwnd","_AutoItObj_ProveCanReturnHwnd") Return $me EndFunc Func _AutoItObj_GetHwnd($me) Msg('In _AutoItObj_GetHwnd(),$me.hwnd_as_str:'&$me.hwnd_as_str) ;HERE! hwnd function does not work, or so I thought, the real problem is cannot return an Hwnd Return hwnd(int($me.hwnd_as_str)) EndFunc Func _AutoItObj_ProveCanReturnHwnd($me) Msg('In _AutoItObj_ProveCanReturnHwnd, goint to return $hGui:0x'&hex($hgui)) Return $hGui; EndFunc ;UTILS Func Msg($s) MsgBox(0,$thisfile,$s) EndFunc Func Inform($t,$s) $inform_step+=1 $s='Step '&$inform_step&@CRLF&$s MsgBox(0,$t,$s) EndFunc Func _ErrFunc() Local $line="[COM Error]:s"&$oError.source&" ScriptLine(" & $oError.scriptline & ") : Number 0x" & Hex($oError.number, 8) & " - " & $oError.windescription Msg($line) EndFunc
MarkRobbins Posted July 25, 2013 Posted July 25, 2013 BUG!: Whats so special about 'E3'? Cannot use this name as a method? expandcollapse popup#include <AutoItObject.au3> OnAutoItExitRegister("EvtScriptExit") _AutoItObject_StartUp() Global $o=_AutoItObject_Create() ;BUG: Cannot seem to make a property-type method called E3, other names work however MsgBox(0,'VarGetType($o)',VarGetType($o));checkit ;Change this to false to show the bug Global $make_it_work=True If Not $make_it_work Then ;Make an E3 property and backer _AutoItObject_AddProperty($o,'_E3',$ELSCOPE_PUBLIC,'initialized') _AutoItObject_AddMethod($o,'E3','E3_property',False) Else ;Make an F3 property and backer _AutoItObject_AddProperty($o,'_E3',$ELSCOPE_PUBLIC,'initialized') _AutoItObject_AddMethod($o,'F3','E3_property',False); THIS LINE DIFFERS IN NAME ONLY 'F3' EndIf If Not $make_it_work Then MsgBox(0,'$o.E3',$o.E3); ERROR Error in expression at $o.E3 Else MsgBox(0,'$o.F3',$o.F3); Not a problem EndIf Func E3_property($me,$value=-1) If @NumParams==2 Then $me._E3=$value Else Return $me._E3 EndIf EndFunc Func EvtScriptExit() _AutoItObject_Shutdown() EndFunc
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now