我有一些预编译的 WPF 应用程序,我需要通过发送各种消息(例如:WM_POINTERMOVE、WM_KEYDOWN 等)来控制它们而无需重新编译它们。我尝试的控制方法是将消息注入(inject)应用程序消息泵。作为测试,我通过获取应用程序的窗口句柄,然后使用 SendMessage 发送消息,对其他一些 Win32 应用程序进行了尝试。
BOOL CALLBACK EnumWindowsProc(
_In_ HWND hwnd,
_In_ LPARAM lParam
)
{
LPWSTR windowName = new TCHAR[256];
GetWindowText(hwnd, windowName, 256);
std::wstring windowNameString(windowName);
int position = windowNameString.find(std::wstring(L"MyApplicationWindowName"));
if (position > -1) {
hTargetWindow = hwnd;
delete windowName;
return FALSE;//stop enumerating windows
}
delete windowName;
return TRUE;
}
.....
EnumWindows(EnumWindowsProc, NULL);;
SendMessage(hTargetWindow, MY_MESSAGE, 0, 0);
我使用 EnumWindows 检索了应用程序的 HWND(效果很好)。然后我使用 SendMessage 和 PostMessage 发送消息。而其他应用程序不会响应此 WPF 应用程序。作为另一个测试,我创建了一个 WPF 应用程序并添加了一些代码,以便在它收到特定消息时设置断点。
ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) =>
{
if(msg.message == MY_MESSAGE)
Debug.WriteLine("break");
};
断点永远不会被击中,表明消息没有进入消息泵。在其他类型的应用程序中尝试同样的事情会取得成功。注入(inject)这些消息我做错了什么。
最佳答案
我想在这里做一个更详细的回复,但时间有限,我在这里做一个总结。我确实找到了其他几个想要做同样事情的人。
处理 Windows 消息的 WPF 类会进行额外的检查。如果接收到鼠标消息而不是处理鼠标消息中的信息,WPF 将再次调用以查询鼠标光标以查看其实际位置,它将检查它是否真的具有焦点,等等(类似的检查是为其他一些输入消息完成)。根据 WPF 类库中的注释,如果这些检查中的任何一个失败,则假定发生了导致 WPF 错误地获取消息的某些情况。通过确保 WPF 应用程序具有焦点,我能够让事情适用于我的场景。
此外,我还必须做一些我不建议任何人做的事情,例如创建一个代理 User32.dll 来覆盖某些 WPF 行为。这适用于我的目的,但仅适用于单个操作系统版本。幸运的是,我的目标机器不会连接到 Internet 并且需要执行它一年左右的任务并且不会在它的隔离环境中接收任何操作系统更新; Windows 更新可以轻松终止此解决方案。
关于c++ - 将消息注入(inject) WPF 应用程序消息泵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39499578/