I have a program with several custom controls. One of these custom controls is a text input control. Since a window does not automatically receive keyboard focus when you click on it, i’ve created a mouse hook in my program that calls SetFocus() on a window when the user clicks in that window. However, there is a problem.
If another program has focus when you click on my program’s window (or any of the controls in that window) SetFocus() fails. I then have to click again for it to succeed. Here’s the code:
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);
}
And the output of those printf calls is this:
SetFocus(Hwnd = 00410c06) failed. Error code: 87
SetFocus(Hwnd = 00410c06) returned success.
SetFocus(Hwnd = 01740fc8) failed. Error code: 87
SetFocus(Hwnd = 01740fc8) returned success.
Error code 87 is ERROR_INVALID_PARAMETER, but i’m obviously passing a valid window handle to the function, so why is it failing?
I’ve found a solution. After a lot of googling and trial & error I eventually came across this webpage (backup link). It goes over the behavior of window focus and activation in detail.
I ended up adding some code to the WM_ACTIVATE handler of my main window that searches for the child window that was clicked when the window is activated. Here’s all the code:
Here’s the hook procedure:
Here’s the code i put in the WM_ACTIVATE handler:
And here’s the FocusChildWindow() function: