Jump to content

_ProcessGetWindow() for turning a Process ID into a Window Handle


RulerOf
 Share

Recommended Posts

Hello Folks,

A little bit of Googlin' and a couple of Forum searches seems to indicate that, for some reason, this function isn't really prevalent, so I wanted to post the code I wrote here.

Anyone care to pick it apart for me? I write AutoIt code in my spare time, so I may have missed a few gotchas that my limited (but successful!) testing couldn't reveal.

_ProcessGetWindow() is designed to be the counterpart of WinGetProcess(), returning HWND's from an input process ID. It can also be told to provide a single, best guess result in the event you don't want to try parsing multiple windows from the output.

In the event that this is a highly redundant post, I apologize, but I did do some searching in advance, and all I came up with was instructions to do just this :blink:

Edit:

Ha-ha, found a bug when I went to use it. As originally written, it wouldn't return HWND's for processes owning less than two windows ;)

Code updated.

#include-once
#include <array.au3>

; #FUNCTION# ============================================================================================================================
; Name...........: _ProcessGetWindow
;
; Description ...: Returns an array of HWNDs containing all windows owned by the process $p_PID, or optionally a single "best guess."
;
; Syntax.........: _ProcessGetWindow( $p_PID [, $p_ReturnBestGuess = False ])
;
; Parameters ....: $p_PID - The PID of the process you want the Window for.
;                  $p_ReturnBestGuess - If True, function will return only 1 reult on a best-guess basis.
;                                           The "Best Guess" is the VISIBLE window owned by $p_PID with the longest title.
;
; Return values .: Success      - Return $_array containing HWND info.
;                                       $_array[0] = Number of results
;                                       $_array[n] = HWND of Window n
;
;                  Failure      - Returns 0
;
;                  Error        - Returns -1 and sets @error
;                                            1 - Requires a non-zero number.
;                                            2 - Process does not exist
;                                            3 - WinList() Error
;
; Author ........: Andrew Bobulsky, contact: RulerOf <at that public email service provided by Google>.
; Remarks .......: The reverse of WinGetProcess()
; =======================================================================================================================================

Func _ProcessGetWindow( $p_PID, $p_ReturnBestGuess = False )

    Local $p_ReturnVal[1] = [0]

    Local $p_WinList = WinList()

    If @error Then ;Some Error handling
        SetError(3)
        Return -1
    EndIf

    If $p_PID = 0 Then ;Some Error handling
        SetError(1)
        Return -1
    EndIf

    If ProcessExists($p_PID) = 0 Then ;Some Error handling
        ConsoleWrite("_ProcessGetWindow: Process " & $p_PID & " doesn't exist!" & @CRLF)
        SetError(2)
        Return -1
    EndIf

    For $i = 1 To $p_WinList[0][0] Step 1
        Local $w_PID = WinGetProcess($p_WinList[$i][1])

       ; ConsoleWrite("Processing Window: " & Chr(34) & $p_WinList[$i][0] & Chr(34) & @CRLF & " with HWND: " & $p_WinList[$i][1] & @CRLF & " and PID: " & $w_PID & @CRLF)

        If $w_PID = $p_PID Then
            ;ConsoleWrite("Match: HWND " & $p_WinList[$i][1] & @CRLF)
            $p_ReturnVal[0] += 1
            _ArrayAdd($p_ReturnVal, $p_WinList[$i][1])
        EndIf
    Next

    If $p_ReturnVal[0] > 1 Then

        If $p_ReturnBestGuess Then

            Do

                Local $i_State = WinGetState($p_ReturnVal[2])
                Local $i_StateLongest = WinGetState($p_ReturnVal[1])

                Select
                    Case BitAND($i_State, 2) And BitAND($i_StateLongest, 2) ;If they're both visible
                        If StringLen(WinGetTitle($p_ReturnVal[2])) > StringLen(WinGetTitle($p_ReturnVal[1])) Then ;And the new one has a longer title
                            _ArrayDelete($p_ReturnVal, 1) ;Delete the "loser"
                            $p_ReturnVal[0] -= 1 ;Decrement counter
                        Else
                            _ArrayDelete($p_ReturnVal, 2) ;Delete the failed challenger
                            $p_ReturnVal[0] -= 1
                        EndIf

                    Case BitAND($i_State, 2) And Not BitAND($i_StateLongest, 2) ;If the new one's visible and the old one isn't
                        _ArrayDelete($p_ReturnVal, 1) ;Delete the old one
                        $p_ReturnVal[0] -= 1 ;Decrement counter

                    Case Else ;Neither window is visible, let's just keep the first one.
                        _ArrayDelete($p_ReturnVal, 2)
                        $p_ReturnVal[0] -= 1

                EndSelect

            Until $p_ReturnVal[0] = 1

        EndIf

        Return $p_ReturnVal

    ElseIf $p_ReturnVal[0] = 1 Then
        Return $p_ReturnVal ;Only 1 window.
    Else
        Return 0 ;Window not found.
    EndIf
EndFunc
Edited by RulerOf
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...