Win32: how does the OS decide to re-assign focus on window close? - windows

When a focused window is closed, Windows will typically set focus to a different window when possible. I'm trying to figure out what exactly causes this to happen, and in what scenarios does this not occur.
I'm noticing that when some windows are closed, they do not cause the OS to set focus to a new window (eg. Discord, Slack). Discord and Slack are both hidden instead of destroyed on close, but then there are also other windows that when hidden will still cause the OS to set focus to a different window. One such example is with a fresh WPF app and changing the window's Visibility to Collapsed - this causes the window to be hidden, not destroyed, and yet the OS reassigns focus to another window.
What causes some windows when hidden to reassign focus (eg. WPF collapse)? As opposed to applications like Discord/Slack, which are hidden, yet do not reassign OS focus.

It's a multi-step dance of message exchanges, and I no longer have all the details cached in my head. So, generally speaking ...
There's a distinction between activating a window and setting the focus to a window. Windows can get activated in various ways, including a mouse click (either in the client or non-client areas, a keyboard operation, a window being created by a process that currently has "the foreground love", etc.)
A window that's activated can (in effect) accept the focus, reject the focus, or direct the focus to another window (such as a child window like an edit control or button).
A window that doesn't make the effort to direct the focus explicitly when its activated will (likely) end up with the focus by default. That's mostly an artifact of how DefWindowProc handles the relevant messages. But if it's using the dialog manager, then the dialog manager will (if I recall correctly) set the focus to one of the child windows that has the WS_TABSTOP window style.
Imagine a simple text editor application that has a top-level window and one child window that fill the top-level window's client area and hosts the actual editor functionality. In normal behavior, the child window would have the focus whenever the application is in the foreground. But if the top-level window is activated (for something other than a mouse click in the child window's client area), and the top-level window fails to redirect the focus to its child, then it may appear as though nothing has the focus because the window that does have the focus doesn't respond to most kinds of keyboard input.
Key messages involved include: WM_ACTIVATEAPP, WM_NCACTIVATE, WM_ACTIVATE, WM_MOUSEACTIVATE, WM_SETFOCUS, and WM_KILLFOCUS.
Edited to emphasize
what causes the OS to re-assign focus from a window?
In most cases, the OS does not assign focus. It activates and deactivates windows, and the affected applications respond to those events by setting the focus. Applications have a lot of flexibility in how to respond. So if there's an anomaly in where the focus is, it may be more of a question about the behavior of individual applications than about Windows.
It's also possible for a window to have focus but for it to seem as if no window has focus. One case is where the top-level window has focus but doesn't react to the keyboard itself because focus is normally supposed to be assigned to one if its child windows. It's also possible for a hidden window (at least a hidden child window) to have focus if it's not disabled.
Win32's DefWindowProc and dialog-specific APIs, MFC, WPF, and other frameworks generally provide "standard" behavior for handling focus and activation in common cases. But there's a lot of nuance, and there are inherently some differences. For example, WPF applications (if I recall correctly) use windowless child controls, so the traditional behaviors have to be implemented by the framework.

Related

How to automatically restore focus to a launched application on Windows

I have developed a full-screen application that hooks into and launched by a 3rd party/client application. The problem is that the client application gets focus soon after it launches my application, with the result that although my application is full screen, and set to be on top, it does not receive keyboard input, as such the user has to click on it to bring it to focus, which makes for a poor user experience.
How can I restore focus to my application after the client acquires it?
If it matters, my application is written in C++ and has a QT UI.
Not quite the answer but the reason why my application does not have input focus. I'll let Charles Petzold explain (from Programming Windows 5ed, pg 213)
The Window that receives a particular keyboard event is the window that has input focus. The concept of input focus is closely related to the concept of the active window. The window with the input focus is either the active window or a descendant window of the active window -- that is , a child of the active window, or a child of a child of the active window, and so forth.
My Qt application is not spawned spawned by an active window and therefore does not have input focus. The solution therefore would be to parent my application to the active window. Unfortunately this is not straightforward in Qt, if at all possible.
Here is the Qt documentation:
http://doc.qt.io/qt-4.8/qwidget.html#activateWindow
http://doc.qt.io/qt-4.8/qwidget.html#raise
http://doc.qt.io/qt-4.8/qwidget.html#setFocus
Hope it helps when called after launch...

Win32 C++ - Do something when window is restored, which message?

So, I have a dialog based application using pure WinAPI. There is a main dialog, and then multiple other dialogs that are toolwindows. These toolwindows are meant to free-float around, the user can drag them, hide them, and show them, but they have no taskbar entry. This is what I intended, but the problem is, when I switch from the main window to a different application, then click on the taskbar entry for the main window, the main window will show up, but the toolwindows will not. They stay hidden behind the main window and sometimes windows of other applications, and you cannot use them until you move all of the top-most windows and hunt down the toolwindow.
So, what I'm trying to do to work around this is, when the user restores the window from being minimized, I want to enumerate through all of the tool windows and bring them to the front, maybe by calling SetActiveWindow().
But what message gets sent when the window is restored? I was thinking WM_SHOW, or WM_RESTORE, but they don't exist.
Another question, and if you answer this the first question is irrelevant because I will no longer need to use that workaround: Is there a better method of bringing all tool-windows to the front?
Give the tool windows the WS_POPUP style (and not WS_OVERLAPPED), and make the main window their parent (strictly it is their owner window). That way the tool windows will remain on top of the main window. This may (or may not) be what you want.
The naive answer to the question is to listen to WM_SIZE and respond to a wParam value of SIZE_RESTORED.
The other obvious possibility is to make all the tool windows be owned by the main window. So long as you are happy for the tool windows always to be on top of the main window, this will solve your problem. The owned windows will be hidden when the owner is minimized, and re-shown when the owner is restored.
Learn more about ownership in the MSDN topic on Window Features.

