Popular Post LarsJ Posted July 16, 2021 Popular Post 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 Skysnake, 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
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