Leaderboard
Popular Content
Showing content with the highest reputation on 11/28/2021 in all areas
-
Screen scraping
SkysLastChance and one other reacted to Nine for a topic
Screen scraping means a way to read / write on the representation of the current screen. You can, with this UDF, read the actual foreground of the screen or a background window. Hidden or minimized window are not supported. I tried to optimize the use of AutoIt as much as I could, but some actions require the performance of a DLL. I have found multiple threads and others UDF discussing this subject but never found an optimized approach to this issue without gathering everything inside a large DLL. The examples I am providing show how to use a background window (even if it is in the foreground when you run it directly with Scite) or use the current screen. Reading current screen is faster (about 20-30 ms faster) than reading a background window. You need to first initialize the structure based on width and height. You can reuse the structure as long as you want if the dimensions do not change. You will need to make a new initialize if dimensions are changing. You do not need (this way) to have the actual size of a window. You can decide to reduce the dimensions to increase performance. Supports x86 and x64. The following functions are included in the UDF : _GetScreen_Initialize($iWidth, $iHeight) _GetScreen_GetScreen() _GetScreen_GetWindow($hWnd, $iFlag = 0) _GetScreen_GetPixel($iX, $iY) _GetScreen_SetPixel($iX, $iY, $iValue) _GetScreen_SearchArea($iLeft, $iTop, $iRight, $iBottom, $iColor, $iStart = 1) _GetScreen_SearchAll($iColor, $iStart = 1) _GetScreen_PixelReplaceArea($iColorFrom, $iColorTo, $iLeft, $iTop, $iRight, $iBottom) _GetScreen_PixelReplaceAll($iColorFrom, $iColorTo) _GetScreen_CheckSumArea($iLeft, $iTop, $iRight, $iBottom) _GetScreen_SaveFile($sFileName) _GetScreen_GetBitMap() Version 2022-04-17 * Added new optional parameter $iFlag to _GetScreen_GetWindow 0 = full window for Win 7 and over 1 = client area for Win 7 and over 2 = full window for Win 10 and over (this can be used with applications (like Chrome) that do not support WM_PRINT or WM_PRINTCLIENT messages) Version 2021-11-28 * Corrected a bug in SearchArea Version 2021-08-30 * Fixed bugs related to areas * Added support to repetitive searches in the same area * Added a function to make a CheckSum of an area * Added an additional example Version 2021-08-24 * Removed unused structure * Harmonized code Example 1 : show various functions using the _GetScreen_GetWindow (background support) Example 2 : show new functions using _GetScreen_GetScreen() (foreground only but faster) All comments are very much welcome. GetScreen.zip2 points -
Version 1.6.3.0
17,293 downloads
Extensive library to control and manipulate Microsoft Active Directory. Threads: Development - General Help & Support - Example Scripts - Wiki Previous downloads: 30467 Known Bugs: (last changed: 2020-10-05) None Things to come: (last changed: 2020-07-21) None BTW: If you like this UDF please click the "I like this" button. This tells me where to next put my development effort1 point -
_GDIPlus_GraphicsGetDPIRatio() works correctly only if you compile it with #AutoIt3Wrapper_Res_HiDpi=Y. Obviously, the manifest must be present in the executable. #include <Array.au3> #include <GDIPlus.au3> #AutoIt3Wrapper_Res_HiDpi=Y _ArrayDisplay(_GDIPlus_GraphicsGetDPIRatio()) Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96) Local $aResults[2] = [0, 0] _GDIPlus_Startup() Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0) If @error Then Return SetError(1, @extended, $aResults) #forcedef $__g_hGDIPDll, $ghGDIPDll $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0) If @error Then Return SetError(2, @extended, $aResults) Local $iDPI = $aResult[2] Local $aresults[2] = [$iDPIDef / $iDPI, $iDPI / $iDPIDef] _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_Shutdown() Return $aresults EndFunc ;==>_GDIPlus_GraphicsGetDPIRatio This way I get the correct array values which are not 1, 1!1 point
-
AFAIK, this is outdated methodology that was replaced by current W3C webdriver implementation This is implemented in _WD_ElementAction / 'value'. You can use _WD_Action / 'actions' to send keystrokes directly to the main browser window. There are some existing examples on the forum.1 point
-
WebDriver UDF - Help & Support (III)
mLipok reacted to seadoggie01 for a topic
@mLipok Instead of zooming in on Chrome, could you resize the window larger than the screen to mimic the zoom? Why are you zooming in the first place? If it's for the user's preferences, you could zoom in when they need to take some action, and zoom back out when you need to automate actions. (And yes, I realize these are both workarounds, but I like to ignore the underlying issues as they're generally not going to be quickly fixed )1 point -
@mLipokIt appears to be a known problem with Chromedriver. See here for further details. Have you checked to see if other browsers have the same issue? Edit: You may want to review the following discussion --1 point
-
Struct ArrayIn Example03 above, many instances of a larger structure are copied from .NET to AutoIt. The total time spent both generating and copying data is measured. In order to measure the time used exclusively for copying data, it's necessary to split the code into two functions: A function to generate data and a function to copy data. This can be done by storing all instances of the structure in an array of structures. To copy instances of the structure from AutoIt back to .NET, it's convenient to store the structures in an array in the .NET code. Example03 below is a new version where it's possible to measure structure generation times and transfer times separately. Similarly, Example02 is a new version where it's possible to measure array generation times and transfer times separately. Note that code to generate duplicates is included in Rand2dArrayCreate() and RandStructsCreate() functions. Example02 #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 <Array.au3> #include "Random2dArray.au3" Example( 100, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 50000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 100000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 250000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) ;Example( 750000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) ;Example( 2000000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Func Example( _ $iRows, _ ; Number of rows in the array $aColumns, _ ; Number of columns and data types in the array, see 1) in docu $sSource = "" ) ; Character source for string columns, random strings are created from these characters ; Load .NET code, create object Local Static $oNetCode = 0, $oRand2dArrayClass If Not $oNetCode Then $oNetCode = DotNet_LoadVBcode( FileRead( "Example02.vb" ), "System.dll" ) $oRand2dArrayClass = DotNet_CreateObject( $oNetCode, "Rand2dArrayClass" ) EndIf ; Check $aColumns array Local $iError = CheckColumnsArray( $aColumns ) If $iError Then Return SetError($iError,0,0) ; Define $aColTypes array Local $iColumns = UBound( $aColumns ) Local $aColTypes[6][$iColumns+1] ; Update $aColTypes and $aColumns For $i = 0 To $iColumns - 1 If CalcColTypes( $i, $aColumns, $aColTypes, $iRows, $sSource ) Then ContinueLoop $aColumns[$i][2] += 1 ; Because of .NET Random class ; Convert duplicates as a percentage to number of unique rows $aColumns[$i][3] = $iRows - Int( $iRows * $aColumns[$i][3] / 100 ) If $aColumns[$i][3] And $aColumns[$i][3] < $iRows Then $aColumns[$i][3] -= 1 Next ; Visual code verification If $iRows = 100 Then $oRand2dArrayClass.Rand2dArrayCreate( $iRows, $aColumns, $aColTypes, $sSource ) Local $aArray100 = $oRand2dArrayClass.Rand2dArrayToAutoIt() $oRand2dArrayClass.Rand2dArrayDelete() _ArrayDisplay( $aArray100 ) Return EndIf ; Number of rows ConsoleWrite( "Array rows = " & $iRows & @CRLF ) ; Create array Local $hTimer = TimerInit() $oRand2dArrayClass.Rand2dArrayCreate( $iRows, $aColumns, $aColTypes, $sSource ) ConsoleWrite( "Create array = " & TimerDiff( $hTimer ) & @CRLF ) ; Pass array to AutoIt $hTimer = TimerInit() Local $aArray = $oRand2dArrayClass.Rand2dArrayToAutoIt() ConsoleWrite( "Pass to AutoIt = " & TimerDiff( $hTimer ) & @CRLF ) ; Delete .NET array $oRand2dArrayClass.Rand2dArrayDelete() ; Pass array to .NET $hTimer = TimerInit() $oRand2dArrayClass.Rand2dArrayToDotNet( $aArray ) ConsoleWrite( "Pass to .NET = " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) ; Delete .NET array $oRand2dArrayClass.Rand2dArrayDelete() EndFunc #cs Array rows = 50000 Create array = 161.3358744048 Pass to AutoIt = 53.1796500402687 Pass to .NET = 128.998994597868 Array rows = 100000 Create array = 276.623278397762 Pass to AutoIt = 108.432993923537 Pass to .NET = 258.063372194661 Array rows = 250000 Create array = 898.781576733183 Pass to AutoIt = 264.890631696736 Pass to .NET = 631.123803539603 Array rows = 750000 Create array = 2717.34763337093 Pass to AutoIt = 837.568960363219 Pass to .NET = 2094.36373615079 Array rows = 2000000 Create array = 7424.69637769875 Pass to AutoIt = 2081.94096635518 Pass to .NET = 5806.68962274841 #ce Imports System Class Rand2dArrayClass 'Global in class Dim aObjects(,) Public Sub Rand2dArrayCreate( iRows As Integer, aColumns As Object(,), aColTypes As Object(,), sSource As String ) Dim iColumns As Integer = aColumns.GetUpperBound(1) + 1 Dim aSource As Char() = sSource.ToCharArray() Dim iSourceLen As Integer = sSource.Length ReDim aObjects(iColumns-1,iRows-1) Dim oRnd As New Random() Dim sStr As String = "" Dim k, y, m, dMax As Integer For i As Integer = 0 To iRows - 1 'String columns For j As Integer = 1 To aColTypes(0,0) k = aColTypes(j,0) If i <= aColumns(3,k) Then For l As Integer = 1 To oRnd.Next( aColumns(1,k), aColumns(2,k) ) sStr &= aSource(oRnd.Next( iSourceLen )) Next aObjects(k,i) = sStr sStr = "" Else aObjects(k,i) = aObjects(k,oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Integer columns For j As Integer = 1 To aColTypes(0,1) k = aColTypes(j,1) If i <= aColumns(3,k) Then aObjects(k,i) = oRnd.Next( aColumns(1,k), aColumns(2,k) ) Else aObjects(k,i) = aObjects(k,oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Float columns For j As Integer = 1 To aColTypes(0,2) k = aColTypes(j,2) If i <= aColumns(3,k) Then aObjects(k,i) = aColumns(1,k) + ( aColumns(2,k) - aColumns(1,k) ) * oRnd.NextDouble() Else aObjects(k,i) = aObjects(k,oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Date columns For j As Integer = 1 To aColTypes(0,3) k = aColTypes(j,3) If i <= aColumns(3,k) Then y = oRnd.Next( aColumns(1,k), aColumns(2,k) ) m = oRnd.Next( 1, 13 ) Select m Case 1, 3, 5, 7, 8, 10, 12 dMax = 31 Case 4, 6, 9, 11 dMax = 30 Case Else '2 dMax = If( y Mod 4 <> 0, 28, If( y Mod 400 = 0, 29, If( y Mod 100 = 0, 28, 29 ) ) ) End Select aObjects(k,i) = y * 10000 + m * 100 + oRnd.Next( 1, dMax + 1 ) Else aObjects(k,i) = aObjects(k,oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Time columns For j As Integer = 1 To aColTypes(0,4) k = aColTypes(j,4) If i <= aColumns(3,k) Then aObjects(k,i) = oRnd.Next( aColumns(1,k), aColumns(2,k) ) * 10000 + oRnd.Next( 0, 60 ) * 100 + oRnd.Next( 0, 60 ) Else aObjects(k,i) = aObjects(k,oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Row/col columns For j As Integer = 1 To aColTypes(0,5) k = aColTypes(j,5) aObjects(k,i) = i & "/" & k Next Next End Sub Public Function Rand2dArrayToAutoIt() As Object(,) Return aObjects End Function Public Sub Rand2dArrayToDotNet( aArray As Object(,) ) aObjects = aArray End Sub Public Sub Rand2dArrayDelete() ReDim aObjects(0,0) End Sub End Class Example03 #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 "Random2dArray.au3" Example( 100, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 50000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 100000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Example( 250000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) ;Example( 750000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) ;Example( 2000000, "sifdtr", "abcdefghijklmnopqrstuvwxyz" ) Func Example( _ $iRows, _ ; Number of rows in the array $aColumns, _ ; Number of columns and data types in the array, see 1) in docu $sSource = "" ) ; Character source for string columns, random strings are created from these characters ; Load .NET code, create object Local Static $oNetCode = 0, $oRandStructsClass If Not $oNetCode Then $oNetCode = DotNet_LoadVBcode( FileRead( "Example03.vb" ), "System.dll" ) $oRandStructsClass = DotNet_CreateObject( $oNetCode, "RandStructsClass" ) EndIf ; Check $aColumns array Local $iError = CheckColumnsArray( $aColumns ) If $iError Then Return SetError($iError,0,0) ; Define $aColTypes array Local $iColumns = UBound( $aColumns ) Local $aColTypes[6][$iColumns+1] ; Update $aColTypes and $aColumns For $i = 0 To $iColumns - 1 If CalcColTypes( $i, $aColumns, $aColTypes, $iRows, $sSource ) Then ContinueLoop $aColumns[$i][2] += 1 ; Because of .NET Random class ; Convert duplicates as a percentage to number of unique rows $aColumns[$i][3] = $iRows - Int( $iRows * $aColumns[$i][3] / 100 ) If $aColumns[$i][3] And $aColumns[$i][3] < $iRows Then $aColumns[$i][3] -= 1 Next ; Visual code verification If $iRows = 100 Then $oRandStructsClass.RandStructsCreate( $iRows, $aColumns, $aColTypes, $sSource ) Local $pPtr100 = $oRandStructsClass.RandStructsToAutoIt( $iRows ), $tStruct, $tString, $iSize = @AutoItX64 ? 56 : 40 ConsoleWrite( "$pPtr100 = " & Ptr( $pPtr100 ) & @CRLF & @CRLF ) ; Display first structure ConsoleWrite( "First structure:" & @CRLF ) $tStruct = DllStructCreate( "int iString;ptr pString;int iInteger;double dDouble;int iDate;int iTime;int iRowCol;ptr pRowCol", $pPtr100 ) ConsoleWrite( "$tStruct.iString = " & $tStruct.iString & @CRLF ) ConsoleWrite( "$tStruct.pString = " & Ptr( $tStruct.pString ) & @CRLF ) $tString = DllStructCreate( "char sString[" & $tStruct.iString & "]", $tStruct.pString ) ConsoleWrite( "$tString.sString = " & $tString.sString & @CRLF ) ConsoleWrite( "$tStruct.iInteger = " & $tStruct.iInteger & @CRLF ) ConsoleWrite( "$tStruct.dDouble = " & $tStruct.dDouble & @CRLF ) ConsoleWrite( "$tStruct.iDate = " & $tStruct.iDate & @CRLF ) ConsoleWrite( "$tStruct.iTime = " & $tStruct.iTime & @CRLF ) ConsoleWrite( "$tStruct.iRowCol = " & $tStruct.iRowCol & @CRLF ) ConsoleWrite( "$tStruct.pRowCol = " & Ptr( $tStruct.pRowCol ) & @CRLF ) $tString = DllStructCreate( "char sString[" & $tStruct.iRowCol & "]", $tStruct.pRowCol ) ConsoleWrite( "$tString.sString = " & $tString.sString & @CRLF & @CRLF ) ; Display last structure ConsoleWrite( "Last structure:" & @CRLF ) $tStruct = DllStructCreate( "int iString;ptr pString;int iInteger;double dDouble;int iDate;int iTime;int iRowCol;ptr pRowCol", $pPtr100 + $iSize * ( $iRows - 1 ) ) ConsoleWrite( "$tStruct.iString = " & $tStruct.iString & @CRLF ) ConsoleWrite( "$tStruct.pString = " & Ptr( $tStruct.pString ) & @CRLF ) $tString = DllStructCreate( "char sString[" & $tStruct.iString & "]", $tStruct.pString ) ConsoleWrite( "$tString.sString = " & $tString.sString & @CRLF ) ConsoleWrite( "$tStruct.iInteger = " & $tStruct.iInteger & @CRLF ) ConsoleWrite( "$tStruct.dDouble = " & $tStruct.dDouble & @CRLF ) ConsoleWrite( "$tStruct.iDate = " & $tStruct.iDate & @CRLF ) ConsoleWrite( "$tStruct.iTime = " & $tStruct.iTime & @CRLF ) ConsoleWrite( "$tStruct.iRowCol = " & $tStruct.iRowCol & @CRLF ) ConsoleWrite( "$tStruct.pRowCol = " & Ptr( $tStruct.pRowCol ) & @CRLF ) $tString = DllStructCreate( "char sString[" & $tStruct.iRowCol & "]", $tStruct.pRowCol ) ConsoleWrite( "$tString.sString = " & $tString.sString & @CRLF & @CRLF ) ; Delete .NET structs $oRandStructsClass.RandStructsDelete() ; Free structure memory $oRandStructsClass.FreeStructure() Return EndIf ; Number of rows ConsoleWrite( "Struct rows = " & $iRows & @CRLF ) ; Create structs Local $hTimer = TimerInit() $oRandStructsClass.RandStructsCreate( $iRows, $aColumns, $aColTypes, $sSource ) ConsoleWrite( "Create structs = " & TimerDiff( $hTimer ) & @CRLF ) ; Copy structs to AutoIt $hTimer = TimerInit() Local $pPtr = $oRandStructsClass.RandStructsToAutoIt( $iRows ) ConsoleWrite( "Copy to AutoIt = " & TimerDiff( $hTimer ) & @CRLF ) ; Delete .NET structs $oRandStructsClass.RandStructsDelete() ; Copy structs to .NET $hTimer = TimerInit() $oRandStructsClass.RandStructsToDotNet( $iRows ) ConsoleWrite( "Copy to .NET = " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) ; Delete .NET structs $oRandStructsClass.RandStructsDelete() ; Free structure memory $oRandStructsClass.FreeStructure() #forceref $pPtr EndFunc #cs Struct rows = 50000 Create structs = 118.687319937022 Copy to AutoIt = 14.4374527116075 Copy to .NET = 27.3954765492515 Struct rows = 100000 Create structs = 270.28500615459 Copy to AutoIt = 30.5258261460518 Copy to .NET = 71.3821661221316 Struct rows = 250000 Create structs = 654.394887271121 Copy to AutoIt = 70.4205373540553 Copy to .NET = 144.230739927763 Struct rows = 750000 Create structs = 1731.17973924928 Copy to AutoIt = 203.711537966051 Copy to .NET = 437.325547215529 Struct rows = 2000000 Create structs = 4556.50490192412 Copy to AutoIt = 547.36291803216 Copy to .NET = 1646.96449730863 #ce Imports System Imports System.Runtime.InteropServices Public Structure Test Public iString As Integer 'String length Public sString As String Public iInteger As Integer Public dDouble As Double Public iDate As Integer Public iTime As Integer Public iRowCol As Integer 'String length Public sRowCol As String End Structure Class RandStructsClass 'Globals in class Dim tTest As Test, iSize As Integer = Marshal.SizeOf( tTest ) Dim aTest() As Test Dim pnt As IntPtr Public Sub RandStructsCreate( iRows As Integer, aColumns As Object(,), aColTypes As Object(,), sSource As String ) Dim iColumns As Integer = aColumns.GetUpperBound(1) + 1 Dim aSource As Char() = sSource.ToCharArray() Dim iSourceLen As Integer = sSource.Length Dim oRnd As New Random() ReDim aTest(iRows-1) Dim tTest As Test Dim sStr As String = "" Dim k, y, m, dMax As Integer For i As Integer = 0 To iRows - 1 'String columns For j As Integer = 1 To aColTypes(0,0) k = aColTypes(j,0) If i <= aColumns(3,k) Then For l As Integer = 1 To oRnd.Next( aColumns(1,k), aColumns(2,k) ) sStr &= aSource(oRnd.Next( iSourceLen )) Next tTest.iString = sStr.Length + 1 tTest.sString = sStr sStr = "" Else aTest(i) = aTest(oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Integer columns For j As Integer = 1 To aColTypes(0,1) k = aColTypes(j,1) If i <= aColumns(3,k) Then tTest.iInteger = oRnd.Next( aColumns(1,k), aColumns(2,k) ) Else aTest(i) = aTest(oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Float columns For j As Integer = 1 To aColTypes(0,2) k = aColTypes(j,2) If i <= aColumns(3,k) Then tTest.dDouble = aColumns(1,k) + ( aColumns(2,k) - aColumns(1,k) ) * oRnd.NextDouble() Else aTest(i) = aTest(oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Date columns For j As Integer = 1 To aColTypes(0,3) k = aColTypes(j,3) If i <= aColumns(3,k) Then y = oRnd.Next( aColumns(1,k), aColumns(2,k) ) m = oRnd.Next( 1, 13 ) Select m Case 1, 3, 5, 7, 8, 10, 12 dMax = 31 Case 4, 6, 9, 11 dMax = 30 Case Else '2 dMax = If( y Mod 4 <> 0, 28, If( y Mod 400 = 0, 29, If( y Mod 100 = 0, 28, 29 ) ) ) End Select tTest.iDate = y * 10000 + m * 100 + oRnd.Next( 1, dMax + 1 ) Else aTest(i) = aTest(oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Time columns For j As Integer = 1 To aColTypes(0,4) k = aColTypes(j,4) If i <= aColumns(3,k) Then tTest.iTime = oRnd.Next( aColumns(1,k), aColumns(2,k) ) * 10000 + oRnd.Next( 0, 60 ) * 100 + oRnd.Next( 0, 60 ) Else aTest(i) = aTest(oRnd.Next(0,aColumns(3,k)+1)) End If Next 'Row/col columns For j As Integer = 1 To aColTypes(0,5) k = aColTypes(j,5) tTest.sRowCol = i & "/" & k tTest.iRowCol = tTest.sRowCol.Length + 1 Next aTest(i) = tTest Next End Sub Public Function RandStructsToAutoIt( iRows As Integer ) As String pnt = Marshal.AllocHGlobal( iRows * iSize ) 'Console.WriteLine( "Marshal.SizeOf( tTest ) = {0}", iSize ) 'Copy structures to unmanaged memory For i As Integer = 0 To iRows - 1 Marshal.StructureToPtr( aTest(i), pnt + i * iSize, False ) Next Return pnt.ToString() End Function Public Sub RandStructsToDotNet( iRows As Integer ) ReDim aTest(iRows-1) For i As Integer = 0 To iRows - 1 aTest(i) = CType( Marshal.PtrToStructure( pnt + i * iSize, GetType( Test ) ), Test ) Next End Sub Public Sub RandStructsDelete() ReDim aTest(0) End Sub Public Sub FreeStructure() Marshal.FreeHGlobal( pnt ) End Sub End Class Performance Example02 Example03 --------------------------------- --------------------------------- Array rows = 50000 Struct rows = 50000 Create array = 161.3358744048 Create structs = 118.687319937022 Pass to AutoIt = 53.1796500402687 Copy to AutoIt = 14.4374527116075 Pass to .NET = 128.998994597868 Copy to .NET = 27.3954765492515 Array rows = 100000 Struct rows = 100000 Create array = 276.623278397762 Create structs = 270.28500615459 Pass to AutoIt = 108.432993923537 Copy to AutoIt = 30.5258261460518 Pass to .NET = 258.063372194661 Copy to .NET = 71.3821661221316 Array rows = 250000 Struct rows = 250000 Create array = 898.781576733183 Create structs = 654.394887271121 Pass to AutoIt = 264.890631696736 Copy to AutoIt = 70.4205373540553 Pass to .NET = 631.123803539603 Copy to .NET = 144.230739927763 Array rows = 750000 Struct rows = 750000 Create array = 2717.34763337093 Create structs = 1731.17973924928 Pass to AutoIt = 837.568960363219 Copy to AutoIt = 203.711537966051 Pass to .NET = 2094.36373615079 Copy to .NET = 437.325547215529 Array rows = 2000000 Struct rows = 2000000 Create array = 7424.69637769875 Create structs = 4556.50490192412 Pass to AutoIt = 2081.94096635518 Copy to AutoIt = 547.36291803216 Pass to .NET = 5806.68962274841 Copy to .NET = 1646.96449730863 Data creation rates are higher for structures than for arrays. It takes about 30 - 100 percent longer to create arrays than structures. This is probably due to the fact that the 2d arrays are arrays of objects, where the more computationally heavy objects are needed to handle data of different types (strings, integers and doubles). While the 1d array of structures consists only of one data type (structures). The code to create random data is the same for both arrays and structures. Therefore, it can almost only be the difference between arrays and structures that results in a higher speed for structures. Data transfer rates are significantly higher for structures than for arrays. The speeds are about 3-4 times higher for structures. And this applies to transfers in both directions from .NET to AutoIt and from AutoIt to .NET. Transfers from .NET to AutoIt are 2-3 times faster than the other direction. With the Marshal Class used in this thread, it's apparently not possible to transfer a 1d array of structures as a single data block. But it cannot be ruled out that it's possible through custom marshalling. And that, of course, would be very interesting. 7z-fileNew 7z-file at bottom of first post.1 point
-
Here's a fast (and small) C DLL version (attached, or compile with TCC) Takes a file, change it to screencap yourself if needed. #include <GDIPlus.au3> Global Static $CountColorDll = DllOpen("CountColor.dll") Global $hImage, $iLeft = 0, $iTop = 0, $iRight = 1100, $iBottom = 600, $hPixels, $Count = 0, $Color = 0xFFd05e5e _GDIPlus_Startup() $hImage = _GDIPlus_BitmapCreateFromFile("image.png") $Count = _CountColor($hImage, $Color) _GDIPlus_Shutdown() ConsoleWrite("Amount of " & Hex($Color, 8) & " = " & $Count & @crlf) Func _CountColor(ByRef $hImage, $Color) $Pixels = _GDIPlus_BitmapLockBits($hImage, $iLeft, $iTop, $iRight, $iBottom, $GDIP_ILMREAD, $GDIP_PXF32ARGB) $aRet = DllCall($CountColorDLL, "int:cdecl", "CountColor", "ptr", $Pixels.Scan0, "int", ($iRight-$iLeft)*($iBottom-$iTop), "int", $Color) _GDIPlus_BitmapUnlockBits($hImage, $Pixels) _GDIPlus_BitmapDispose($hImage) Return $aRet[0] EndFunc #cs =================================================================================================== C code for the DLL, compile with 'Tiny C Compiler' (TCC) https://bellard.org/tcc/ tcc -shared CountColor.c =================================================================================================== #include <stdlib.h> __declspec(dllexport) int CountColor(int* pixel, int len, int color) { int i, count = 0; for(i=0;i<len;i++){if(pixel[i]==color){count+=1;}} return count;} =================================================================================================== #ce Btw, there are WAY more than 566 pixels that have color d05e5e, I count 28661 of them (and the edge of the circle is antialiased so they dont count) CountColor.dll1 point
-
@Chimp Nice!!! I just added this little tweak to set Bold font style of text indicating N%: GUICtrlSetFont(-1, 8.5, 700) ; $FW_BOLD1 point
-
OpenJson is a library that allows the extraction of data from text encoded in JSON format in a simple way. #include "OpenJson.au3" $json_text = FileRead('json.txt') $dict = _OJParse($json_text) ; #GET COUNT OF ITEMS# =========================================================================================================== ConsoleWrite('GET COUNT OF ITEMS' & @CRLF) $count = $dict.Item('rows').Item(1).Item('elements').Count ConsoleWrite('Items count: ' & $count & @CRLF & @CRLF) ; #SHOW SINGLE VALUES# =========================================================================================================== ConsoleWrite('SHOW SINGLE VALUES' & @CRLF) For $i = 1 To $count ConsoleWrite($dict.Item('rows').Item(1).Item('elements').Item($i).Item('duration').Item('text') & @CRLF) Next ConsoleWrite(@CRLF) ; #SHOW ALL KEYS# =========================================================================================================== ConsoleWrite('SHOW ALL KEYS' & @CRLF) $keys = $dict.Keys For $k In $keys ConsoleWrite($k & @CRLF) Next ConsoleWrite(@CRLF) ; #SHOW ALL VALUES# =========================================================================================================== ConsoleWrite('SHOW ALL VALUES' & @CRLF) $items = $dict.Item('destination_addresses').Items For $i In $items ConsoleWrite($i & @CRLF) Next ConsoleWrite(@CRLF) ; #CHECK IF KEY EXISTS# =========================================================================================================== ConsoleWrite('CHECK IF KEY EXISTS' & @CRLF) $exists = $dict.Item('rows').Item(1).Exists('elements') ConsoleWrite("Exists key 'elements'?: " & $exists & @CRLF) ; #OUTPUT# =========================================================================================================== ;~ GET COUNT OF ITEMS ;~ Items count: 6 ;~ SHOW SINGLE VALUES ;~ 3 hours 54 mins ;~ 1 hour 44 mins ;~ 1 day 18 hours ;~ 18 hours 43 mins ;~ 1 day 2 hours ;~ 1 day 18 hours ;~ SHOW ALL KEYS ;~ destination_addresses ;~ origin_addresses ;~ rows ;~ status ;~ SHOW ALL VALUES ;~ Washington, DC, USA ;~ Philadelphia, PA, USA ;~ Santa Barbara, CA, USA ;~ Miami, FL, USA ;~ Austin, TX, USA ;~ Napa County, CA, USA ;~ CHECK IF KEY EXISTS ;~ Exists key 'elements'?: True ; #OUTPUT# =========================================================================================================== ;================================================================== The object returned by the _OJParse function contains 5 methods for extracting the information: Count: returns the number of items contained within an element Item('key') or Item(index): returns a specific item Keys: gets the list of keys for a specific element Items: gets the list of items of a specific element Exists('key'): or Exists(index): check if an element exists ;================================================================== Elements must be chained to get sub elements: Example: File example.txt { "persons":[ {"name":"Diego","age":27}, {"name":"Juan","age":19}, {"name":"Andres","age":43}, {"name":"Emilio","age":35} ] } Autoit code: #include "OpenJson.au3" $json_text = FileRead('example.txt') $dict = _OJParse($json_text) $name = $dict.Item('persons').Item(3).Item('name') ConsoleWrite($name) OUTPUT: Andres ;================================================================== ;There are three considerations that must be taken when using this library 1.- You should not to use double quotes within the texts. Double quotes within a text should be avoided, otherwise the library will throw an error. For example double quotes should not be in any of the following ways: "Hello" world" "hello "world"" But single quotes are allowed within the text: "Hello 'world' " 2.- Be careful with the structure of the text in JSON format Although it is obvious, it is worth remembering that if the provided JSON text structure has an error, the library will throw an error or return incomplete or empty data. This library uses the recursion process to build a tree of data in memory, so it is very sensitive to the quality of the JSON text that is processed. Please make sure that the JSON text to be processed is correct. None of the following five special characters must be missing or excess: [] {} " Otherwise the library will throw an error, but be sure that if the text in JSON format is syntactically correct, the library will work correctly. 3.- Keys are case sensitive Make sure the keys have the exact same name as supplied in the JSON-formatted text. $dict.Item('name') is not the same as $dict.Item('Name') ;================================================================== Three files are included in the attached archive: OpenJson.au3 - The UDF Library OJTest.au3 - Contains examples of the five functions available for manipulating JSON data json.txt - Contains sample text in JSON format OpenJson_v1.2.zip1 point