On which occasions exactly is WM_ACTIVATE sent?

I'm trying to debug a huge Win32 GUI application (I have full sources) divided into several processes. The problem is the following: in one process I have a dialog with a listbox, when I double-click an item in the listbox another process is started that creates its own window that is brought to front and covers the initial dialog. If I do some manipulations (that I can't fully explain yet since I don't fully understand them yet) something forces the initial dialog to start flashing in the taskbar.

I tried Microsoft Spy++ and see that whenever I do that manipulation WM_ACTIVATE is sent to the dialog, most of the times it has these parameters:

fActive: WA_INACTIVE fMinimized:False hwndPrevious:(null) 

and in those cases the dialog doesn't starts flashing. But once in a while the parameters are

fActive: WA_ACTIVE fMinimized:False hwndPrevious:(null) 

and that precisely corresponds to the dialog flashing.

MSDN says WM_ACTIVATE is sent with WA_ACTIVE when a window is activated by some method other than a mouse click (for example, by a call to the SetActiveWindow function or by use of the keyboard interface to select the window).

Now in the application code SetActiveWindow() is never called and I don't do anything with the keyboard that could switch windows.

What other reasons are possible for WM_ACTIVATE being sent with WA_ACTIVE?

2 Answers

Your problem is caused by SetForegroundWindow(). It has counter-measures in place that prevents a process from shoving a window into the face of the user while she's actively working in another app.

The SetForegroundWindow() is happening when the second process creates its window and implicitly tries to take foreground with it. (You said as much when you wrote "brought to the front".)

The first application should call AllowSetForegroundWindow() to say "it's okay, that window is allowed to take foreground activation from me."

Note that if you do this, then the user may run into this situation:

  • User clicks on the list box item.
  • The second process is slow to start up.
  • The user clicks on something else in the first application. (Lost patience.)
  • The second process steals foreground from the first application. (User is frustrated because he was in the middle of doing something else.)

That is the situation that is causing the blinking in your current code. The window manager detected that the user has given up waiting for the second process and started doing something else with the first process, so it blocks the second process when it eventually gets around to trying to steal foreground.

If you create a window with WS_VISIBLE style, the window will be activated on creation.

If you do a ShowWindow(SW_SHOW) it will activate the window (Use SW_SHOWNA instead)

If you do a SetWindowPos without the SWP_NOACTIVATE flag, the window will be activated.

Finally, if you create a window with a template (CDialog), the window is always activated.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like