如何监控当前哪个窗口具有键盘焦点

jma*_*ias 15 winapi mfc

有没有办法跟踪哪个窗口当前有键盘焦点.我可以为每个窗口处理WM_SETFOCUS,但我想知道是否有一个替代的,更简单的方法(即某处的单个消息处理程序).

我可以在MFC中使用OnIdle()并调用GetFocus(),但这似乎有点hacky.

小智 17

因此,从你提出问题的方式来看,我推断你想要一个事件处理程序,只要焦点在窗口之间切换就会调用它.您希望得到通知,而不是必须进行投票.

我实际上并不认为从OnIdle调用GetFocus是一个很大的问题 - 确保它是轮询,但它是低开销的轮询,没有副作用 - 但如果你真的想跟踪它,Windows Hooks可能是你的最佳选择.具体来说,您可以安装CBT挂钩(WH_CBT)并侦听HCBT_SETFOCUS通知.

当Windows即将焦点设置为任何窗口时,Windows使用此挂钩代码调用WH_CBT挂钩.在特定于线程的钩子的情况下,窗口必须属于线程.如果过滤器函数返回TRUE,则焦点不会更改.

您还可以使用WH_CALLWNDPROC挂钩并侦听WM_SETFOCUS消息.

根据您是将其设置为全局挂钩还是应用程序本地,您可以在系统上的所有窗口中跟踪焦点,或仅跟踪流程所拥有的窗口.


olo*_*rin 6

使用 .Net Framework 3.5 有一种简单的方法:库UI 自动化提供了一个事件焦点更改,每次焦点更改为新控件时都会触发该事件。

MSDN 上的页面

样本:

public void SubscribeToFocusChange()
{
    AutomationFocusChangedEventHandler focusHandler 
       = new AutomationFocusChangedEventHandler(OnFocusChanged);
    Automation.AddAutomationFocusChangedEventHandler(focusHandler);
}

private void OnFocusChanged(object sender, AutomationFocusChangedEventArgs e)
{
    AutomationElement focusedElement = sender as AutomationElement;
    //...
}
Run Code Online (Sandbox Code Playgroud)

这个 api 实际上在幕后使用 windows hook 来做到这一点。但是,您必须使用 .Net 框架...


roo*_*roo 4

Win32 GetForegroundWindow怎么样?