Is it possible to create a sub window which will not deactivate the parent?

Normally when creating a sub window (WS_POPUP), the child window will become activate and the parent will become deactivated. However, with menus, both remain active. At least I am assuming the menu is active, it at least has focus.
Example: Click on the file menu in notepad, the menu appears, yet the notepad window still looks active.
Is it possible to mirror this behavior with either a window style or responding to a particular message?
Thanks
Another example: Combo boxes seem to show a subwindow, yet do not deactivate the window. And you can click on that subwindow, while still maintaining an activate main window. Any ideas on how to grab the class /style of that window?
The list dropdown in a combobox is a bit of a hack, it is both a popup and a child window, I can't recommend that approach (Undocumented style combination, and IIRC, it is a bit buggy to do this with a "normal" floating window/toolbar)
This leaves you with two options:
WS_EX_NOACTIVATE (Main window will stay active, floating window is not active)
Handle activate messages (Both windows will look active)
I am surprised that creating a new popup window activates it. Normally you'd need to call SetActiveWindow. However check out WM_ACTIVATE and WM_NCACTIVATE on how to stop the window becoming deactivated.
A fact that a lot of people miss is that windows does not have a separate window manager component :- most of the window management duties are performed by each window - usually in DefWindowProc.
Most window positioning and activation / de-activation is done - ultimately - via a call to SetWindowPos - which always sends a WM_WINDOWPOSCHANGING message allowing the window to have a final say on what happens.
DefWindowProc also activate its own window in response to mouse clicks and so on.
The result of all this is, it is quite possible to create windows that never accept activation - it does require an extensive understanding of what messages and situations might have led to an activation.
Ultimately I can say that it is VERY handy to have a debugging setup configured for remote debugging - so that you can interact with your debugger without effecting the activation state of the system - and hence drop a breakpoint into the window in questions WM_ACTIVATE handler and simply debug any situation leading to an unwanted activation.
If You want to handle keyboard focus as well, it might be trickier - normally focus is given to an activated window - but again its usually the DefWindowProc responsible for assigning both. I just see it dangerous as having one window, still obviously activated, and another with focus. This will confuse any assistive software greatly.
I'd be tempted to perform a message loop level message hook - Similar to IsDialogMessage - to filter keystrokes intended for the popup window.
If you create your popup window with WS_EX_NOACTIVATE it will not be activated by user input (You could still activate it programatically) and therefore your main application window will still remain active.

How may a Window be "pinned" to the desktop surface?

This question is more academic than practical and doesn't involve any one specific language. For the sake of discussion, we'll use Win32 API.
What is the most appropriate way to create a window with the following behavior goals:
Z-Order is lower than every other window except the desktop surface.
Cannot be made to appear on a higher z-order than other windows through mouse or keyboard clicks.
Assumption may be made that the window is borderless.
There are two basic approaches here :-
make your window the 'child' of the desktop.
make your window simply refuse to accept focus or activation :-
The wonder of the windows window manager is that there isn't one. Rather, there is an appearance of a window manager as a result of the emergent behavior of all the windows in the system - namely how they react to messages - which in 99% of cases is handeld by DefWindowProc.
Which means that you can subvert a lot of normal window manager type behaviour by handling messages before DefWindowProc. If you create a window, and position it using the relevent flags at the bottom of the z-order with SetWindowPos, and then handle messages like WM_WINDOWPOSCHANGING, you can ensure that your window never receives activation or focus and always - even when other apps call SetWindowPos - always has the z-bottom flag set.
both approaches are problematic as its very difficult to find out what the desktop window is. GetDesktopWindow returns a handle to a window that is only ever visible if explorer crashes. The rest of the time, the visible desktop is a window created by explorer - ultimately a syslistview control. Spy++ + Findwindow will get you a handle to the window you want to be above.

Which are the differences between dialog|main/child/mdi windows?

I need to understand the differences between windows main/mdi/child/dialogs.... how win32 messages should be propagated... why some messages are present in one type and not other...
There is reference information available here on the MSDN website. If you want more of an introduction or tutorial, then Charles Petzold's book Programming Windows is excellent.
Main window
The application's top window. It is flagged as the process main window and this information can be readily accessed by calling processes with the appropriate permission.
MDI (Multiple document interface) window
This is, typically, in an application main window and it contains a set of MDI Children. This is mostly a window class integrated with Win32 API. I believe it's not treated differently by the operating system as any other window class. Those are becoming extinct in favor of multiple SDI windows (Word 2007).
Child
This is a child window of any other window. Its position, visibility and mostly everything is dependent on the parent window. The children send notifications to their parents. A notification is a specific kind of window message.
Dialog
Dialogs provides easy child creation and input handling based on what 95% of dialogs need. Dialog functions in the API let you create a window and its children using compiled templates in the PE file (.exe). The message handling is also slightly different since you are working mostly with notifications from children.
The main difference with dialogs is when you are using a modal one. The creation call will block until the user closes the dialog. This can make UI updating a little tricky in some situations.
Im not a windows developer, but heres what I understand:
main window - toplevel container which you can active/see in the taskbar.
dialog - little box locking (if modal) your window, not seeable in the taskbar. Mostly used to display message to the user.
mdi (Multiple Document Interface) - Not directly a window but more a simple container for storing child windows. Each child window can be maximized/minimized/closed inside this container, but you wont find any of these in the taskbar.
http://en.wikipedia.org/wiki/Multiple_document_interface

Resources