Страницы: 1
RSS
Нажать на кнопку во всплывающем окне другого приложения
 
Может кто-нибудь не полениться и написать пример макроса нажатия на кнопку "Кнопка1" окна с заголовком "Тест1" с помощью команд WinAPI??

Пытался найти рабочий пример, чтобы разобраться дальше, но ничего из найденного не срабытывает.
Изменено: tchack - 30.11.2022 09:58:12
 
Код
Option Explicit

Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hwndChildAfter As Long, ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Boolean
Private Declare PtrSafe Function PostMessageW Lib "user32" (ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Integer, ByVal lParam As Integer) As Boolean
Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long

Private Const GW_HWNDNEXT = 2
Private Const WM_KEYDOWN As Integer = &H100
Private Const VK_Enter = &HD
Private Const VK_ESCAPE = &H3

Sub myPressButton()
    Dim lhWndP As Long
    If GetHandleFromPartialCaption(lhWndP) = True Then
        'If IsWindowVisible(lhWndP) = True Then
        'End If
    End If
End Sub

Private Function GetHandleFromPartialCaption(ByRef lWnd As Long) As Boolean
    Const windowCaption = "Тест1"
    Const buttonCaption = "Кнопка1"
    
    Dim hwndButt As Long
    Dim lhWndP As Long
    Dim sStr As String
    GetHandleFromPartialCaption = False
    lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
    Do While lhWndP <> 0
        sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
        GetWindowText lhWndP, sStr, Len(sStr)
        sStr = Left$(sStr, Len(sStr) - 1)
        If InStr(1, sStr, windowCaption) > 0 Then
            GetHandleFromPartialCaption = True
            lWnd = lhWndP
            hwndButt = FindWindowEx(lhWndP, ByVal 0&, vbNullString, buttonCaption)
            PostMessageW hwndButt, WM_KEYDOWN, VK_Enter, 0
        End If
        lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
    Loop
End Function

 
МатросНаЗебре, а что здесь дописать, чтобы кнопку нажать:

Код
Sub myPressButton()
    Dim lhWndP As Long
    If GetHandleFromPartialCaption(lhWndP) = True Then
        'If IsWindowVisible(lhWndP) = True Then
        'End If
    End If
End Sub


Как найти окно и кнопку я разобрался. Как нажать эту кнопку??
 
Код
PostMessageW hwndButt, WM_KEYDOWN, VK_Enter, 0
 
МатросНаЗебре,

Может надо?:

Код
PostMessageW lhWndP, WM_KEYDOWN, VK_Enter, 0
 
Если кнопка на форме является выбранной, то можно и lhWndP.
 
МатросНаЗебре,
Код
PostMessageW hwndButt, WM_KEYDOWN, VK_Enter, 0
не срабатывает.

А как нажать кнопку с помощью клика мышки? Я добавил в код:

Код
Private Const BM_CLICK = &HF5


Код
PostMessageW hwndButt, BM_CLICK, 0, 0


Но тоже не срабатывает.

Код
Sub myPressButton()
    Dim hwndButt, lhWndP As Long
    If GetHandleFromPartialCaption(lhWndP) = True Then
        'If IsWindowVisible(lhWndP) = True Then
            PostMessageW hwndButt, BM_CLICK, 0, 0
        'End If
    End If
End Sub
 
Цитата
tchack написал:
с помощью клика мышки?
надо, наверное, API начать изучать. Мышка ничего не нажимает как-то иначе, от клавиатуры - она подает точно такие же команды, как привели выше. Т.е. от того, кого Вы заставите нажать кнопку сам процесс вообще не поменяется.
Цитата
tchack написал:
тоже не срабатывает.
судя по коду - и не должно, т.к. ищете одно окно, а команду вообще другому передаете. Нашли lhWndP, а нажать пытаетесь hwndButt. При этом совершенно непонятно - Вы это hwndButt вообще нашли?
Изменено: Дмитрий(The_Prist) Щербаков - 30.11.2022 11:53:40
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
С просторов:
Код
Replace
hwndButton = PostMessage(hwndButton, BM_CLICK, 0, 0)
with
Call SendMessage(hwndButton, WM_LBUTTONDOWN, 0&, ByVal 0&)
Call SendMessage(hwndButton, WM_LBUTTONUP, 0&, ByVal 0&)

If no-go also try replacing the 'Call SendMessage' with 'Call PostMessage' (no other changes needed). Btw, neither of those returns an HWND, so never use hwndButton = with them.

If you need the declares:
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
 
Да, кнопка, которую надо нажать не находится.

Я же правильно понимаю, что тут должно выводится значение не равное 0:
Код
Debug.Print FindWindowEx(FindWindow(vbNullString, "Тест1"), 0, vbNullString, "Отмена")

также как тут выводится значение не равное 0:
Код
Debug.Print FindWindow(vbNullString, "Тест1")


Правильный ход мыслей?
 
