Я собираюсь ответить на это с чисто точки зрения Win32 C &, потому что я не знаю Delphi или ее библиотеки. Преобразование этого в C# можно выполнить с помощью p/invoke, но некоторые части могут/должны быть неуправляемыми.
Во-первых, нет гарантий. Если целевое приложение делает элементы управления без окон (если на каждом экранном элементе нет HWND
), вам в значительной степени не повезло. Это не все, что редко, так что да ...
Шаг 1, зарегистрировать окна крючок прослушивания для новых окон, созданных целевого процесса *:
//dllHMod is an HMODULE that refers to the DLL containing ShellHookProc
HHOOK hook = SetWindowsHookEx(WH_SHELL, ShellHookProc, dllHMod, 0);
// error handling, stashing hook away for unregistering later, etc...
LRESULT CALLBACK ShellHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0) return CallNextHookEx(NULL, nCode, wParam, lParam);
if(nCode == HSHELL_WINDOWCREATED)
{
WindowCreate((HWND)wParam);
}
return 0;
}
WindowCreated(HWND)
должен копить HWND прочь, если Правильный процесс (определяется через GetWindowThreadProcessId
). На этом этапе вы сможете получить каждое окно верхнего уровня, принадлежащее целевому процессу. Обратите внимание, что регистрация глобального крючка несет заметное снижение производительности, а не то, что это действительно имеет значение в вашем случае, но вы должны ожидать этого.
Теперь для забавной части. Нет надежного способа узнать, когда окно полностью сконструировано, или когда его делается рендеринг (есть способы сказать, когда он STARTS рендеринг, но это действительно не помогает). Мой совет, guess. Просто бросьте какое-то произвольное ожидание, а затем попробуйте и перечислите все дочерние окна.
Чтобы перечислить дочерние окна (если вы знаете достаточно о целевом окне, есть лучшие способы сделать это, но я предполагаю, что поиск проще всего):
//targetHWND is an HWND of one of the top-level windows you've found
EnumChildWindows(targetHWND, ChildWindowCallback, NULL);
//more code...
BOOL ChildWindowCallback(HWND window, LPARAM ignored)
{
if(IsTargetWindow(window)) { /* Do something */ }
return TRUE;
}
Реализация IsTargetWindow
еще одна сложная часть ,Надеемся, вы найдете для этого надежный тест (например, проверьте имя класса, имя окна, стиль, что-то, посмотрите на GetWindowInfo
).
Как только у вас есть окно, которое вы хотите контролировать, вы можете использовать SetWindowLongPtr
и GWLP_WNDPROC
, чтобы просмотреть все сообщения, которые он получает. Это потребует ввода кода (и, следовательно, неуправляемого кода) и ужасно низкого уровня. Я бы посоветовал это сделать, если бы вы могли избежать этого, но у вас не было источника ...
Я думаю, что этот ответ является достойной отправной точкой, но еще раз это будет невероятно болезненно, если это возможно вообще. Удачи.
* Кроме того, если вы знаете, что целевое приложение не создает окна, кроме как при запуске (или во время обнаружения/прогнозируемых точек), вы можете использовать EnumWindows
.
Whew. Прошло пять лет с тех пор, как я разработал последнее программное обеспечение в Delphi, поэтому я не полностью готов ответить, но это звучит совершенно невозможно, когда единственное, что у вас есть, это двоичный файл. И я не хочу быть ликующим или быть умным, но такие вещи являются аргументами для Open Source - если не открыты для публики, то, по крайней мере, открыты для оплачивающего клиента. –
На каком языке вы работаете? –