Two use-cases:
Enumerate windows and then get the process handle for each window
Enumerate processes and then get the main application window handle for each process
Enumerate windows and then get the process handle for each window
You need these APIs:
win32gui.EnumWindows() to enumerate all top-level windows (that is no child windows aka controls)
win32process.GetWindowThreadProcessId() to get process ID from window handle
win32api.OpenProcess() to get process handle from process ID
Enumerate processes and then get the main application window handle
for each process
You need these APIs:
win32process.EnumProcesses() to enumerate all processes
win32api.GetWindowLong() with argument GWL_STYLE to get window styles and GWL_EXSTYLE to get extended window styles
win32gui.GetParent() to determine unowned windows
By filtering the result of EnumWindows() using GetWindowThreadProcessId() you can get all windows that belong to a given process.
Determining the main window can be tricky as there is no single window style that would designate a window as the main window. After all, an application might have multiple main windows.
Best you could do is to use the same rules that the taskbar uses to determine application windows, because that's what the user perceives as main windows:
The Shell places a button on the taskbar whenever an application
creates an unowned window—that is, a window that does not have a
parent and that has the appropriate extended style bits.
To ensure that the window button is
placed on the taskbar, create an unowned window with the
WS_EX_APPWINDOW extended style. To prevent the window button from
being placed on the taskbar, create the unowned window with the
WS_EX_TOOLWINDOW extended style. As an alternative, you can create a
hidden window and make this hidden window the owner of your visible
window.
Use GetParent() and GetWindowLong() to determine the unowned windows that have the right window styles according to these rules.
Related
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.
My program opens multiple windows on taskbar (not MDI). I want to display a Jumplist that is specific for each Window. How is it done?
Windows uses the Application User Model ID to group taskbar buttons and jump lists. This lets you group multiple processes together, or in your case split multiple windows from the same process.
You can assign a different AppUserModelID to a window by using the SHGetPropertyStoreForWindow() function to obtain the window's IPropertyStore interface and then set its System.AppUserModel.ID property.
I've been researching popup menus (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms647626(v=vs.85).aspx) and a bit confused at what they are behind the scenes.
They act partially like windows, but look like controls. For instance, they pop up above other elements, steal focus, and can go outside their parent container which makes me think they are a type of window. But they pass back an HMENU handle instead of a window handle, and they have no title bar, nor handles, nor show up in the task bar.
If they are a type of control, how can they go outside their parent window?
If they are a type of window, can I use window-specific functions on them? or if they are a control in a new window, is there a way to get a win handle to that new window?
Can I get the location of the popup menu for another application?
Found the answer:
trying to get a handle to a context menu in c++
Looks like a menu is a type of window, that is a child of the desktop window. You can get its window handle with EnumChildWindows on the desktop WinHandle and look for the class name of #32768.
There's more about these reserved system windows here:
About Window Classes | System Classes
A popup menu is a menu, not a window.
A menu merely uses a window for display. A new window is created each time the menu is displayed, and is destroyed afterward. By contrast, the same HMENU can be used to display the menu many times.
I would like to host an application window from a process "A" into the main window of a process "B", just as if "A"'s window were a MDI child window. Is this possible in Windows? Or are there some tricks which would allow me to fake this?
By the way, I'd like to remove the title bar (or better yet, all the non-client stuff) of "A"'s window when it is embedded into "B"'s window. I suppose that this must be possible by tweaking the window styles or window classes, but I am by no means an expert in these Win32 intricacies.
It's possible to host the Window. Change A's parent HWND by calling the SetParent function against it. To change the window styles, you need to use the GetWindowLong/SetWindowLong pair to change the attributes that you want to muck with.
If this is a third-party application (ie, not yours), then you're probably in for a rough ride, particularly if the window does any theming or anything custom with its window (for example, changes to the drag area, etc).
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