2010-01-02 2 views
0

У меня есть клиент, который использует старое, выполненное на заказ приложение ERP, для которого у них нет исходного кода, и компания, которая его разработала, больше не существует. Приложение разработано в 2000 году и построено с помощью Delphi. Поскольку последний исполняемый файл с 2003 года, это может быть D6 или D7.Прикрепить окно к запущенному приложению

В одной важной форме есть несколько полей, в которых клиент хотел бы отображать дополнительные данные из других баз данных и спрашивал меня, возможно ли использовать данные «клейкой ленты» по существующей форме.

Первая идея, которую я получил, чтобы построить приложение, которое будет: список

  • обзора из окна целевого приложения создает и найти элементы управления на форме
  • придают «некоторые» событие, когда, чтобы получить уведомление, когда отображается целевая форма
  • придает «некоторое» событие, когда, чтобы получить уведомление, когда поле на целевой форме изменяется
  • дисплея дополнительной информации в небольшом окне накладывания целевым образует

Есть ли примеры того, как это сделать. Я искал google с вариациями этого вопроса, но безуспешно.

Примечание - переписывание приложения ERP не планируется.

О языке - я могу сделать это с помощью C# или Delphi.

+0

Whew. Прошло пять лет с тех пор, как я разработал последнее программное обеспечение в Delphi, поэтому я не полностью готов ответить, но это звучит совершенно невозможно, когда единственное, что у вас есть, это двоичный файл. И я не хочу быть ликующим или быть умным, но такие вещи являются аргументами для Open Source - если не открыты для публики, то, по крайней мере, открыты для оплачивающего клиента. –

+0

На каком языке вы работаете? –

ответ

4

Я собираюсь ответить на это с чисто точки зрения 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.

+0

Кевин, большое спасибо за этот очень подробный ответ. – zendar