Jump to content

Is there a way to run this code faster on Windows 10?


Recommended Posts

On 1/15/2019 at 11:48 PM, Bilgus said:

why not copy the dc of the window and search that instead using a similar method or bitblit

 can you please guide me as to where I can find information on how to use this method. I am open to anything else that works faster. My experience in programming is only a one semester high school class. I can do things with guidance but don't know a lot of intricacies. Thanks

Link to comment
Share on other sites

Link to comment
Share on other sites

This should give you a place to start from

#cs ----------------------------------------------------------------------------

    AutoIt Version: 3.3.14.5

#ce ----------------------------------------------------------------------------

#include <APIGdiConstants.au3>
#include <GUIConstantsEx.au3>
#include <SendMessage.au3>
#include <StaticConstants.au3>
#include <WinAPIGdi.au3>
#include <WinAPIHObj.au3>

#include <Timers.au3>

$G_iPID = RunProgram()
$G_hWND = _GetHwndFromPID($G_iPID)
ConsoleWrite("PID: " & $G_iPID & " hWNd: " & $G_hWND & @CRLF)
Example($G_hWND)



Func RunProgram()
    ; Run Notepad with the window maximized.
    Local $iPID = Run("notepad.exe", "", @SW_SHOW)

    ; Wait 10 seconds for the Notepad window to appear.
    WinWait("[CLASS:Notepad]", "", 10)

    Return $iPID
EndFunc   ;==>RunProgram

;Function for getting HWND from PID
;www.autoitscript.com/wiki/FAQ#How_can_I_get_a_window_handle_when_all_I_have_is_a_PID.3F
Func _GetHwndFromPID($iPID)
    $hWND = 0
    $winlist = WinList()
    Do
        For $i = 1 To $winlist[0][0]
            If $winlist[$i][0] <> "" Then
                $iPID2 = WinGetProcess($winlist[$i][1])
                If $iPID2 = $iPID Then
                    $hWND = $winlist[$i][1]
                    ExitLoop
                EndIf
            EndIf
        Next
    Until $hWND <> 0
    Return $hWND
EndFunc   ;==>_GetHwndFromPID



