Что нового

[Окна, Диалоги] Узнать handle(HWND) окна по связаному с ним PID

bic

Знающий
Сообщения
46
Репутация
14
Приложение запущено два раза.
При запуске получил два разных PID.

Можно ли по PID узнать handle связаного с ним окна?
Либо получить handle при запуске приложения?

Все контролы отсутствуют, текст тоже.
Все остальные показатели одинаковые, за исключение handle & PID.

handle нужен для ControlSend

Сейчас получаю handle после запуска приложения, пока окно активно.
Код:
$handle = WinGetHandle("[ACTIVE]")

Единственный ли это способ?
 
Автор
B

bic

Знающий
Сообщения
46
Репутация
14
Мне бы handle а не PID
PID получаю при запуске приложения.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 471
Репутация
2 401
Код:
$hWin = _WinGetHandleEx(@AutoItPID, "", "", "", 0)

MsgBox(64, "Result", "hWnd: " & $hWin & ", Title: " & WinGetTitle($hWin))

Func _WinGetHandleEx($iPID, $sClassNN="", $sPartTitle="", $sText="", $iVisibleOnly=1)
    If IsString($iPID) Then $iPID = ProcessExists($iPID)
    
	Local $sWList_Str = "[CLASS:" & $sClassNN & ";REGEXPTITLE:(?i).*" & $sPartTitle & ".*]"
	If $sClassNN = "" Then $sWList_Str = "[REGEXPTITLE:(?i).*" & $sPartTitle & ".*]"
	
    Local $aWList = WinList($sWList_Str, $sText)
    If @error Then Return SetError(1, 0, "")
    
    For $i = 1 To $aWList[0][0]
        If WinGetProcess($aWList[$i][1]) = $iPID Then
            If Not $iVisibleOnly Or ($iVisibleOnly And BitAND(WinGetState($aWList[$i][1]), 2)) Then Return $aWList[$i][1]
        EndIf
    Next
    
    Return SetError(2, 0, "")
EndFunc
 
Автор
B

bic

Знающий
Сообщения
46
Репутация
14
Функция возвращает пустую строку hWnd.
ControlSend Работает только с активным окном, так же как send.
 
Автор
B

bic

Знающий
Сообщения
46
Репутация
14
Код:
$PID = run("notepad.exe")
WinWaitActive("Безымянный")
;~ $hWin = WinGetHandle("[ACTIVE]")
;~ MsgBox("","",$hWin) ; выдает что-то типа 0x00610206
;================================================================================
$hWin = _WinGetHandleEx($PID)

MsgBox(64, "Result", "hWnd: " & $hWin & ", Title: " & WinGetTitle($hWin))

Func _WinGetHandleEx($iPID, $sClassNN="", $sPartTitle="", $sText="", $iVisibleOnly=1)
    If IsString($iPID) Then $iPID = ProcessExists($iPID)

    Local $aWList = WinList("[CLASS:" & $sClassNN & ";REGEXPTITLE:(?i).*" & $sPartTitle & ".*]", $sText)
    If @error Then Return SetError(1, 0, "")

    For $i = 1 To $aWList[0][0]
        If WinGetProcess($aWList[$i][1]) = $iPID Then
            If Not $iVisibleOnly Or ($iVisibleOnly And BitAND(WinGetState($aWList[$i][1]), 2)) Then Return $aWList[$i][1]
        EndIf
    Next

    Return SetError(2, 0, "")
EndFunc
;================================================================================

WinSetState ( $hWin,"" , @SW_MINIMIZE )
ControlSend($hWin, "", "[CLASS:Edit; INSTANCE:1]", "sss")


Если handle узнавать по PID, то возвращает пустую строку $hWin и ControlSend не работает.
Если же handle узнавать по только что созданному окну, возвращает что-то типа 0x00610206 и ControlSend работает.
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
bic
Вот этот пример проверял на Блокноте, работает...

Код:
; НАЧАЛО

$varPID = Run ("notepad")
WinWait ("Безымянный -")
$hwnd = _GetHwnd($varPID)

WinMove ($hwnd, "", 100, 100, 500, 200)

Sleep (1000)

$varPID2 = Run ("notepad")
WinWait ("Безымянный -")
$hwnd2 = _GetHwnd($varPID2)

WinMove ($hwnd2, "", 100, 400, 500, 200)

Sleep (1000)

ControlSend ($hwnd, "", "Edit1", "Why hello there!" & @CR, 1)
ControlSend ($hwnd2, "", "Edit1", "Hello to you, how's it going?" & @CR, 1)
ControlSend ($hwnd, "", "Edit1", "Oh quite well, and you?" & @CR, 1)
ControlSend ($hwnd2, "", "Edit1", "No complaints here." & @CR, 1)

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

; КОНЕЦ


(источник)
 
Автор
B

bic

Знающий
Сообщения
46
Репутация
14
snoitaleR
Спасибо, работает как надо.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 471
Репутация
2 401
bic [?]
Если handle узнавать по PID, то возвращает пустую строку $hWin и ControlSend не работает
Мне показалось что я успел поправить функцию прежде чем её увидят :smile: но как оказалось не успел. У меня в посте немного другая функция ;)
 
Автор
B

bic

Знающий
Сообщения
46
Репутация
14
CreatoR
Точно, все работает, спасибо. :ok:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Все намного проще.

_WinAPI_EnumProcessWindows() из WinAPIEx.au3.

Возвращает список всех окон (хендлов) связанных с указанным процессом (PID).

;)

CreatoR, snoitaleR

Окон у процесса может быть > 1. Если я не ошибаюсь, то в ваших примерах используется только первое найденное в списке окно, что не есть универсальный метод. Кстати, я даже создавал такую тему.

bic

Нужно иногда пользоваться поиском по форуму.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 471
Репутация
2 401
Yashied [?]
Все намного проще
Для меня если честно проще использовать одну функцию для одной конкретной задачи, чем подключать целую библиотеку...

Окон у процесса может быть > 1
Ты думаешь я об этом не знаю? :smile:

в ваших примерах используется только первое найденное в списке окно, что не есть универсальный метод
Я не притендовал на универсальность, и в задаче автора темы нет уточнения, сколько окон ему нужно, раз написал что нужно окно процесса, то логично предположить что первое попавшееся.

Нужно иногда пользоваться поиском по форуму
Кроме твоей темы, в «Похожие темы» ниже есть ещё одна (я бы сказал превратившаяся позже в забавную тему) от `p r o x y: http://autoit-script.ru/index.php?topic=351.0
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
CreatoR и Yashied по поводу
я бы сказал превратившаяся позже в забавную тему...
Пиво я тогда пил оба раза, а на свои вопросы только сейчас надкнулся. Пардон...
 
Верх