SetFocus() 因有效的窗口句柄而失败

Gog*_*a70 4 c++ winapi

我有一个包含多个自定义控件的程序。这些自定义控件之一是文本输入控件。由于窗口在您单击时不会自动接收键盘焦点,因此我在我的程序中创建了一个鼠标钩子,当用户在该窗口中单击时,该钩子会在该窗口上调用 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,但我显然将有效的窗口句柄传递给该函数,那么为什么它会失败?

Chi*_*ata 6

每当您调用 SetFocus 时,窗口必须附加到调用线程的消息队列,否则 SetFocus 将返回无效。要解决此问题,SetForegroundWindow请先在鼠标移动到窗口上方时使用,然后再调用SetFocus.