我有一个包含多个自定义控件的程序。这些自定义控件之一是文本输入控件。由于窗口在您单击时不会自动接收键盘焦点,因此我在我的程序中创建了一个鼠标钩子,当用户在该窗口中单击时,该钩子会在该窗口上调用 SetFocus()。但是,有一个问题。
如果单击我的程序窗口(或该窗口中的任何控件)时另一个程序具有焦点,则 SetFocus() 失败。然后我必须再次单击它才能成功。这是代码:
LRESULT CALLBACK kbfProc(int nCode, WPARAM wParam, LPARAM lParam) // Keyboard focus switching procedure
{
switch(nCode)
{
case HC_ACTION:
{
if(wParam == WM_LBUTTONDOWN || wParam == WM_NCLBUTTONDOWN)
{
MOUSEHOOKSTRUCT * mhs = (MOUSEHOOKSTRUCT*) lParam;
if(SetFocus(mhs->hwnd) == NULL)
{
printf("SetFocus(Hwnd = %.8x) failed. Error code: %lu\n", mhs->hwnd, GetLastError());
} else {
printf("SetFocus(Hwnd = %.8x) returned success.\n", mhs->hwnd);
}
}
}
break;
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)
这些 printf 调用的输出是这样的:
SetFocus(Hwnd = 00410c06) failed. Error code: 87
SetFocus(Hwnd = 00410c06) returned success.
SetFocus(Hwnd = 01740fc8) failed. Error code: 87
SetFocus(Hwnd = 01740fc8) returned success.
Run Code Online (Sandbox Code Playgroud)
错误代码 87 是 ERROR_INVALID_PARAMETER,但我显然将有效的窗口句柄传递给该函数,那么为什么它会失败?
每当您调用 SetFocus 时,窗口必须附加到调用线程的消息队列,否则 SetFocus 将返回无效。要解决此问题,SetForegroundWindow请先在鼠标移动到窗口上方时使用,然后再调用SetFocus.