gpt4 book ai didi

c# - 如何获取应用程序的事件 ChildWindow?

转载 作者:行者123 更新时间:2023-11-30 18:10:52 27 4
gpt4 key购买 nike

我有这个问题:我有一个特定应用程序的主窗口的处理程序,我想在该应用程序上模拟按键...

我正在使用 sendMessage/postMessage api 调用来执行此操作。我不使用 .Net SendKeys 函数或 win32 api 的 keybd_event 的原因是它们在全局级别模拟按键。在我的例子中,目标应用程序不是最活跃的应用程序(其他应用程序可能在更高的 z 级别运行,因此覆盖了目标应用程序)。

sendMessage 和 postMessage 的问题在于您必须传递您希望按键被按下的确切子窗口的处理程序。例如,在记事本中,如果我将 key 发送到主窗口的处理程序,没有任何反应,我必须将 key 发送到基本上由您可以书写的白色 Canvas 组成的子窗口的处理程序。

获取事件子窗口的处理程序是问题所在。一开始,我使用 GetTopWindow 或 GetWindow(GW_CHILD) api 调用,因为它返回最活跃的子窗口。我正在做的是继续调用 GetWindow(GW_CHILD) 直到我得到一个没有更多子窗口的子窗口。这适用于某些应用程序,如记事本或绘画。但是,在某些情况下(例如 firefox),它不起作用。原因是父窗口有整个 firefox 区域,而它的子窗口有打开的网页(如 google)。所以,当我请求 mainWindow 最活跃的子窗口时,它返回它唯一的子窗口,也就是对应网页区域的那个。它仅在事件窗口是那个窗口时才有效(比如用户在某个页面的文本框上写东西)。但是,如果事件的是地址栏,它就不起作用,因为事件窗口不是子窗口,而是父窗口……我无法以编程方式获取此信息。

我实际上找到了一种方法,使用 GetGUIThreadInfo api 调用,使用以下代码:

    // get thread of the main window handle of the process
var threadId = GetWindowThreadProcessId(firefox.MainWindowHandle, IntPtr.Zero);

// get gui info
var info = new GUITHREADINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
if (!GetGUIThreadInfo(threadId, out info))
throw new Win32Exception();

// send the letter W to the active window
PostMessage(info.hwndActive, WM_KEYDOWN, (IntPtr)Keys.W, IntPtr.Zero);

而且效果很好:如果地址栏处于事件状态,它会向地址栏发送一个“W”字母。如果谷歌的搜索文本框处于事件状态,它会向它发送“W”字母......完美!但是,这个方法不能被我使用,原因很简单:如果目标应用程序不是操作系统的事件窗口,则 ThreadInfo 结构为空。例如,如果我的目标是 firefox,如果 firefox 处于事件状态(最顶层的应用程序,重点/事件的应用程序),它就可以工作,但是如果记事本位于 firefox 之上,它就不起作用,它无法获取事件窗口处理程序。

我知道我可以通过使用 setForegroundWindow api 调用来激活目标应用程序然后捕获事件子窗口的处理程序来解决这个问题,但我不想将目标应用程序带到前台。

我还尝试了其他技术,如 AttachThreadInput() 和 GetFocus() api 调用,它们也有效,但存在同样的问题:如果目标应用程序不是事件的 Windows 应用程序,它就不起作用。

所以基本上我需要找到一些方法让处理程序到达应用程序的事件子窗口,即使该应用程序不是最活跃的应用程序也是如此。

有什么想法吗?谢谢

最佳答案

您可能想查看 EnumChildWindows功能。

关于c# - 如何获取应用程序的事件 ChildWindow?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/834437/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com