Func Example($hWND) ;helpfile _WinAPI_CreateDIBSection
    Local $hStarttime = _Timer_Init()

    Local $iWidth = 0, $iHeight = 0

    Local $aWinsz = WinGetPos($hWND)
    If IsArray($aWinsz) Then
        $iWidth = $aWinsz[2]
        $iHeight = $aWinsz[3]
    EndIf

    Local $hWndDC = _WinAPI_GetDC($hWND)
    Local $hCompDC = _WinAPI_CreateCompatibleDC(0)

    ; Create 32 (ARGB) bits-per-pixel device-independent bitmap (DIB) that use a mask
    Local $tBIV5HDR = DllStructCreate($tagBITMAPV5HEADER)

    DllStructSetData($tBIV5HDR, 'bV5Size', DllStructGetSize($tBIV5HDR))
    DllStructSetData($tBIV5HDR, 'bV5Width', $iWidth)
    DllStructSetData($tBIV5HDR, 'bV5Height', $iHeight)
    DllStructSetData($tBIV5HDR, 'bV5Planes', 1)
    DllStructSetData($tBIV5HDR, 'bV5BitCount', 32)
    DllStructSetData($tBIV5HDR, 'biCompression', $BI_BITFIELDS)
    DllStructSetData($tBIV5HDR, 'bV5SizeImage', 0)
    DllStructSetData($tBIV5HDR, 'bV5XPelsPerMeter', 0)
    DllStructSetData($tBIV5HDR, 'bV5YPelsPerMeter', 0)
    DllStructSetData($tBIV5HDR, 'bV5ClrUsed', 0)
    DllStructSetData($tBIV5HDR, 'bV5ClrImportant', 0)
    DllStructSetData($tBIV5HDR, 'bV5RedMask', 0x00FF0000)
    DllStructSetData($tBIV5HDR, 'bV5GreenMask', 0x0000FF00)
    DllStructSetData($tBIV5HDR, 'bV5BlueMask', 0x000000FF)
    DllStructSetData($tBIV5HDR, 'bV5AlphaMask', 0xFF000000)
    DllStructSetData($tBIV5HDR, 'bV5CSType', 0)
    DllStructSetData($tBIV5HDR, 'bV5Endpoints', 0, 1)
    DllStructSetData($tBIV5HDR, 'bV5Endpoints', 0, 2)
    DllStructSetData($tBIV5HDR, 'bV5Endpoints', 0, 3)
    DllStructSetData($tBIV5HDR, 'bV5GammaRed', 0)
    DllStructSetData($tBIV5HDR, 'bV5GammaGreen', 0)
    DllStructSetData($tBIV5HDR, 'bV5GammaBlue', 0)
    DllStructSetData($tBIV5HDR, 'bV5Intent', 0)
    DllStructSetData($tBIV5HDR, 'bV5ProfileData', 0)
    DllStructSetData($tBIV5HDR, 'bV5ProfileSize', 0)
    DllStructSetData($tBIV5HDR, 'bV5Reserved', 0)

    Local $pBits
    Local $hBmp = _WinAPI_CreateDIBSection(0, $tBIV5HDR, $DIB_RGB_COLORS, $pBits)
    Local $hBmpOld = _WinAPI_SelectObject($hCompDC, $hBmp)
    Local $tPixels = DllStructCreate("dword[" & $iWidth * $iHeight & "]", $pBits) ;DWORD is 32 bits


    _WinAPI_PrintWindow($hWND, $hCompDC) ;copy hWND into the compatible dc we created
    WinSetState($hWND, "", @SW_MINIMIZE)

    _WinAPI_SelectObject($hCompDC, $hBmpOld) ;deselect hbmp from dc and restore hBmpOld so we can play with it

    ConsoleWrite("Setup: " & _Timer_Diff($hStarttime) & " Ms" & @CRLF)
    $hStarttime = _Timer_Init()

    For $iY = 0 To $iHeight - 1
        For $iX = 1 To $iWidth
            Local $iColorIdx = ($iY * $iWidth) + $iX ;;Calculate position in array based on image stride
            $iColor = DllStructGetData($tPixels, 1, $iColorIdx)
            ;;alternatively you could search for a specific color...
            If BitAND($iColor, 0x0000FF00) > 0xB0 And BitAND($iColor, 0x0000FF) < 0x3F And BitAND($iColor, 0x000000FF) < 0x3F Then
                DllStructSetData($tPixels, 1, 0xFF00FF00, $iColorIdx) ;Don't Forget Alpha Channel
            EndIf
        Next
    Next

    ConsoleWrite("Search: " & _Timer_Diff($hStarttime) & " Ms" & @CRLF)

    ;copy hbmp into picture control to view results
    Local $hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), $iWidth, $iHeight)
    Local $idPic = GUICtrlCreatePic('', 0, 0, $iWidth, $iHeight)
    Local $hPic = GUICtrlGetHandle($idPic)

    ; Set bitmap to control
    _SendMessage($hPic, $STM_SETIMAGE, 0, $hBmp)
    Local $hObj = _SendMessage($hPic, $STM_GETIMAGE)
    If $hObj <> $hBmp Then
        _WinAPI_DeleteObject($hBmp)
    EndIf

    GUISetState(@SW_SHOW)

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ;release objects
    _WinAPI_DeleteObject($hBmp)
    _WinAPI_ReleaseDC(0, $hCompDC)
    _WinAPI_ReleaseDC($hWND, $hWndDC)

EndFunc   ;==>Example

Things to remember:

This is a bit slower than what is possible since we go over the whole image and are searching for a range of colors and then show the results

You can save some time by storing the $tagBITMAPV5HEADER structure rather than re-creating it each time

same goes for hCompDC and hWndDC but this is just an example to get you started....

 

Ideally the client area should be excluded _WinAPI_PrintWindow($hWND, $hCompDC, true)

Store the handle from _WinAPI_SelectObject() you need to put it back when finished (see $hBmpOld = _WinAPI_SelectObject($hCompDC, $hBmp))

You need to free/delete handles/objects you create when you finish with them (see release objects comment...)

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...