Wpf 我如何构建一个Windows应用程序,该应用程序截取并通过击键和鼠标单击传递给其他应用程序?

Wpf 我如何构建一个Windows应用程序,该应用程序截取并通过击键和鼠标单击传递给其他应用程序?,wpf,winforms,winapi,topmost,Wpf,Winforms,Winapi,Topmost,我正在与一位希望向遗留应用程序添加功能的客户合作。该应用程序的供应商是无用的,它有一个Windows窗体UI。我的客户想要的是,当用户单击应用程序中的一条信息时,会触发此应用程序之外的某些功能 我已经看到为另一个客户做了一个简单的版本。在本例中,有一个应用程序由一个表单组成,该表单已使用SetWindowPos设置为最顶部的窗口。当用户单击此表单上的按钮时,应用程序会找到旧应用程序的窗口,并从窗口标题中获取信息。这是不雅的-有这个浮动按钮,永远不会消失,即使传统的应用程序没有打开-但它的工作 我

我正在与一位希望向遗留应用程序添加功能的客户合作。该应用程序的供应商是无用的,它有一个Windows窗体UI。我的客户想要的是,当用户单击应用程序中的一条信息时,会触发此应用程序之外的某些功能

我已经看到为另一个客户做了一个简单的版本。在本例中,有一个应用程序由一个表单组成,该表单已使用
SetWindowPos
设置为最顶部的窗口。当用户单击此表单上的按钮时,应用程序会找到旧应用程序的窗口,并从窗口标题中获取信息。这是不雅的-有这个浮动按钮,永远不会消失,即使传统的应用程序没有打开-但它的工作

我想知道是否可以使用一个带有
最顶层属性集的无边界透明WPF窗口来做类似的事情。我想到的应用程序将分析遗留应用程序窗口中的内容,并定义热点列表。它将拦截和处理热点中的任何鼠标点击,并将所有剩余的鼠标点击传递给遗留应用程序

我对WindowsAPI没有太多的经验,所以我不知道实现这种功能是否简单(甚至可能)。我突然想到,如果我在创作反恶意软件工具,我心目中的应用程序正是我想要削弱的东西


如果这确实是一个可行的项目,那么最好的方法是什么?我应该注意哪些意外问题?

这可以通过和/或
WH_GETMESSAGE
钩子使用重叠按钮来实现,而不需要任何技巧。

戴维斯建议的替代方法是使用
GetWindowLong
SetWindowLong
CallWindowProc
要挂接应用程序窗口程序,我认为它比使用“windows挂接”方法简单一些,但仍然可以通过该方法挂接和/或再次子类化。有关一个简短的示例,请参见msdn上的窗口子类化:

我一定会尝试。它可能不起作用,但至少应该很容易尝试。而且,大多数情况下,如果它不起作用,就意味着没有其他“简单”的方法

UI自动化植根于为残疾人提供的辅助技术,这在大多数情况下是我们想要用我们不拥有的应用程序来做的:从外部应用程序做事情,而不能真正以“标准方式”来做

它在逻辑上也有事件的概念,请参见此处的Officel文档:
在我看来,子类化是您需要的

创建Windows应用程序时,它会生成一个窗口,然后向该窗口添加子窗口(子窗口称为控件,其行为与窗口完全相同!它们可以是按钮、文本区域等)

每个窗口都有一个窗口过程,每次用户/程序与您的窗口交互时,您的窗口过程都会收到一条包含交互信息的消息。通常,控件与其父控件共享一个窗口过程,在该窗口过程中,代码根据消息所描述的窗口/控件的ID(hwnd)确定要执行的操作,也就是说:“如果“单击”消息描述退出按钮控制,则关闭程序。如果“单击”消息描述父窗口,则不执行任何操作。“

要了解有关Windows的更多信息,请查看此处:

子类化是截取和/或捕获发送给另一个窗口过程的消息的过程。它通常作为扩展第三方应用程序的控件和窗口行为的一种方式。可以使用DLL
GetWindowLong()
SetWindowLong()对另一个过程进行子类化
调用WindowProcedure()
,以及您自己的自定义窗口过程。这非常简单-下面是您如何操作的:

  • 使用
    FindWindow()
  • 获取上一个窗口过程并将其存储
WNDPROC wborigeditproc=GetWindowLong(hTargetWnd,GWL\u WNDPROC)

  • 用您自己的覆盖窗口过程
SetWindowLong(hTargetWnd、GWL\u WNDPROC、HookWndProcedure);

然后,在卸载时,再次还原旧的窗口过程。窗口过程是您的所有魔术将发生的地方。您将能够在该函数中决定希望处理哪些消息以及希望将哪些消息传递给旧的窗口过程。下面是一个窗口过程示例:

LRESULT APIENTRY HookWndProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 
    if(hwnd == hTargetWndButton_OK) {
        // This is the button we wish to intercept... do some processing, then send it back to Windows
        return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } else {
        // Allow the message to pass through to the original application's window procedure.
        return CallWindowProc(wpOrigEditProc, hwnd, uMsg, 
            wParam, lParam); 
    }
} 
`

然后,诀窍是将DLL加载到目标进程中。我认为最好的方法是将指向DLL的导入项添加到应用程序中,因为应用程序和DLL应该始终捆绑在一起。要添加导入,请使用CFF Explorer

我相信你会有更多的问题,因为可能会丢失一些信息。我会尝试回答我的帖子中出现的任何问题,但如果我不立即回复,请阅读上面的MSDN链接:D。希望这将成为你的一次很好的学习体验:)

检查diz:


它可以编写脚本,可以阅读窗口标题等。(当我使用MS Windows时,我编写了一个小脚本,弹出一个窗口,显示物品价格和p+p成本之和,这些值是从ebay网页的选择中解析出来的。此外,我还将其更改为我的货币。因此,我只需标记物品的价格和p+p,然后按下一个键,瞧。)

你需要对应用程序中的所有窗口进行子类化,这很费劲。@david:你只需要对所有高级窗口进行子类化,根据我对op的问题的理解,只有1个窗口需要子类化混乱呢