主窗体打开一个子窗体,其上有一些按钮CONTROL。我需要捕获键盘事件,所以我将其中一个控件子类化。一切都很好,直到控制失去了焦点。
理想情况下,只要这个子窗体打开,我就想将焦点分配给此控件,从而捕获所有击键,无论用户点击的位置如何。
我怀疑超级类别可能是更好的方法,但我对它并不熟悉。
也许我应该做的是在主窗体上使用加速器?
增加: 我应该提一下,主窗体有一个大型的listview控件,它被子类化以恢复上/下箭头和鼠标滚轮等。
答案 0 :(得分:1)
传统的方法是安装一个键盘钩子(SetWindowsHookEx),但是你需要将它注入到每个应用程序中,并且它不能在32/64位边界上工作。
然而,您可以轻松地在计时器上使用GetKeyboardState轮询键盘,并检查您的f1-f12键是否已激活。计时器的速度可以达到100毫秒,几乎可以捕获所有内容,而几乎不使用任何资源。
答案 1 :(得分:0)
假设这是在Windows和Win32 API中,一个选项是在主GetMessage
,TranslateMessage
,DispatchMessage
循环中查找消息。您可以对此循环中的任何消息进行特殊处理,无论它针对哪个窗口。
您应该使用IsChild
来检查该消息是否适用于主窗口上的控件(而不是可能单独显示的某个对话框或消息框)。获得正确的逻辑也很繁琐。当您知道控件失去焦点时,最好只拦截拦截消息,而仅拦截您需要的确切消息。
多年前,我编写了一个库消息循环,内置了很多内容。我有一个简单的管理器类,它指向我自己的小窗口类的实例。循环知道对话框和普通窗口之间的区别,让每个窗口类都有机会监视其子信息,等等。你将无法直接运行它,并且约定有点奇怪,但你可能会觉得这很有用......
int c_Window_List::Message_Loop (void)
{
MSG msg;
bool l_Handled;
while (GetMessage (&msg, NULL, 0, 0))
{
l_Handled = false;
c_Windows::c_Cursor l_Cursor;
bool ok;
for (ok = l_Cursor.Find_First (g_Windows); ok; ok = l_Cursor.Step_Next ())
{
if (IsChild (l_Cursor.Key (), msg.hwnd))
{
if (l_Cursor.Data ().f_Accelerators != NULL)
{
l_Handled = TranslateAccelerator (l_Cursor.Key (), l_Cursor.Data ().f_Accelerators, &msg);
if (l_Handled) break;
}
if (l_Cursor.Data ().f_Manager != 0)
{
l_Handled = l_Cursor.Data ().f_Manager->Spy_Msg (l_Cursor.Key (), msg);
}
if (l_Handled) break;
if (l_Cursor.Data ().f_Is_Dialog)
{
l_Handled = IsDialogMessage (l_Cursor.Key (), &msg);
if (l_Handled) break;
}
}
}
if (!l_Handled)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
if (g_Windows.Size () == 0)
{
// When all windows have closed, exit
PostQuitMessage (0);
}
}
return msg.wParam;
}
f_
前缀表示字段 - 我稍后选择了m_
约定,但此代码在很长一段时间内未被重新访问。 f_Manager
特别指向我c_Window_Base
类的实例。 c_Cursor
类是一种迭代器,用于遍历存储在g_Windows
变量中的所有窗口(实际上是静态类成员而不是全局)。