Popular Post LarsJ Posted July 16, 2021 Popular Post Share Posted July 16, 2021 (edited) Using an Object as Element in a Const Array In this post, an object is used as an element in a constant array. Still, it's possible to change an object property. How is that possible? Object variables access the object itself through a reference (pointer). A simple object variable can be created with the Dictionary object. Dictionary ObjectExamples\Example0.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $oDict1 = ObjCreate( "Scripting.Dictionary" ) ; Object reference counter = 1 Local $oDict2 = $oDict1 ; Object reference counter = 2 $oDict1.Item( "$vVar" ) = 123 $oDict1 = 0 ; Object reference counter = 1 ConsoleWrite( "$oDict2.Item( ""$vVar"" ) = " & $oDict2.Item( "$vVar" ) & @CRLF ) $oDict2 = 0 ; Object reference counter = 0 that deletes the object EndFunc #cs $oDict2.Item( "$vVar" ) = 123 #ce The variables $oDict1 and $oDict2 both refer to the same object. The Item property can be set with $oDict1 and read with $oDict2 and vice versa. Examples\Example1.au3: expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include "..\Includes\InspectVariable.au3" Example() Func Example() Local $oDict1 = ObjCreate( "Scripting.Dictionary" ), $oDict2 = $oDict1 ConsoleWrite( "$oDict1" & @CRLF ) ConsoleWrite( "Type = " & VarGetType( $oDict1 ) & @CRLF ) AccessVariables01( InspectVariableMtd, $oDict1 ) ConsoleWrite( @CRLF ) ConsoleWrite( "$oDict2" & @CRLF ) ConsoleWrite( "Type = " & VarGetType( $oDict2 ) & @CRLF ) AccessVariables01( InspectVariableMtd, $oDict2 ) ConsoleWrite( @CRLF ) ConsoleWrite( "Ptr( $oDict1 ) = " & Ptr( $oDict1 ) & @CRLF ) EndFunc #cs $oDict1 Type = Object ptr = 0x00000000005CB110 ($pVariant) vt = 0x0009 (VT_DISPATCH, pointer to object) data = 0x00000000005B02B0 $oDict2 Type = Object ptr = 0x00000000005CB150 ($pVariant) vt = 0x0009 (VT_DISPATCH, pointer to object) data = 0x00000000005B02B0 Ptr( $oDict1 ) = 0x00000000005B02B0 #ce The InspectVariable.au3 UDF from Accessing AutoIt Variables is used to examine $oDict1 and $oDict2. Today we know that AutoIt variables are internally stored in variant structures. For object variables, the variant type is VT_DISPATCH, and the data field contains a pointer (reference) to the object. Note that this pointer has the same value for both object variables. And that it's the same pointer as returned by Ptr( $oDict1 ). The Item property of the Dictionary object is also a variant that can store all AutoIt data types. DllStruct TypeExamples\Example2.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $tagStruct = "struct;int var1;byte var2;uint var3;char var4[128];endstruct" Local $tStruct = DllStructCreate( $tagStruct ) DllStructSetData( $tStruct, "var1", -100 ) DllStructSetData( $tStruct, "var2", 255 ) DllStructSetData( $tStruct, "var3", 300 ) DllStructSetData( $tStruct, "var4", "Hello" ) Local $oDict1 = ObjCreate( "Scripting.Dictionary" ) Local $oDict2 = $oDict1 $oDict1.Item( "$tStruct" ) = $tStruct ConsoleWrite( "DllStructGetData( $oDict2.Item( ""$tStruct"" ), ""var3"" ) = " & DllStructGetData( $oDict2.Item( "$tStruct" ), "var3" ) & @CRLF ) EndFunc #cs DllStructGetData( $oDict2.Item( "$tStruct" ), "var3" ) = 300 #ce Array TypeAutoIt arrays are internally stored as safearrays of variants. Ie. the array itself is a safearray and the array elements are variant structures. Examples\Example3.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $oDict1 = ObjCreate( "Scripting.Dictionary" ) Local $oDict2 = $oDict1 Local $aArray[5] = [ 0, 1, 222, 3, 4 ] $oDict1.Item( "$aArray" ) = $aArray ConsoleWrite( "$oDict2.Item( ""$aArray"" )[2] = " & $oDict2.Item( "$aArray" )[2] & @CRLF ) ; $oDict1.Item( "$aArray" )[3] = 333 ; Error: Statement cannot be just an expression Local $aMyArray = $oDict1.Item( "$aArray" ) $aMyArray[3] = 333 $oDict1.Item( "$aArray" ) = $aMyArray ConsoleWrite( "$oDict2.Item( ""$aArray"" )[3] = " & $oDict2.Item( "$aArray" )[3] & @CRLF ) EndFunc #cs $oDict2.Item( "$aArray" )[2] = 222 $oDict2.Item( "$aArray" )[3] = 333 #ce Const ArrayA consequence of an object variable having access to the object itself through a reference makes it possible to store an object variable in a constant array (or constant variable) and still be able to change an object property. Since a change of an object property doesn't change the array element (or variable) that refers to the object, the property change doesn't conflict with a constant array (or variable). Examples\Example4.au3: expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict.Item( "Int" ) = 1 $oDict.Item( "Flt" ) = 1.1 $oDict.Item( "Str" ) = "One" ;Local $aArray[1] = [ $oDict ] Local Const $aArray[1] = [ $oDict ] ; Local Const $oDict = 0 ConsoleWrite( "$aArray[0].Item( ""Int"" ) = " & $aArray[0].Item( "Int" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Flt"" ) = " & $aArray[0].Item( "Flt" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Str"" ) = " & $aArray[0].Item( "Str" ) & @CRLF & @CRLF ) #cs ; Direct modification of the $aArray values in this way doesn't work ; But it does work if you remove "Const" in the declaration of $aArray $aArray[0].Item( "Int" ) = 2 ; Error: $aArray previously declared as a 'Const' $aArray[0].Item( "Flt" ) = 2.2 ; Error: $aArray previously declared as a 'Const' $aArray[0].Item( "Str" ) = "Two" ; Error: $aArray previously declared as a 'Const' ConsoleWrite( "$aArray[0].Item( ""Int"" ) = " & $aArray[0].Item( "Int" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Flt"" ) = " & $aArray[0].Item( "Flt" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Str"" ) = " & $aArray[0].Item( "Str" ) & @CRLF & @CRLF ) #ce ;#cs ; Indirect modification of the $aArray values in this way does work Local $oMyDict = $aArray[0] $oMyDict.Item( "Int" ) = 2 $oMyDict.Item( "Flt" ) = 2.2 $oMyDict.Item( "Str" ) = "Two" $oMyDict = 0 ConsoleWrite( "$aArray[0].Item( ""Int"" ) = " & $aArray[0].Item( "Int" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Flt"" ) = " & $aArray[0].Item( "Flt" ) & @CRLF ) ConsoleWrite( "$aArray[0].Item( ""Str"" ) = " & $aArray[0].Item( "Str" ) & @CRLF & @CRLF ) ;#ce EndFunc #cs $aArray[0].Item( "Int" ) = 1 $aArray[0].Item( "Flt" ) = 1.1 $aArray[0].Item( "Str" ) = One $aArray[0].Item( "Int" ) = 2 $aArray[0].Item( "Flt" ) = 2.2 $aArray[0].Item( "Str" ) = Two #ce This example is similar to the example in the link at top of post. 7z-fileThe 7z-file contains source code for UDFs and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. Misc.7z Edited July 16, 2021 by LarsJ Gianni, mLipok, Werty and 2 others 4 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
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