powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
8 сообщений из 8, страница 1 из 1
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38276966
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сразу определимся что нескольких экземпляров такого окна быть не может (страхуется при запуске EXE).
Простой метод такой:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
 ByVal strClassName As String, _
 ByVal lpWindowName As Any) As Long

Private Sub CommandFindWindow_Click()
  Dim hwndTarget As Long
  hwndTarget = FindWindow(vbNullString, "My proga name")
  MsgBox hwndTarget
End Sub


В принципе это работает. Но это не надежно
1) Я могу создать папку с именем "My proga name", запустить совершенно другой EXE с таким же именем и т.д.
2) Даже если нет условий п.(1), то... я на Висте столкнулся с проблемой. Вдруг перестала находить окно. Debug показал что
hwndTarget=65728 Оч.странное число, гуглил, ведет куда-то в SystemTray_Main, но точно не в мое окно.

Метод которым надо действовать я в принципе понял (даже Ципиховичу или BeloZero -не помню кому именно, его когда-то советовал).
Делаем перебор окон:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
Private Sub CommandFindEnum_Click()
  Dim hwndTarget As Long
  hwndTarget = FindMyWindow
  MsgBox hwndTarget
End Sub

Public Function FindMyWindow() As Long
  hwndEnumTarget = 0
  EnumWindows AddressOf EnumWindowsProc, 1 '1-конкретное окно, пока используем GetWindowText=Form.Caption
  FindMyWindow = hwndEnumTarget
End Function

Private Function EnumWindowsProc(ByVal app_hwnd As Long, _
 ByVal lParam As Long) As Boolean
' Return False to stop the enumeration.
 
  Dim buf As String * 256
  Dim Title As String
  Dim length As Long

  ' Get the window's title.
  length = GetWindowText(app_hwnd, buf, Len(buf))
  Title = Left$(buf, length)
  If lParam = 1 Then 'конкретное окно (пока заданный в Caption текст)
    If Title = "My proga name" Then
      hwndEnumTarget = app_hwnd
      EnumWindowsProc = False ' Save the hwnd and end the enumeration
      '---Debug---
      Debug.Print Title & " (" & app_hwnd & ")"
      Form1.Text1.Text = Title & " (" & app_hwnd & ")"
      '---Debug---
      Exit Function
    End If
  Else 'lparam=0 (все окна)
    '---Debug---
    Debug.Print Title & " (" & app_hwnd & ")"
    Form1.Text1.Text = Form1.Text1.Text & vbCrLf & Title & " (" & app_hwnd & ")"
    '---Debug---
  End If
  
  EnumWindowsProc = True ' Continue the enumeration (default)
End Function



Но: в том виде как я этот код написал этот код делает то же самое (сравнивает If Title = "My proga name", возвращает app_hwnd и выходит) и будет также ошибаться, как и предыдущий.

Т.е. вопрос.
На что заменить код
Код: vbnet
1.
If Title = "My proga name" Then


Я знаю app_hwnd окна, я хочу знать что
ЭТО ИМЕННО НУЖНОЕ ОКНО
Каким свойством (кроме Title) снабдить окно (целевой EXE тоже мой) и как это свойство запросить из другого EXE зная app_hwnd ?

Я пробовал GetWindowModuleFileName, но "буков много" и кажется это неэффективно.

Можно еще поиграться с ByVal strClassName As String в FindWindow (первый метод), но это вряд ли сработает против EXE-муляжа с таким же именем.
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277202
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как вариант...

Добавить в целевое окно кнопку, сделать ей:

Код: vbnet
1.
2.
Button.Caption = "This is the GUID qwertyuiop" 'такую фигню случайно не придумаешь
.Visible=false



И искать перебором типа

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
    If Title = "Form1" Then
      Dim hwndTemp As Long
      hwndTemp = FindWindowEx(app_hwnd, 0&, vbNullString, "This is the GUID qwertyuiop")
      If hwndTemp <> 0 Then 'если есть child с зарезервированной фигней в его Caption
        hwndEnumTarget = app_hwnd
        EnumWindowsProc = False ' Save the hwnd and end the enumeration
        Exit Function
      End If
    End If



Это работает.
Сойдет?
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277488
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любой вариант сойдет, если он делает то, что нужно, и ничего более.

