【问题标题】:Attach window to running application将窗口附加到正在运行的应用程序
【发布时间】:2010-01-02 13:10:42
【问题描述】:

我有客户使用较旧的、自定义构建的 ERP 应用程序,他们没有源代码,并且开发该应用程序的公司不再存在。应用程序是在 2000 年开发的,它是用 Delphi 构建的。由于最后一个可执行文件是 2003 年的,它可能是 D6 或 D7。

在一个重要的表单上,客户希望在某些字段中显示来自其他数据库的其他数据,并询问我是否可以在现有表单上“粘贴”数据。

我的第一个想法是构建应用程序:

  • windows 目标应用程序的浏览列表在窗体上创建和查找控件
  • 在显示目标表单时附加“some”事件以获取通知
  • 附加“some”事件,当目标表单上的字段发生更改时收到通知
  • 在小窗口覆盖目标窗体中显示附加信息

有没有关于如何做这样的事情的例子。我用这个问题标题的变体搜索了谷歌,但没有成功。

注意 - 没有计划重写 ERP 应用程序。

关于语言——我可以用 C# 或 Delphi 来做。

【问题讨论】:

  • 哇。自从我上次在 Delphi 中开发软件已经五年了,所以我不完全有资格回答,但是当你唯一拥有的是二进制文件时,这听起来很不可能。而且我并不是要高兴或成为一个聪明人,但像这样的事情是开源的论据 - 如果不向公众开放,那么至少向付费客户开放。
  • 你用什么语言开发?

标签: user-interface winapi controls spy++ cross-application


【解决方案1】:

我将从纯 C 和 Win32 的角度回答这个问题,因为我不了解 Delphi 或其库。可以通过 p/invoke 将其转换为 C#,但某些部分可能/将需要非托管。

首先,不保证。如果目标应用程序正在执行无 Windows 控件(如果每个屏幕控件下都没有 HWND),那么您就很不走运了。这并不少见,所以是的......

第一步,注册一个窗口挂钩,监听目标进程创建的新窗口*:

//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;
}

如果正确的进程(通过GetWindowThreadProcessId 确定)拥有它,WindowCreated(HWND) 应该将 HWND 隐藏起来。此时,您将能够获得目标进程拥有的每个顶级窗口。请注意,注册全局钩子会带来显着的性能损失,这在您的情况下并不重要,但您应该预料到它。

现在是有趣的部分。没有可靠的方法来判断窗口何时完全构建,或何时完成渲染(有一些方法可以判断它何时开始渲染,但这并没有真正帮助)。我的建议,。只需在那里随意等待,然后尝试枚举所有子窗口。

枚举子窗口(如果您对目标窗口有足够的了解,有更好的方法可以做到这一点;但我假设搜索是最简单的):

//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)。

一旦您有了想要监控的窗口,您就可以使用SetWindowLongPtrGWLP_WNDPROC 来查看它收到的所有消息。这将需要代码注入(因此需要非托管代码)并且级别非常低。如果您可以避免它,我建议您不要这样做,但缺少来源...

我认为这个答案是一个不错的起点,但再次这将是令人难以置信的痛苦,如果它甚至可能的话。祝你好运。

*或者,如果您知道目标应用程序不会创建窗口,除非在启动时(或在可检测/可预测的时间点),您可以使用EnumWindows

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    相关资源
    最近更新 更多