Leaderboard
Popular Content
Showing content with the highest reputation on 12/08/2019 in all areas
-
... Nice ...and this is useful for which application? ... and what is the For..Next loop used for? Jos3 points
-
UI Automation Events In standard Windows GUI code, you can respond to Windows messages by registering and implementing a message handler function. A WM_NOTIFY message handler is registered and implemented in this way: ; Registration GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" ) ; Implementation Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) ; Code EndFunc The WM_NOTIFY function is a callback function. In UI Automation code, you can respond to UI Automation events by registering and implementing an event handler object. A FocusChangedEventHandler object is registered and implemented in this way: ; Registration UIAEH_FocusChangedEventHandlerCreate() $oUIAutomation.AddFocusChangedEventHandler( 0, $oUIAEH_FocusChangedEventHandler ) ; Implementation ; This is the function that receives events Func UIAEH_FocusChangedEventHandler_HandleFocusChangedEvent( $pSelf, $pSender ) ; Code EndFunc $oUIAEH_FocusChangedEventHandler is the event handler object. It's a callback object. This thread is about how to respond to UI Automation events by registering, implementing and using event handler objects. User Defined Functions Registering and implementing the event handler object in the code above is very simple. To make it that simple, it's necessary to include a few functions in a UDF. The zip-file at bottom of post contains a UIAEH_FocusChangedEventHandler.au3 UDF that allows the registration and implementation of the event handler object as simple as shown above. UIAEH_FocusChangedEventHandlerCreate() is a function in this UDF. The function creates the $oUIAEH_FocusChangedEventHandler object. Because this is a callback object it must be implemented through ObjectFromTag() (coded in ObjectFromTag.au3 in zip-file) function by trancexx and not through the usual ObjCreateInterface() which is used to create other UI Automation objects. (The warning at top of the help text is much more an error in the help text than an error in the function. Thousands of examples show that ObjCreateInterface() works flawlessly.) You don't need to use ObjectFromTag() in your own code. This function is completely handled in the UDFs. UIAEH_FocusChangedEventHandler_HandleFocusChangedEvent() is the function that receives events. This function is coded but commented out in UIAEH_FocusChangedEventHandler.au3. Copy this function to your own code. See FocusChangedEventHandler example below. UIA Event Handlers The first version of Microsoft's UI Automation code (the Windows 7 version that works on Windows XP, Windows Vista, Windows 7 and all later versions) implements four different event handler objects. In addition to the FocusChangedEventHandler object, it's the AutomationEventHandler, PropertyChangedEventHandler and StructureChangedEventHandler objects. The zip-file at the bottom contains the corresponding three event handler UDFs. By the way, these four event handlers are implemented in AutoIt several years ago in this and the following posts. FocusChangedEventHandler exposes a method to handle events that are raised when the keyboard focus moves to another UI Automation element. AutomationEventHandler exposes a method to handle Microsoft UI Automation events. These events include MenuOpened ($UIA_MenuOpenedEventId) and Window_WindowOpened ($UIA_Window_WindowOpenedEventId) events. See module UIA_EventIds in UIA_Constants.au3 for a complete list. Note that EventIds that belong to Windows 8 or later cannot be used in this version of the event handler. But they can be used after code updates over the coming weeks. 2019-12-15 If you select Desktop, AutomationEvent and all Events (Event Ids) in UI Automation Event Monitor below and click Start, you'll see the following output in SciTE console: $oUIAEH_AutomationEventHandler OK Desktop: AddAutomationEventHandler() = AsyncContentLoaded OK Desktop: AddAutomationEventHandler() = AutomationFocusChanged ERR Desktop: AddAutomationEventHandler() = AutomationPropertyChanged OK Desktop: AddAutomationEventHandler() = InputDiscarded OK Desktop: AddAutomationEventHandler() = InputReachedOtherElement OK Desktop: AddAutomationEventHandler() = InputReachedTarget OK Desktop: AddAutomationEventHandler() = Invoke_Invoked OK Desktop: AddAutomationEventHandler() = LayoutInvalidated OK Desktop: AddAutomationEventHandler() = MenuClosed OK Desktop: AddAutomationEventHandler() = MenuModeEnd OK Desktop: AddAutomationEventHandler() = MenuModeStart OK Desktop: AddAutomationEventHandler() = MenuOpened OK Desktop: AddAutomationEventHandler() = Selection_Invalidated OK Desktop: AddAutomationEventHandler() = SelectionItem_ElementAddedToSelection OK Desktop: AddAutomationEventHandler() = SelectionItem_ElementRemovedFromSelection OK Desktop: AddAutomationEventHandler() = SelectionItem_ElementSelected OK Desktop: AddAutomationEventHandler() = StructureChanged OK Desktop: AddAutomationEventHandler() = Text_TextChanged OK Desktop: AddAutomationEventHandler() = Text_TextSelectionChanged OK Desktop: AddAutomationEventHandler() = ToolTipClosed OK Desktop: AddAutomationEventHandler() = ToolTipOpened OK Desktop: AddAutomationEventHandler() = Window_WindowClosed OK Desktop: AddAutomationEventHandler() = Window_WindowOpened OK Note the error for the AutomationFocusChanged event handler (at the top of the list). I've found that there is an error, but so far have no explanation for it. PropertyChangedEventHandler exposes a method to handle Microsoft UI Automation events that occur when a property is changed. These events include Name ($UIA_NamePropertyId) and ValueValue ($UIA_ValueValuePropertyId) changes. See module UIA_PropertyIds in UIA_Constants.au3 for a complete list. Note that PropertyIds that belong to Windows 8 or later cannot be used in this version of the event handler. But they can be used after code updates over the coming weeks. StructureChangedEventHandler exposes a method to handle events that occur when the Microsoft UI Automation tree structure is changed. This event handler seems to be more valuable in eg. screen readers than in usual UI Automation code. NotificationEventHandler exposes a method to handle Microsoft UI Automation notification events. See this post. FocusChangedEventHandler example This is full code in Examples\FocusChangedEventHandlerEx.au3. Run the code in SciTE with F5. #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\UIAEH_FocusChangedEventHandler.au3" Example() Func Example() UIAEH_FocusChangedEventHandlerCreate() If Not IsObj( $oUIAEH_FocusChangedEventHandler ) Then Return ConsoleWrite( "$oUIAEH_FocusChangedEventHandler ERR" & @CRLF ) ConsoleWrite( "$oUIAEH_FocusChangedEventHandler OK" & @CRLF ) Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) Local $iError = $oUIAutomation.AddFocusChangedEventHandler( 0, $oUIAEH_FocusChangedEventHandler ) If $iError Then Return ConsoleWrite( "AddFocusChangedEventHandler() ERR" & @CRLF ) ConsoleWrite( "AddFocusChangedEventHandler() OK" & @CRLF ) HotKeySet( "{ESC}", "Quit" ) While Sleep(10) WEnd EndFunc Func Quit() UIAEH_FocusChangedEventHandlerDelete() Exit EndFunc ; This is the function that receives events Func UIAEH_FocusChangedEventHandler_HandleFocusChangedEvent( $pSelf, $pSender ) ; Ret: long Par: ptr ConsoleWrite( @CRLF & "UIAEH_FocusChangedEventHandler_HandleFocusChangedEvent: " & $pSender & @CRLF ) Local $oSender = ObjCreateInterface( $pSender, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) $oSender.AddRef() ConsoleWrite( "Title = " & UIAEH_GetCurrentPropertyValue( $oSender, $UIA_NamePropertyId ) & @CRLF & _ "Class = " & UIAEH_GetCurrentPropertyValue( $oSender, $UIA_ClassNamePropertyId ) & @CRLF & _ "Ctrl type = " & UIAEH_GetCurrentPropertyValue( $oSender, $UIA_ControlTypePropertyId ) & @CRLF & _ "Ctrl name = " & UIAEH_GetCurrentPropertyValue( $oSender, $UIA_LocalizedControlTypePropertyId ) & @CRLF & _ "Handle = " & "0x" & Hex( UIAEH_GetCurrentPropertyValue( $oSender, $UIA_NativeWindowHandlePropertyId ) ) & @CRLF & _ "Value = " & UIAEH_GetCurrentPropertyValue( $oSender, $UIA_ValueValuePropertyId ) & @CRLF ) Return 0x00000000 ; $S_OK #forceref $pSelf EndFunc ; Auxiliary function (for simple properties only) ; There must be only one instance of this function Func UIAEH_GetCurrentPropertyValue( $oSender, $iPropertyId ) Local $vPropertyValue $oSender.GetCurrentPropertyValue( $iPropertyId, $vPropertyValue ) Return $vPropertyValue EndFunc Test the code by opening the Desktop context menu and move the mouse over the menu items. When the mouse hovers over a menu item it gets focus. Exit with Esc. AutomationEventHandlerEx.au3 Test the example by opening some windows, menus and tooltips. PropertyChangedEventHandlerEx.au3 Open Windows Task Manager (Ctrl+Shift+Esc) and you'll get a whole bunch of property changed events. Note that to access Windows Task Manager (and other programs) on Windows 10, use #RequireAdmin in the script and run SciTE as administrator. StructureChangedEventHandlerEx.au3 Clicking on a folder in File/Windows Explorer treeview generates a lot of structure changed events. New examples will be added over the coming weeks. UI Automation Event Monitor UI Automation Event Monitor is a tool to detect UI Automation events. The first group of toolbar buttons is used to set up the UI Automation event handler. The images have a PropertyChangedEventHandler set up to monitor Name ($UIA_NamePropertyId) and ValueValue ($UIA_ValueValuePropertyId) property changes in Windows Task Manager. Note that to access Windows Task Manager (and other programs) on Windows 10, use #RequireAdmin in the script (UIAEHEvents.au3) and run SciTE as administrator. These four toolbar buttons are hot-track enabled with the technique used in this example. The buttons open four listviews to set up the event handler. All listviews have multiple selections enabled. Select multiple items at once and check a single item in/out to check all selected items in/out. Use mouse or Space key to check an item in/out. In the first image, the mouse hovers over the Top Windows button so that it's selected. In the second image, the Top Windows button is clicked so that the listview is opened. Moving the mouse over the next three buttons automatically opens the corresponding listviews due to hot-tracking. Click the toolbar button again to close the listview or move the mouse above the title bar. Windows Task Manager is checked in the Top Windows listview. The Event Handlers listview is enabled when a Top Window is checked. The Event Ids listview is enabled when the AutomationEvent event handler is checked. The Property Ids listview is enabled when the PropertyChanged event handler is checked. In Event Ids and Property Ids listview you can select an item by pressing the first letter on the keyboard. The second group of toolbar buttons is used to Start/Stop the event handler (or multiple event handlers), Pause/Continue updating the Events listview, and Clear the listview. Note that the Pause button only stops updating the listview. Events are still detected and stored in $aEvents array. All new events are added at the bottom of the listview when you click Continue or Stop. The Pause Main Loop button is used to stop the GUI main loop, which significantly increases the performance of the Events listview. When the GUI main loop is paused you can only click the Continue Main Loop button (same button as Pause Main Loop) and you can close the GUI. Events listview The Events listview is a virtual listview because of performance and to make it easy to constantly add new rows to the bottom of the listview. Nevertheless, there can still be performance issues when a lot of events are generated. To remedy these issues, it's possible to stop the GUI main loop with the Pause Main Loop button. This significantly increases the performance of the Events listview. When there are a large number of events (when many new rows are added quickly at the bottom of the listview), this procedure must be followed to stop the event handler (or multiple event handlers): Make sure the GUI main loop isn't paused. Click the Pause button (second toolbar group) to pause Events listview updates. Click the Stop button to stop the event handler. When there are a small number of events you can immediately click the Stop button. To test the UI Automation Event Monitor, try performing the four examples (in Examples\, briefly described above) through the monitor GUI. There'll probably be some GUI updates in the coming weeks. UIA Menu, Tooltip and Window Events Monitor is a simpler version of UI Automation Event Monitor that detects only MenuOpened, ToolTipOpened and Window_WindowOpened events (AutomationEvents). Updates Windows 8, Windows 8.1 and Windows 10 updates Threads UI Automation UDFs contains all include files. UIASpy - UI Automation Spy Tool is a GUI tool that provides information about windows and controls and their interconnection and provides functionality to generate sample code. UIASpy is essential for creating UI Automation code. In Using UI Automation Code in AutoIt you can find and download examples and read information about using UIA code. IUIAutomation MS framework automate chrome, FF, IE, .... created by junkew August 2013 is the first AutoIt thread on UIA code. Zip-file The zip contains source files for GUIs and examples. Note that UI Automation UDFs must be installed in the Includes folder. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Note that under Windows 7 and earlier versions, only the original four event handlers (AutomationEventHandler, FocusChangedEventHandler, PropertyChangedEventHandler, StructureChangedEventHandler) introduced in Windows 7 can be used. Comments are welcome. Let me know if there are any issues. UIAEHEvents.7z2 points
-
dHash generates a “difference hash” for a given image - a perceptual hash based on Neal Krawetz’s dHash algorithm in this “Hacker Factor” blog entry. http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html 1. Reduce size 2. Reduce color 3. Compute the difference 4. Assign bits The resulting hash value represents the relative change in brightness intensity. To compare two hashes, just count the number of bits that are different (called Hamming distance.) A value of 0 indicates the same hash and likely a similar picture. A value greater than 10 is likely a different image, and a value between 1 and 10 is potentially a variation. dHs - dHash_v0003.zip2 points
-
URL is meant literally for that command: $sCommand = '{"command":["loadfile", "file:///' & StringReplace($s_Global_Path_MediaFile, "\", "/") & '","replace"]}' & @LF1 point
-
ListView export speed
pixelsearch reacted to jpm for a topic
Awsome work I check carefully my conclusion you optimise carefullt the use of _GUICtrlListView_GetItemText() when use in loops 😎1 point -
one more #include<array.au3> $aIni = IniReadSection("colours.ini", "colours") For $i = 1 to ubound($aIni) - 1 _ArraySwap($aIni , $i , _ArrayMinIndex($aIni , 1 , $i)) Next _ArrayDisplay($aIni)1 point
-
OK. It took me some time to partly digest this. I focus on the actual data you'll be storing and querying. The rest of your program workflow is something completely separate. So from what I gathered, you have to store at least countries, their states and potentially many abbreviations for them. Alongside you also have to deal with a list of apps (whatever that means) and the preference they have set for conversion of the above data. I'd advise that you download a good 3rd-party SQLite DB manager, like SQLite Expert (the freeware version offers a lot of features without nagware, adware nor anything). Take some time to tour the thing, play with examples. That tool will allow you to easily setup DB schemas (with some help), try them on real-world or example data, execute queries and determine what to change until the result is satisfactory w.r.t. your context. A database is organized in tables (think "mahematical sets", an SQL table has no intrinsic order😞 a number of rows (like in a spreadsheet) and one or more columns which store attributes for the row. A row must have a unique ID, generally a meaningless unique integer (somehow similar to the name or memory address of a variable). You may have to create one or more indices to speed up searching the data in the table. A typical DB contains several tables, most of the time related by strong relationships and satisfying some constraints. The goal of a DB schema (its design) is to enforce those constraints and relationships in all cases. For instance a genealogy DB must satisfy that noone is it's own parent, noone is his sister parent, that everyone has one male and one female parent... Even on what seems a trivial example, you can feel that "parent" and "parenthood" has to be made rigourous notions to deal with real-world cases (adoption vs biological parents, gamete donation, gay parents, surrogate mother, transgender, whatelse). If you don't precisely enough define the entities and their relationships, your DB is going to make you very sorry some day. Countries: the ISO codes (ISO2 & ISO3, i.e. US & USA, but some countries don't have an ISO3 code assigned) are good candidates to identify a country. Yet, some countries aren't recognized in some contexts! More fuzzy are country names: there are several "official standards" to choose from and this gets worse with country names translations: is my country France, Frankreich, Frànkrich, Frankrijk, Francia, Francià, França, Γαλλία, Fransän, Франция, საფრანგეთი, کومرٱ ڤلات فرانسٱ , whatelse? Depending on your use, you'll have to store translations of country names elsewhere from fixed columns of the country table for as many languages or standard of your choice, or choice of the apps you deal with. That needs to be precisely defined as you'll see below with examples. Countrynames (nicknames) are stored in a separate table, each with a link to their row in country table. This machinery is the opposite to data pointers in many IT languages: here, the child "points" to the parent. This is called a foreign key in DB world. 'Foreign' in that it links an entry in one table to one entry in another table, here the country table. States within a given country: a state has to be in relationship with one and only one country, even if one can find states with the same name in distinct countries. In some countries "region" has the same meaning as "state in the US". A state will carry a unique ID (say an integer), one name or abbreviation or translation AND a key to a country (the ID of the country, also an integer). This is a many to one relationship (names to countries). Now if you'll have to handle countries and/or states/regions in several languages, you'll find it much easier to have created table linking a name with a unique country (another foreign key). This way you can search this table for "Франция" and using the foreign key, find that it refers to FR (ISO2) or FRA (ISO3). If you choose a wrong design and store alternative/translated names or abbreviations in columns of the country table, you'd have to search every such column separately, involving more work and more maintenance if things evolve. OTOH, with such a separate table you can instantly list all know names of a country, or all states/region in a country, all with one fast query. String are stored internally as Unicode (as you can see in table currencies). You can search case-sensitively or not, use wildcards % and _ (equivalent for DOS * and ?) and even use add-on functions like fuzzy search or regex (compatible with AutoIt PCRE). Trying to do the same with arrays is going to be messy and painful. I'm joining an example toy DB. Countries table derived from my own, countrynames in a restricted number of languages and conventions, currencies linked by foreign-key from the country table, statesnames in another table. As examples, you can list all the countrynames like '%anm%' by using the Name header of the countrynames table in the Data tab, or by using the following query in the SQL tab and hitting F5: select * from countrynames where countryname like '%anm%'; To find the ISO2 code and intl phone prefix for cyprus or chyprus or chypre or ..., and check that there is no ambiguity on the name (only one prefix should result): select distinct phoneintl from countries join countrynames using (countryid) where countryname like 'c%pr%'; Find a list of official ENiso names of countries using currencyISO 'AUD': select countryname from countrynames join countries using (countryid) join currencies using (currencyid) where currencyISO = 'AUD' and countrynamelang = 'EN' and countrynametype = 'ISO'; Obviously this example isn't any close to what you actually need but it should give you a global idea about where you're heading if you follow this route and how powerful the beast can be (and that's only the surface). Not every piece of data is complete in every table, I've rushed that from several pieces floating around. The table countrynames includes one extra unpopulated column: countrynametype. Feel free to populate these with some data of your own, countrynametype allowing you to classify what kind of name or abbreviation the row contains. States/regions/provinces use yet another table with foreign key to countries table. StateNames table gives alternate names or attributes to official states listed in States table. List all states of Australia with their codes and French names, order by statecode ascending: select distinct statecode, statename as FRname from countries join countrynames using(countryid) join states using (countryid) join statenames using (stateid) where countryname like 'australia' and statenamelang = 'FR' order by statecode You can have dozens or hundreds tables in a DB, large DBs can have hundreds thousand and reach 100 TB. Don't be afraid by syntax, I know it seems weird at first: it's always clearer and shorter than code which would produce the same result! SQL language allows you to precisely describe what you want, not how to get there. Abbrevs.sq3 Sorry folks for the text wall.1 point
-
It's way too early to provide any design advice since we have little clue about the actual set of requirements in your use case. There is a version of SQLite which allow strong encryption (see https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki), rendering the file --an SQLite DB is just a single file-- completely unintelligible to anyone not having state-size resources. Its enssentially transparent and shouldn't be a cycle hog. What you can do to avoid having a separate file is make it a resource of your program, extract it to use it, eventually changing it, then storing it back as a new resource in place of the initial one. It's a bit circonvoluted but that should work. The first step for you is to exhaustively list all entities that you'll be dealing with, their type, nature and their relationships. Then list the queries that you know you'll use most. Post a few examples of all these.1 point
-
Given the flexibility for storing that many variants and possibly a significant volume of data, I'd go for an SQLite database. It would support huge data, as many and complex tables you'll require, extremely powerful querying facilities and portability across any hadware/software platform you can think of.1 point
-
I would store all codes as global variable with initial value in your include file before function _StateConvertAU() like this: Global $g_Codes = _ "ACT=AUSTRALIAN CAPITAL TERRITORY#" & _ "NSW=NEW SOUTH WALES#" & _ ... & _ "NT=NORTHERN TERRITORY" $g_Codes = StringSplit($g_Codes, "#") Func _StateConvertAU($sState, $bAbbrev = False, $sAppName = "") ... EndFunc ;==> _StateConvertAU()1 point
-
The solution proposed by @rudi required that you have an .ini outside file. Take a look at FileInstall to pull the ini file from the compiled script into a temp folder that you can delete at script end. If that doesn't work you could add a file containing your conversion codes as a resource here : One other internal solution is to create a Global Const $Array[999][2] listing in it all the corresponding values of your conversion codes.1 point
-
Hi. [Apps] ; 0 = default behaviour ; 1 = always return Abrev ; 2 = always return Full App1=0 App2=1 App3=2 [Codes] Australian Capital Territory=ACT NEW SOUTH WALES=NSW NORTHERN TERRITORY=NT #include <Array.au3> #include <Debug.au3> $ReturnVal = StateConverter("NT") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ReturnVal = ' & $ReturnVal & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Func StateConverter($_input, $Short = 0, $sAppName = "") ; Col 0 = Abrev, Col 1 = Full Name switch $short case 0,1 $Col=$Short case else $Col=0 endswitch $INI = "C:\Temp\CountryTable.INI" $Sect = "Codes" $aCodes = IniReadSection($INI, $Sect) _DebugArrayDisplay($aCodes) $row = _ArraySearch($aCodes, $_input, 1) ; searching Col 0 = Full Names If $row = -1 Then $row = _ArraySearch($aCodes, $_input, 1, 0, 0, 0, 1, 1) ; searching Col 1 = Abreviations If $row = -1 Then ; Neither Col 0 nor Col 1 Return SetError(False, 1, $_input) EndIf EndIf $Sect = "apps" $default = 0 $ForceValue = IniRead($INI, $Sect, $sAppName, $default) ; $default = 0 : Return what func call asked for. 1 = Always Abrev, 2 = Always FullName Switch $ForceValue Case 0 $col = $Short Case 1 $col = 1 ; Abbrev Case 2 $col = 0 ; full name EndSwitch Return $aCodes[$row][$col] EndFunc ;==>StateConverter1 point
-
This week there have been some posts regarding use of compiled code in AutoIt through dll files and through C# and VB code via .NET. Use of compiled code is based, among other things, on Variants and Safearrays. This is an opportunity to distribute the latest updated version of these UDFs: Variant.au3 and SafeArray.au3. Variants and Safearrays are also used in UI Automation threads (Framework, UIASpy, Using) and in AutoItObject. In addition, references to these UDFs can be found in quite a number of posts. If you search for the UDFs it can be difficult to find the newest version. Hence this thread. Variant.au3: #include-once ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Copied from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy ; https://www.autoitscript.com/forum/index.php?showtopic=110379 Global Const $tagVARIANT = "word vt;word r1;word r2;word r3;ptr data; ptr" ; The structure takes up 16/24 bytes when running 32/64 bit ; Space for the data element at the end represents 2 pointers ; This is 8 bytes running 32 bit and 16 bytes running 64 bit Global Const $VT_EMPTY = 0 ; 0x0000 Global Const $VT_NULL = 1 ; 0x0001 Global Const $VT_I2 = 2 ; 0x0002 Global Const $VT_I4 = 3 ; 0x0003 Global Const $VT_R4 = 4 ; 0x0004 Global Const $VT_R8 = 5 ; 0x0005 Global Const $VT_CY = 6 ; 0x0006 Global Const $VT_DATE = 7 ; 0x0007 Global Const $VT_BSTR = 8 ; 0x0008 Global Const $VT_DISPATCH = 9 ; 0x0009 Global Const $VT_ERROR = 10 ; 0x000A Global Const $VT_BOOL = 11 ; 0x000B Global Const $VT_VARIANT = 12 ; 0x000C Global Const $VT_UNKNOWN = 13 ; 0x000D Global Const $VT_DECIMAL = 14 ; 0x000E Global Const $VT_I1 = 16 ; 0x0010 Global Const $VT_UI1 = 17 ; 0x0011 Global Const $VT_UI2 = 18 ; 0x0012 Global Const $VT_UI4 = 19 ; 0x0013 Global Const $VT_I8 = 20 ; 0x0014 Global Const $VT_UI8 = 21 ; 0x0015 Global Const $VT_INT = 22 ; 0x0016 Global Const $VT_UINT = 23 ; 0x0017 Global Const $VT_VOID = 24 ; 0x0018 Global Const $VT_HRESULT = 25 ; 0x0019 Global Const $VT_PTR = 26 ; 0x001A Global Const $VT_SAFEARRAY = 27 ; 0x001B Global Const $VT_CARRAY = 28 ; 0x001C Global Const $VT_USERDEFINED = 29 ; 0x001D Global Const $VT_LPSTR = 30 ; 0x001E Global Const $VT_LPWSTR = 31 ; 0x001F Global Const $VT_RECORD = 36 ; 0x0024 Global Const $VT_INT_PTR = 37 ; 0x0025 Global Const $VT_UINT_PTR = 38 ; 0x0026 Global Const $VT_FILETIME = 64 ; 0x0040 Global Const $VT_BLOB = 65 ; 0x0041 Global Const $VT_STREAM = 66 ; 0x0042 Global Const $VT_STORAGE = 67 ; 0x0043 Global Const $VT_STREAMED_OBJECT = 68 ; 0x0044 Global Const $VT_STORED_OBJECT = 69 ; 0x0045 Global Const $VT_BLOB_OBJECT = 70 ; 0x0046 Global Const $VT_CF = 71 ; 0x0047 Global Const $VT_CLSID = 72 ; 0x0048 Global Const $VT_VERSIONED_STREAM = 73 ; 0x0049 Global Const $VT_BSTR_BLOB = 0xFFF Global Const $VT_VECTOR = 0x1000 Global Const $VT_ARRAY = 0x2000 Global Const $VT_BYREF = 0x4000 Global Const $VT_RESERVED = 0x8000 Global Const $VT_ILLEGAL = 0xFFFF Global Const $VT_ILLEGALMASKED = 0xFFF Global Const $VT_TYPEMASK = 0xFFF ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ;Global Const $tagVARIANT = "word vt;word r1;word r2;word r3;ptr data; ptr" ; The structure takes up 16/24 bytes when running 32/64 bit ; Space for the data element at the end represents 2 pointers ; This is 8 bytes running 32 bit and 16 bytes running 64 bit #cs DECIMAL structure https://msdn.microsoft.com/en-us/library/windows/desktop/ms221061(v=vs.85).aspx From oledb.h: typedef struct tagDEC { USHORT wReserved; ; vt, 2 bytes union { ; r1, 2 bytes struct { BYTE scale; BYTE sign; }; USHORT signscale; }; ULONG Hi32; ; r2, r3, 4 bytes union { ; data, 8 bytes struct { #ifdef _MAC ULONG Mid32; ULONG Lo32; #else ULONG Lo32; ULONG Mid32; #endif }; ULONGLONG Lo64; }; } DECIMAL; #ce Global Const $tagDEC = "word wReserved;byte scale;byte sign;uint Hi32;uint Lo32;uint Mid32" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Variant functions ; Copied from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy ; https://www.autoitscript.com/forum/index.php?showtopic=110379 ; #FUNCTION# ==================================================================================================================== ; Name...........: VariantClear ; Description ...: Clears the value of a variant ; Syntax.........: VariantClear($pvarg) ; Parameters ....: $pvarg - the VARIANT to clear ; Return values .: Success - 0 ; Failure - nonzero ; Author ........: Prog@ndy ; Modified.......: ; Remarks .......: ; Related .......: VariantFree ; Link ..........: http://msdn.microsoft.com/en-us/library/ms221165.aspx ; Example .......: ; =============================================================================================================================== Func VariantClear($pvarg) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "long", "VariantClear", "ptr", $pvarg) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: VariantCopy ; Description ...: Copies a VARIANT to another ; Syntax.........: VariantCopy($pvargDest, $pvargSrc) ; Parameters ....: $pvargDest - Destionation variant ; $pvargSrc - Source variant ; Return values .: Success - 0 ; Failure - nonzero ; Author ........: Prog@ndy ; Modified.......: ; Remarks .......: ; Related .......: VariantRead ; Link ..........: http://msdn.microsoft.com/en-us/library/ms221697.aspx ; Example .......: ; =============================================================================================================================== Func VariantCopy($pvargDest, $pvargSrc) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "long", "VariantCopy", "ptr", $pvargDest, 'ptr', $pvargSrc) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: VariantInit ; Description ...: Initializes a variant. ; Syntax.........: VariantInit($pvarg) ; Parameters ....: $pvarg - the VARIANT to initialize ; Return values .: Success - 0 ; Failure - nonzero ; Author ........: Prog@ndy ; Modified.......: ; Remarks .......: ; Related .......: VariantClear ; Link ..........: http://msdn.microsoft.com/en-us/library/ms221402.aspx ; Example .......: ; =============================================================================================================================== Func VariantInit($pvarg) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "long", "VariantInit", "ptr", $pvarg) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Func VariantChangeType( $pVarDest, $pVarSrc, $wFlags, $vt ) Local $aRet = DllCall( "OleAut32.dll", "long", "VariantChangeType", "ptr", $pVarDest, "ptr", $pVarSrc, "word", $wFlags, "word", $vt ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc Func VariantChangeTypeEx( $pVarDest, $pVarSrc, $lcid, $wFlags, $vt ) Local $aRet = DllCall( "OleAut32.dll", "long", "VariantChangeTypeEx", "ptr", $pVarDest, "ptr", $pVarSrc, "word", $lcid, "word", $wFlags, "word", $vt ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc Func VarAdd( $pVarLeft, $pVarRight, $pVarResult ) Local $aRet = DllCall( "OleAut32.dll", "long", "VarAdd", "ptr", $pVarLeft, "ptr", $pVarRight, "ptr", $pVarResult ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc Func VarSub( $pVarLeft, $pVarRight, $pVarResult ) Local $aRet = DllCall( "OleAut32.dll", "long", "VarSub", "ptr", $pVarLeft, "ptr", $pVarRight, "ptr", $pVarResult ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; BSTR (basic string) functions ; Copied from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy ; https://www.autoitscript.com/forum/index.php?showtopic=110379 Func SysAllocString( $str ) Local $aRet = DllCall( "OleAut32.dll", "ptr", "SysAllocString", "wstr", $str ) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFunc Func SysFreeString( $pBSTR ) If Not $pBSTR Then Return SetError(1, 0, 0) DllCall( "OleAut32.dll", "none", "SysFreeString", "ptr", $pBSTR ) If @error Then Return SetError(2, 0, 0) EndFunc Func SysReadString( $pBSTR, $iLen = -1 ) If Not $pBSTR Then Return SetError(1, 0, "") If $iLen < 1 Then $iLen = SysStringLen( $pBSTR ) If $iLen < 1 Then Return SetError(2, 0, "") Return DllStructGetData( DllStructCreate( "wchar[" & $iLen & "]", $pBSTR ), 1 ) EndFunc Func SysStringLen( $pBSTR ) If Not $pBSTR Then Return SetError(1, 0, 0) Local $aRet = DllCall( "OleAut32.dll", "uint", "SysStringLen", "ptr", $pBSTR ) If @error Then Return SetError(2, 0, 0) Return $aRet[0] EndFunc ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Func VarBstrCat( $pBSTRLeft, $pBSTRRight, $pBSTRResult ) Local $aRet = DllCall( "OleAut32.dll", "long", "VarBstrCat", "ptr", $pBSTRLeft, "ptr", $pBSTRRight, "ptr", $pBSTRResult ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc SafeArray.au3: #include-once Global Const $tagSAFEARRAYBOUND = _ "ulong cElements;" & _ ; The number of elements in the dimension. "long lLbound;" ; The lower bound of the dimension. Global Const $tagSAFEARRAY = _ "ushort cDims;" & _ ; The number of dimensions. "ushort fFeatures;" & _ ; Flags, see below. "ulong cbElements;" & _ ; The size of an array element. "ulong cLocks;" & _ ; The number of times the array has been locked without a corresponding unlock. "ptr pvData;" & _ ; The data. $tagSAFEARRAYBOUND ; One $tagSAFEARRAYBOUND for each dimension. ; fFeatures flags Global Const $FADF_AUTO = 0x0001 ; An array that is allocated on the stack. Global Const $FADF_STATIC = 0x0002 ; An array that is statically allocated. Global Const $FADF_EMBEDDED = 0x0004 ; An array that is embedded in a structure. Global Const $FADF_FIXEDSIZE = 0x0010 ; An array that may not be resized or reallocated. Global Const $FADF_RECORD = 0x0020 ; An array that contains records. When set, there will be a pointer to the IRecordInfo interface at negative offset 4 in the array descriptor. Global Const $FADF_HAVEIID = 0x0040 ; An array that has an IID identifying interface. When set, there will be a GUID at negative offset 16 in the safearray descriptor. Flag is set only when FADF_DISPATCH or FADF_UNKNOWN is also set. Global Const $FADF_HAVEVARTYPE = 0x0080 ; An array that has a variant type. The variant type can be retrieved with SafeArrayGetVartype. Global Const $FADF_BSTR = 0x0100 ; An array of BSTRs. Global Const $FADF_UNKNOWN = 0x0200 ; An array of IUnknown*. Global Const $FADF_DISPATCH = 0x0400 ; An array of IDispatch*. Global Const $FADF_VARIANT = 0x0800 ; An array of VARIANTs. Global Const $FADF_RESERVED = 0xF008 ; Bits reserved for future use. ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Safearray functions ; Copied from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy ; https://www.autoitscript.com/forum/index.php?showtopic=110379 Func SafeArrayCreate($vType, $cDims, $tsaBound) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "ptr", "SafeArrayCreate", "dword", $vType, "uint", $cDims, "struct*", $tsaBound) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc Func SafeArrayDestroy($pSafeArray) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "int", "SafeArrayDestroy", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc Func SafeArrayAccessData($pSafeArray, ByRef $pArrayData) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "int", "SafeArrayAccessData", "ptr", $pSafeArray, "ptr*", 0) If @error Then Return SetError(1, 0, 1) $pArrayData = $aCall[2] Return $aCall[0] EndFunc Func SafeArrayUnaccessData($pSafeArray) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "int", "SafeArrayUnaccessData", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc Func SafeArrayGetUBound($pSafeArray, $iDim, ByRef $iBound) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "int", "SafeArrayGetUBound", "ptr", $pSafeArray, "uint", $iDim, "long*", 0) If @error Then Return SetError(1, 0, 1) $iBound = $aCall[3] Return $aCall[0] EndFunc Func SafeArrayGetLBound($pSafeArray, $iDim, ByRef $iBound) ; Author: Prog@ndy Local $aCall = DllCall("OleAut32.dll", "int", "SafeArrayGetLBound", "ptr", $pSafeArray, "uint", $iDim, "long*", 0) If @error Then Return SetError(1, 0, 1) $iBound = $aCall[3] Return $aCall[0] EndFunc Func SafeArrayGetDim($pSafeArray) Local $aResult = DllCall("OleAut32.dll", "uint", "SafeArrayGetDim", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 0) Return $aResult[0] EndFunc ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Func SafeArrayCopy( $psaSource, ByRef $psaDestination ) Local $aRet = DllCall( "OleAut32.dll", "int", "SafeArrayCopy", "ptr", $psaSource, "ptr*", 0 ) If @error Then Return SetError(1,0,1) $psaDestination = $aRet[2] Return $aRet[0] EndFunc Func SafeArrayCopyData( $psaSource, $psaDestination ) Local $aRet = DllCall( "OleAut32.dll", "int", "SafeArrayCopyData", "ptr", $psaSource, "ptr", $psaDestination ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc Func SafeArrayCreateEmptyWr( $vType ) Local $tsaBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tsaBound, "cElements", 0 ) DllStructSetData( $tsaBound, "lLbound", 0 ) Return SafeArrayCreate( $vType, 0, $tsaBound ) EndFunc Func SafeArrayDestroyData( $pSafeArray ) Local $aRet = DllCall( "OleAut32.dll", "int", "SafeArrayDestroyData", "ptr", $pSafeArray ) If @error Then Return SetError(1,0,1) Return $aRet[0] EndFunc Func SafeArrayGetVartype( $pSafeArray, ByRef $iVartype ) Local $aRet = DllCall( "OleAut32.dll", "int", "SafeArrayGetVartype", "ptr", $pSafeArray, "ptr*", 0 ) If @error Then Return SetError(1,0,1) $iVartype = $aRet[2] Return $aRet[0] EndFunc Func SafeArrayRedim( ByRef $pSafeArray, $tsaBound ) Local $aRet = DllCall( "OleAut32.dll", "int", "SafeArrayRedim", "ptr", $pSafeArray, "struct*", $tsaBound ) If @error Then Return SetError(1,0,1) $pSafeArray = $aRet[1] Return $aRet[0] EndFunc SafeArrayCreateEmptyWr() is a wrapper function to create an empty safearray. It's not a translation of a similar Windows API function. AutoIt arrays are safearrays Note that AutoIt arrays are stored internally as safearrays. AutoIt arrays are accessed through normal AutoIt variables, and a set of operators and functions have been created to manipulate the arrays. This makes AutoIt arrays proprietary arrays that cannot be easily used in other programming languages. Zip-file 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. VariantsSafearrays.7z1 point