Еще можно слать окну свое сообщение, если ответ есть, значит оно. Минус — нужно сабклассить окно и отвечать на сообщение.
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277514
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntonariyЕще можно слать окну свое сообщение, если ответ есть, значит оно. Минус — нужно сабклассить окно и отвечать на сообщение.
Собственно я это итак делаю:
Вот текущий (продакшн) код на стороне клиента:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
'запрос
Public Sub AskForNewDocumentName()
  hwndTarget = FindWindow(vbNullString, WINDOWTITLE_SERVER)
  If hwndTarget <> 0 Then
    Dim cds As COPYDATASTRUCT
    
    cds.dwData = 2 'идентифицирует тип передаваемых данных -запрос имени документа
    
    Call SendMessage(hwndTarget, WM_COPYDATA, Form1.hwnd, cds)
    
  End If
End Sub

...
'ответ
    Case WM_COPYDATA
      Dim cds As COPYDATASTRUCT
      Dim the_str As String
      
      Call CopyMemory(cds, ByVal lParam, Len(cds))
      
      If (cds.dwData = 2) And (wParam = hwndTarget) Then 'сообщение содержащее имя документа
        the_str = PtrToString_len(cds.lpData, cds.cbData)
        Form1.TextDocumentName.Text = the_str
      End If
      Exit Function



А проблема в том что на Висте уж не знаю при каких комбинациях запусков окон может случиться
что этот код
вместо реального hwndTarget возвращает hwndTarget=65728, что не соответствует реальному окну.
Соответственно никакого сообщения назад не приходит и Form1.TextDocumentName.Text пустой.
Да и следующую команду не пошлешь, hwndTarget то неправильный.

AntonariyЛюбой вариант сойдет, если он делает то, что нужно, и ничего более.
Вот я и спрашиваю. Код в моем предыдущем посте будет делать то что нужно и не более?
Т.е.
1) Он перебирает все окна
2) Он проверяет окно на соответствие WINDOWTITLE_SERVER
3) Он дополнительно проверяет окно на наличие CHILD с хитрым Caption = "qwertyuiopasdfg" (например)
4) Если окно найдено, то вернет его hwnd и прекратит перебор, если нет -переберет окна и вернет 0.

Просто проверка только WINDOWTITLE_SERVER не гарантирует от клона с таким же Caption,
и более того (а подозрение что нечто такое и вызывает глюк), я не уверен что при создании иконки в трее (для искомого окна) система не генерит окно с таким же именем WINDOWTITLE_SERVER (SystemTray_Main ???), которое и будет с какой-то вероятностью найдено вместо искомого.
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277867
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А проблема в том что на Висте уж не знаю при каких комбинациях запусков окон может случиться
что этот код
вместо реального hwndTarget возвращает hwndTarget=65728, что не соответствует реальному окну.Проблема в том, что ты отправляешь не свое сообщение, а системное. Нет никаких гарантий, что системе не вздумается обработать его после тебя и переписать параметры. Свое сообщение это WM_USER + произвольное число. Значения больше WM_USER система гарантированно игнорирует.
Дмитрий77Вот я и спрашиваю. Код в моем предыдущем посте будет делать то что нужно и не более? Это покажет лишь тестирование.
Дмитрий771) Он перебирает все окна
2) Он проверяет окно на соответствие WINDOWTITLE_SERVER
3) Он дополнительно проверяет окно на наличие CHILD с хитрым Caption = "qwertyuiopasdfg" (например)
4) Если окно найдено, то вернет его hwnd и прекратит перебор, если нет -переберет окна и вернет 0.Чем больше условий тем больше вероятность не срабатывания алгоритма.
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277874
_Дмит_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как-то искал окна с пустым Caption (их было несколько, не только нужные), выкрутился используя GetModuleFileNameEx
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38277901
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ведь верно. У меня даже была функция FileByHwnd, но я ей не пользовался, и найти сейчас не могу.
...
Рейтинг: 0 / 0
Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
    #38279415
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Дмит_GetModuleFileNameEx
Не совсем понимаю причем тут именно эта ф-ция.
Я смотрел в сторону GetWindowModuleFileName (работает аналогично GetWindowText).
Но она по ходу возвращает полные пути и не к exe а к vbm60 чего-то там.dll (и это не в IDE)
Мне это не понравилось.

Но думаю с перебором и перепроверкой по child я тоже неплохо выкрутился - пока этот свой вариант и внедрил, замечу проблемы -буду думать дальше.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как ТОЧНО и БЕЗОШИБОЧНО узнать hwndTarget целевого окна?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]