WM_KILLFOCUS Not Getting Sent

Started by
10 comments, last by JonW 18 years, 4 months ago
Hi, I have some code like the following to create a top-level window: [In the window creation function] // Create the window, store in hWnd.... ShowWindow(hWnd, SW_SHOW); SetFocus(hWnd); [In the message handler] case WM_SETFOCUS: OutputDebugString("Got focus.\n"); break; case WM_KILLFOCUS: OutputDebugString("Lost focus.\n"); break; After the window is created, I get a WM_SETFOCUS message right away as I should. But then if I click on another application's window, such as Explorer, I don't receive the WM_KILLFOCUS message. The funny thing is, I can click on dozens of windows from other processes without receiving the message, and then when I click on my application's other top-level window I finally receive the WM_KILLFOCUS message. If I first click on the created window and then click on, say, Explorer, I will receive the WM_KILLFOCUS message as I should. I just won't receive it when the focus is set with the SetFocus call. I tried replacing it with SetActiveWindow and SetForegroundWindow, but the results are the same. Sorry if that sounds confusing... couldn't phrase it any more clearly. Thanks, Jon
Advertisement
I believe you need to handle WM_APPACTIVATE for the case where your entire process loses focus.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Can you state more specifically ?. If you're processing a dialog box's messages, WM_KILLFOCUS won't work as expected.
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
It's not a dialog. Here is the window class code:

WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(88, 87, 104));
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

And the window creation:

hWnd = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, "MyClass", NULL, WS_POPUP|WS_BORDER, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);

It would be ideally if I could know when just this window loses focus, such as to another window in the same process. Should I process both ACTIVATEAPP and KILLFOCUS?

Thanks,
Jon
You need WM_KILLFOCUS for when focus changes inside your process (e.g. to another window of your program) and WM_ACTIVATEAPP (not APPACTIVATE, sorry) for when focus changes between processes (e.g. to a window in another program). See MSDN on WM_ACTIVATEAPP for some extra details.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Even with WM_ACTIVATEAPP, it still does not work right.

Here's the code in my message handler (lets call this created window 'Window A'):

case WM_SETFOCUS:
OutputDebugString("Got focus.\n");
break;

case WM_KILLFOCUS:
OutputDebugString("Lost focus.\n");
break;

case WM_ACTIVATEAPP:
if ((BOOL)wParam)
OutputDebugString("Got app focus.\n");
else
OutputDebugString("Lost app focus.\n");
break;

And here's the output I get when Window A is initially opened:

Got app focus.
Got focus.

If I first click on another application's window, I don't receive either WM_ACTIVATEAPP or WM_KILLFOCUS.

If I click on Window A before clicking on another application's window, I get both outputs:

Lost app focus.
Lost focus.

And if I click on my other top level window (Window B), I get just this:

Lost focus.

So Window A does not receive WM_ACTIVATEAPP when I click on another app's window unless I initially click on Window A. However I can still receive WM_KILLFOCUS when I click on Window B.

I wish MS documented these messages better...
Quote:Original post by ApochPiQ
You need WM_KILLFOCUS for when focus changes inside your process (e.g. to another window of your program) and WM_ACTIVATEAPP (not APPACTIVATE, sorry) for when focus changes between processes (e.g. to a window in another program)...


Not really, WM_KILLFOCUS is sent right before the keyboard focus is transfered to another window (at the same process or another doesn't matter). Using WM_KILLFOCUS is sufficient in this case I think.

Did you try to create a toolbox window alone (a new app with only a toolbox) ?. I think the problem lay somewhere in your window procedure. CreateWindowEx () is fine, I suggest remove WS_POPUP however.
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
Depends on how the message pump and wndprocs are set up in the code; some points will always see WM_ACTIVATEAPP while some points may not catch WM_KILLFOCUS. The messages will always be sent, but whether or not your code sees them depends on where the code is located and how things are set up.

JonWoyame, can you provide some extra details on how the message handling is set up in your app?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

WM_ACTIVATEAPP works for me. BTW, MSDN says you're supposed to return zero upon receiving this message. This message is sent both when your app receives focus, and when it relinquises focus. If wparam is TRUE, you're receiving focus, otherwise, you're losing focus.

I find that WM_KILLFOCUS is only sent when an apps main window reliquenches control to one of it's (child) controls.
Quote:Original post by Anonymous Poster
WM_ACTIVATEAPP works for me. BTW, MSDN says you're supposed to return zero upon receiving this message. This message is sent both when your app receives focus, and when it relinquises focus. If wparam is TRUE, you're receiving focus, otherwise, you're losing focus.

I find that WM_KILLFOCUS is only sent when an apps main window reliquenches control to one of it's (child) controls.


I'm not sure about 'only', you may try creating a plain window which alerts user when WM_KILLFOCUS is sent. Switching between windows in Windows Explorer will also generate this message.
It is weird I've never had troubles with WM_KILLFOCUS, I believe the problem arose from your window procedure (seconded ApochPiQ).
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--

This topic is closed to new replies.

Advertisement