Цитата
tchack написал:
Я же правильно понимаю
именно. Вы ищете хэндл(уникальный идентификатор) окна. И если возвращается 0 - значит это окно не найдено.
Если эта строка:
Код
FindWindow(vbNullString, "Тест1")

выводит 0 - значит окна с заголовком "Тест1" просто нет среди открытых окон. Возможно, текст окна задан неверно. Наверное, имеет смысл скачать программу, которая умеет считывать все окна и выдавать о них информацию. Тогда будет проще написать код.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Окно находится, кнопка на нем не находится.

Код
Debug.Print FindWindowEx(FindWindow(vbNullString, "Тест1"), 0, vbNullString, "Отмена")

Здесь выдается 0.

Caption кнопки копирую через Microsoft Spy++. Может параметры не так проставлены??
Изменено: tchack - 30.11.2022 14:17:41
 
Цитата
tchack написал:
Здесь выдается 0
идите последовательно.
Код
dim hwnd
hwnd = FindWindow(vbNullString, "Тест1")
if hwnd <> 0 then
  Debug.Print "Parent window hwnd: " & hwnd
  hwnd = FindWindowEx(hwnd, 0, vbNullString, "Отмена")
  Debug.Print "Button window: " & hwnd
end if

и если действительно не находится именно кнопка "Отмена" - значит либо она принадлежит не этому окну, либо надпись все же различается. Например, на многих кнопках в реальности есть еще и знак амперсанда для гор.клавиш - "&Отмена". Если он есть - его так же необходимо включать в текст для поиска.
Так же попробуйте вместо vbNullString принудительно указать класс окна, который видите в Spy:
Код
hwnd = FindWindowEx(hwnd, 0, "Button", "Отмена")
Изменено: Дмитрий(The_Prist) Щербаков - 30.11.2022 14:28:28
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Код
Debug.Print FindWindowEx(FindWindow("TfrmRadioSel", "Тест1"), 0, vbNullString, "Отмена")

Указал класс. Все равно 0.

Код
    Dim hwnd As Long
    hwnd = FindWindow("TfrmRadioSel", "Тест1")
    If hwnd <> 0 Then
        Debug.Print "Parent window hwnd: " & hwnd
        hwnd = FindWindowEx(hwnd, 0, vbNullString, "Отмена")
        Debug.Print "Button window: " & hwnd
    End If

Все равно 0 у кнопки.

PS: Само окно находится всегда, а кнопка на нем нет.
Названия класса и текст для поиска я копирую исключительно из SPY++. Амперсанда нет.
Изменено: tchack - 30.11.2022 14:55:11
 
Может проблема в том, что в окне TfrmRadioSel есть TPanel, на которой и находится TButton "Отмена".
TPanel не имеет Caption.
 
Цитата
написал:
Указал класс
Я же написал указать класс для кнопки, а не её окна. Вот для кого пишем и предлагаем, непонятно...
FindWindowEx(FindWindow("TfrmRadioSel", "Тест1"), 0, vbNullString, "Отмена")
жирным текстом - это код поиска ОКНА. И вот в нем как раз указывать класс ну совсем не обязательно. А вот для кнопки - там где "Отмена" - можно попробовать. Я же даже строку кода привел - и все равно не туда воткнули  8-0
А Вы добавляете класс туда, где по Вашим же словам и так все ищется, но ничего не меняете там, где не находится. Где логика?
Специально выделил на этот раз жирным, раз правильное разделение кода, предложенное мной выше, Вам почему-то никак не хочется применять. Хотя это более правильно, чем стремление все в одну строку запихнуть.
Цитата
tchack написал:
Может проблема в том
мне кажется главная проблема в том, что Вы пока совершенно не понимаете, что вообще делаете. А мы тем более не понимаем, что там у Вас где и как правильно.
Изменено: Дмитрий(The_Prist) Щербаков - 30.11.2022 15:03:02
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Пардон, но я проверил все варианты. И с указанием класса для окна и кнопки, только для окна, только для кнопки - все равно 0.

Ранее я писал, что в окне TfrmRadioSel есть TPanel (причем их две и обе без caption), так вот какая-то из них находится.
 
Цитата
tchack написал:
Пардон, но я проверил все варианты.
ага, а как пример привели самый нерабочий из проверенных и совсем не похожий на тот, что предлагали? :) Не делайте так больше, чтобы не путать других и лишних комментариев по таким вопросам не получать.
Цитата
tchack написал:
Ранее я писал
это все хорошо, но в деле с окнами гадать вообще не вариант. Кроме Вас до правды никто не докопается и тем более не угадает сколько там еще окон у Вашего приложения и какому из них принадлежит кнопка. Может надо сначала одно окно найти, потом второе и уже потом - кнопку. Откуда нам знать?
Пробуйте, комбинируйте варианты - возможно, придется не одно окно перебрать. Но что делать...
Если не известно свойство Caption - ищите по классам, перебирайте каждой и в каждом ищите свою кнопку. Нечего больше советовать при таких условиях.
Изменено: Дмитрий(The_Prist) Щербаков - 30.11.2022 15:13:35
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
Страницы: 1
Наверх