1

我正在编写一个对选定窗口进行一些更改的应用程序。我试图弄清楚如何在 c# 中按下按钮后选择窗口的 HWND。

流程将类似于:

用户按下一个显示选择窗口的表单按钮,表单隐藏自己不允许自己选择,用户在桌面上的另一个窗口中单击,这可以是任何应用程序,表单重新出现并收集所选的 HWND窗口中,程序使用 HWND 来处理它的事务。

我不知道该怎么做的部分是获取选择了哪个窗口。

任何帮助将不胜感激!

4

3 回答 3

1

执行此类操作的“经典”方式 -由 Spy++和各种其他允许您选择要检查或使用的 UI 的应用程序使用 - 类似于:(这是从 C++/Win32 API 点编写的查看,但除了 WindowFromPoint 和 GetAncestor 之外,大多数步骤都有 .Net 等效项)

  • 有一些显示十字准线的 UI,它响应 WM_LBUTTONDOWN/Control.MouseDown
  • 当它得到鼠标点击时,
    • 使用 SetCapture/ Control.Capture来“捕获”鼠标:这是一个神奇的部分,只要保持按下左键,您的 HWND 就会接收所有进一步的鼠标移动事件。(这意味着你不需要钩子或类似的东西。),
    • 使用 SetCursor 将光标设置到合适的位置,例如十字准线。
    • 在某处设置一个标志,以便您可以告诉您在拖动/捕获期间将要获得的鼠标移动事件,以及如果用户只是将鼠标正常移动到您的控件上,您将获得的鼠标移动事件。
  • 现在,当用户在屏幕上移动十字准线指针时,您将获得 WM_MOUSEMOVE/Control.MouseMove 事件 - 检查您之前设置的标志以确保这是在“拖动”期间。使用 ClientToScreen/Control.PointToScreen 从移动事件中的控件相对坐标获取屏幕坐标,使用 WindowFromPoint 获取该位置的最子窗口,并使用 GetAncestor(GA_ROOT) 获取顶级窗口。也许检查窗口是否设置了 WS_CAPTION 以确保它是带有标题栏的窗口,如果您关心的话。(您可能还想过滤掉任务栏和桌面窗口。)您还可以使用 GetWindowThreadProcessID 等 API 从您自己的进程中过滤掉窗口。如果 HWND 是一个可行的候选者,请将其保存在某个地方。如果您仍然有一些 UI,
  • 当用户释放鼠标位置时,您将获得 WM_LBUTTONUP/Control.MouseUp - 用户已完成拖动。ReleaseCapture,将图标和光标放回用户按下鼠标之前的状态,然后继续使用保存的 HWND - 如果有的话。

在拖动过程中也处理 ESC 以取消操作也被认为是礼貌的。

此外,上述内容对键盘不友好;在您的应用程序的生命周期内或仅在存在选择对话框时永久使用带有某些热键的说 RegisterHotkey 也是一个好主意,并使用 GetForegroundWindow() 响应热键,如其他回复中所述。

于 2012-09-11T06:33:46.333 回答
1

一种选择是轮询GetForegroundWindow API,直到 HWND 更改为另一个窗口。

于 2012-09-10T21:19:14.917 回答
0

一种方法是

  • 全局鼠标事件处理程序添加到您的应用程序
  • 最小化您的应用程序
  • 当您的全局事件处理程序检测到鼠标单击时:
  • 调用 GetForegroundWindow()
于 2012-09-10T21:18:52.653 回答