Jump to content

GetHwnd from Process


spudw2k
 Share

Recommended Posts

I started developing a cmdline tool to interact with and manipulate Window Forms Controls. I thought this was a useful func so I figured I share.

$hwnd = _GetHwnd("explorer.exe")
msgbox(0,"",$hwnd)

Func _GetHwnd($id,$txt="")   ;Retrieve Hwnd of process
    $proc = 0
    If _IsPIDOrProc($id) Then
        $proc = _PIDOrProcToHwnd($id)
    ElseIf _IsWinTitle($id,$txt) Then
        $proc = _WinTitleToHwnd($id,$txt)
    EndIf
    Return $proc
EndFunc

Func _IsPIDOrProc(ByRef $id)  ;Is running PID or Processname
    If Not ProcessExists($id) Then 
        Return 0
    Else
        Return $id
    EndIf
EndFunc

Func _IsWinTitle(ByRef $id,$txt="")  ;Is running Window Title
    $win = WinGetTitle($id,$txt)
    If Not $win Then Return 0
    $id = $win
    Return 1
EndFunc

Func _IsWinVisible($handle)   ;Is Window Visible
    If BitAnd( WinGetState($handle), 2 ) Then 
        Return 1
    Else
        Return 0
    EndIf
EndFunc

Func _PIDOrProcToHwnd($proc)   ;Convert PID or process to Hwnd
    If ProcessExists($proc) <> $proc Then
        $proclist = ProcessList($proc)
        $proc = $proclist[1][1]
    EndIf
    $var = WinList()   
    For $i = 1 to $var[0][0]   ;Pair PID/Process with Window Title
        If $var[$i][0] <> "" AND _IsWinVisible($var[$i][1]) Then
            If WinGetProcess($var[$i][0]) = $proc Then $proc = WinGetHandle($var[$i][0])
        EndIf
    Next
    Return $proc
EndFunc

Func _WinTitleToHwnd($proc,$txt="")   ;Convert Window title to Hwnd
    $winlist = WinList($proc,$txt)
    If Not $winlist[0][0] Then Return -1
    Return $winlist[1][1]
EndFunc

edit: added txt param

Edited by spudw2k
Link to comment
Share on other sites

Nice, but what if the process has a few windows?

Better hope you get the right one. :D Good question and point. I guess specifying the window name would be the only way in that case.
Link to comment
Share on other sites

You have the handle there. PIDs are just numbers, Task Manager will give you pids, you just have to enable to column.

Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic]

Link to comment
Share on other sites

Returns all windows (Handles) for the specified process.

#Include <Array.au3>
#Include <WinAPI.au3>

Opt('MustDeclareVars', 1)

Global $__Data, $aWnd = _WinAPI_EnumProcessWindows(ProcessExists('explorer.exe'), False)

If IsArray($aWnd) Then
    _ArrayDisplay($aWnd, '_WinAPI_EnumProcessWindows')
EndIf

Func _WinAPI_EnumProcessThreads($PID)

    If Not $PID Then
        $PID = _WinAPI_GetCurrentProcessID()
        If Not $PID Then
            Return SetError(1, 0, 0)
        EndIf
    EndIf

    Local $hSnapshot = DllCall('kernel32.dll', 'ptr', 'CreateToolhelp32Snapshot', 'dword', 0x00000004, 'dword', 0)

    If (@error) Or ($hSnapshot[0] = 0) Then
        Return SetError(1, 0, 0)
    EndIf

    Local $tTHREADENTRY32 = DllStructCreate('dword Size;dword Usage;dword ThreadID;dword OwnerProcessID;long BasePri;long DeltaPri;dword Flags')
    Local $pTHREADENTRY32 = DllStructGetPtr($tTHREADENTRY32)
    Local $Ret, $Result[101] = [0]

    $hSnapshot = $hSnapshot[0]
    DllStructSetData($tTHREADENTRY32, 'Size', DllStructGetSize($tTHREADENTRY32))
    $Ret = DllCall('kernel32.dll', 'int', 'Thread32First', 'ptr', $hSnapshot, 'ptr', $pTHREADENTRY32)
    While (Not @error) And ($Ret[0])
        If DllStructGetData($tTHREADENTRY32, 'OwnerProcessID') = $PID Then
            $Result[0] += 1
            If $Result[0] > UBound($Result) - 1 Then
                ReDim $Result[$Result[0] + 100]
            EndIf
            $Result[$Result[0]] = DllStructGetData($tTHREADENTRY32, 'ThreadID')
        EndIf
        $Ret = DllCall('kernel32.dll', 'int', 'Thread32Next', 'ptr', $hSnapshot, 'ptr', $pTHREADENTRY32)
    WEnd
    _WinAPI_CloseHandle($hSnapshot)
    If $Result[0] Then
        ReDim $Result[$Result[0] + 1]
    Else
        Return SetError(1, 0, 0)
    EndIf
    Return $Result
EndFunc   ;==>_WinAPI_EnumProcessThreads

Func _WinAPI_EnumProcessWindows($PID, $fVisible = 1)

    Local $Threads = _WinAPI_EnumProcessThreads($PID)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    Local $hEnumProc = DllCallbackRegister('__EnumWindowsProc','int','hwnd;int')
    Local $Error = 1

    Dim $__Data[101][2] = [[0]]
    For $i = 1 To $Threads[0]
        DllCall('user32.dll', 'int', 'EnumThreadWindows', 'dword', $Threads[$i], 'ptr',  DllCallbackGetPtr($hEnumProc), 'int', $fVisible)
        If @error Then
            $__Data = 0
            ExitLoop
        EndIf
    Next
    If IsArray($__Data) Then
        $Error = 0
        If $__Data[0][0] Then
            ReDim $__Data[$__Data[0][0] + 1][2]
        Else
            $__Data = 0
        EndIf
    EndIf
    DllCallbackFree($hEnumProc)
    Return SetError($Error, 0, $__Data)
EndFunc   ;==>_WinAPI_EnumProcessWindows

Func __EnumWindowsProc($hWnd, $fVisible)
    If ($fVisible) And (Not BitAND(WinGetState($hWnd), 2)) Then
        Return 1
    EndIf
    $__Data[0][0] += 1
    If $__Data[0][0] > UBound($__Data) - 1 Then
        ReDim $__Data[$__Data[0][0] + 100][2]
    EndIf
    $__Data[$__Data[0][0]][0] = $hWnd
    $__Data[$__Data[0][0]][1] = _WinAPI_GetClassName($hWnd)
    Return 1
EndFunc   ;==>__EnumWindowsProc
Edited by Yashied
Link to comment
Share on other sites

  • 1 month later...

Thanks, exactly what i need.

The result look to list all handles for all objects inside the specified process, i have a question is it possible to isolate and get only the handle of the principal window ?

e.g : with firefox.exe the class of the principal window is MozillaUIWindowClass

Maybe it is already available in you library but i don't understand Dll* fonctions i simply use basics function.

I make it work like that :

#Include <Array.au3>
#include "U:\_DSA\AutoIt\devs\zzzz_DEV_ssss cipe 18.08.09\zzz_shared_libs_sss\WinAPIEx\WinAPIEx.au3"

Opt("WinTitleMatchMode", 4)

Global $processName = "notepad.exe", $winClass = "Notepad", $result
Global $aWnd = _WinAPI_EnumProcessWindows($processName)

If IsArray($aWnd) Then
    $result = _ArraySearch($aWnd, $winClass, 0,0,0,1,0,1)
    $result = $aWnd[$result][0]
    MsgBox(0,"Text",WinGetText($result))
EndIf
Edited by ddeerr
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...