Как получить hWnd для дочернего окна и активировать его с помощью API FindWindowEx - PullRequest
0 голосов
/ 11 февраля 2019

Я использую MS Access 2016 VBA для автоматизации доступа к внешнему приложению.Во внешнем окне приложения есть видео, которое отображается в дочернем окне.

Если я использую spyxx.exe, я могу использовать «Средство поиска», чтобы получить дескриптор элемента управления видео (который, конечно, изменяется), Заголовок («панель»), Класс («wxWindowNR») иСтиль (52000000).Когда я использую дескриптор, возвращенный spyxx.exe, я могу успешно использовать этот дескриптор, чтобы вывести правильное приложение наверх и активировать его.Но так как этот дескриптор изменяется, мне нужно получить его динамически, используя MS Access VBA.

Проблема, с которой я столкнулся, заключается в том, что я не могу понять, как получить тот же дескриптор, который появляется в spyxx.exe, когда яиспользуйте API FindWindowEx, чтобы попытаться получить дескриптор окна дочернего видео.Вот что я пытаюсь (и несколько вариаций на тему): Декларация:

Public Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hwndParent As Long, ByVal hwndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long

и код (чтобы попытаться), чтобы получить дескриптор окна дочернего видеоis (где WinHand - дескриптор родительского окна):

FindWindowEx(WinHand, 0, "wxWindowNR", "panel")

Я знаю, что WinHand подходит для родительского окна, потому что с помощью WinHand я могу сделать приложение активным, самым верхним окном.Однако я никогда не смогу заставить FindWindowEx возвращать дескриптор, который показывает spyxx.exe, дескриптор дочернего окна «панели».

Это возвращает возвращаемые дескрипторы, когда я оставляю имя дочернего окна пустым, как это:

FindWindowEx(WinHand, 0, "wxWindowNR", "")

Но никогда правильный дескриптор этого spyxx.exe показывает.

При поиске в сети большую часть дня кажется, что мне может понадобиться что-то сделать с помощью API EnumChildWindows, но я не знаю, как ссылаться на него в MS Access VBA или как проходить черезвернулись окна, чтобы найти дескриптор окна «панель».

1 Ответ

0 голосов
/ 11 февраля 2019

В интересах тех, кто может столкнуться с подобной проблемой в будущем, я публикую свое решение, которое я использовал (хотя я хотел бы увидеть решение, предлагаемое с использованием EnumChildWindows, так как, похоже, это более элегантный подход,но я не достаточно разбираюсь в API, чтобы знать, как его настроить).

FindWindowEx не смог найти искомое окно элемента управления видео, которое я искал, потому что этот элемент управления был похоронен как дочерний элемент дочернего элементаребенок от ребенка ребенок от родителя.FindWindowEx будет искать только дочерние элементы непосредственно предшествующего родителя.Таким образом, вы должны вложить поиск для скрытого дочернего элемента управления.

Шаги, за которыми я следовал:

  1. Откройте целевое приложение, к окну которого и дочернему окну вам нужно получить доступ из VBA.
  2. Запустите Spyxx.exe (он же Spy ++)
  3. Используя инструмент «Найти окно», получите дескриптор, заголовок и класс дочернего оконного элемента управления, чья дескриптор вам нужен
  4. Запишитеэтих элементов, а затем закройте инструмент «Найти окно»
  5. Все еще используя Spyxx.exe, используйте пункт меню «Дерево / Сохранить дерево в файл ...» (или нажмите CTRL + S), чтобы сохранить дерево оконв текстовый файл (обратите внимание, что по умолчанию для сохранения сохраняется его как объект .sxt Spy ++, который вам здесь не нужен)
  6. Откройте список дереватекстового файла Windows, который вы сохранили в своем любимом текстовом редакторе (он был отформатирован для меня с помощью Notepad ++) и выполните поиск дескриптора окна, который вы отметили в шагах № 3 и № 4 выше
  7. Это должно найти ребенкаокно в дереве, которое вы хотите
  8. Теперь работайте в обратном направлении вверх по дереву, выполняя следующие шаги, пока не дойдете до дескриптора родительского окна.
  9. Запишите заголовок окна для следующего окна повышения уровня - заголовок заключен в двойные кавычки;эта надпись понадобится вам, когда вы напишите код VBA позже
  10. Теперь перейдите на следующий уровень окна вверх и запишите заголовок для этого окна
  11. Продолжайте перемещаться вверх по уровням окна, пока не дойдете дородительское окно для самого приложения

Последний шаг: теперь в коде VBA, чтобы найти дескриптор окна целевого дочернего оконного элемента управления, вам нужно будет вложить команды FindWindowExначиная с родительского окна и продвигаясь вниз по этому пути (замените «wxWindowNR» на любой класс окна, относящийся к дочернему элементу управления, который вы пытаетесь найти):

FindWindowEx (ParentWindowHandle, 0, "wxWindowNR", "[caption from steps 9 to 11]")

Например, вот кодЯ должен был использовать (где ChildWindow5 - дескриптор окна управления видео, которое я искал; команды While ... Wend необходимы, потому что в приложении, на которое я нацеливался, не все дочерние окна существовали сразу при запуске приложения):

ParentWindow = 0
While ParentWindow = 0
    ParentWindow = FindWindow("Target Window Caption")
Wend

ChildWindow1 = 0
While ChildWindow1 = 0
    ChildWindow1 = FindWindowEx(CLng(ParentWindow), 0, "wxWindowNR", "ID_BOOKMARK_SPLITTERWINDOW")
Wend

ChildWindow2 = 0
While ChildWindow2 = 0
    ChildWindow2 = FindWindowEx(CLng(ChildWindow1), 0, "wxWindowNR", "ID_TOPPANEL_SPLITTERWINDOW")
Wend

ChildWindow3 = 0
While ChildWindow3 = 0
    ChildWindow3 = FindWindowEx(CLng(ChildWindow2), 0, "wxWindowNR", "ID_MAINDISPLAY_PANEL")
Wend

ChildWindow4 = 0
While ChildWindow4 = 0
    ChildWindow4 = FindWindowEx(CLng(ChildWindow3), 0, "wxWindowNR", "ID_VIDEODISPLAY_PANEL")
Wend

ChildWindow5 = 0
While ChildWindow5 = 0
    ChildWindow5 = FindWindowEx(CLng(ChildWindow4), 0, "wxWindowNR", "panel")
Wend

Обратите внимание, что каждый последующий поиск дескриптора дочернего окна ссылаетсяces предыдущее родительское окно.

Это сработало для меня.Я все еще думаю, что если кто-то может указать, как это сделать с EnumChildWindows, решение, вероятно, будет гораздо более элегантным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...