In Windows, what is the difference between foreground and active window? To be specific, under what circumstances can a foreground window not be an active window? If the 2 terms are referring to the same concept why there're 2 terms.
The msdn documentation here mentions "clicking a window, or by using the ALT+TAB or ALT+ESC key combination" makes a window active as well as foreground. There is nothing explicitly about the difference between the 2 terms.Check MSDN.
The active window (the result of GetActiveWindow()) is the window attached to the calling thread that gets input. The foreground window (the result of of GetForegroundWindow()) is the window that's currently getting input regardless of its relationship to the calling thread. The active window is essentially localized to your application; the foreground window is global to the system.
For example, if a window belonging to another process is the foreground, calling GetActiveWindow() from within your own process will return NULL.
I believe that it's true that being the foreground window implies being the active window, but the converse is not true. Also note that in modern Windows, applications generally cannot use SetForegroundWindow() to steal focus from another process (unless that process has explicitly given permission via AllowSetForegroundWindow).
I find the description in MSDN a bit confusing as well but here is my revised take:
First a foreground and background window have nothing to do with active windows, it has to do with threading, see below. So it is technically possible to have background window as an active window however it is confusing and the system doesn't do this for you, instead your app needs to call e.g. SetWindowPos to make the background window active.
The system can only have one active top-level window at a time, the system will activate the top-level window if you are working on a child window. All input is then directed to the active window and then normally passed to the child window.
/----------------------\
| |
| FOREGROUND WINDOW |--\
| | |
\----------------------/ |
| BACKGROUND WINDOW |
\-----------------------/
/----------------------\
| |
| ACTIVE WINDOW |--\
| | |
\----------------------/ |
| BACKGROUND WINDOW |
\-----------------------/
From MSDN
Active Window
An active window is the top-level window of the application with which the user is currently working. To allow the user to easily identify the active window, the system places it at the top of the z-order and changes the color of its title bar and border to the system-defined active window colors. Only a top-level window can be an active window. When the user is working with a child window, the system activates the top-level parent window associated with the child window.
Foreground/Background
Each process can have multiple threads of execution, and each thread can create windows. The thread that created the window with which the user is currently working is called the foreground thread, and the window is called the foreground window. All other threads are background threads, and the windows created by background threads are called background windows.
Related
I have a floating window that is owned by my app's main frame window. Now, I have created a new frame window and I want to change the owner of the floating window to the new frame window I created. But, I have not been able to find a way to do so.
Essentially, as a user activates either of my frame windows, I want to make the newly activated frame the owner of the floating window.
I tried SetParent hoping if I didn't change the style of the floating window from WS_POPUP to WS_CHILD, that would be a trick that would work but the floating window just fails to display after doing that. And, it is actually becomes a child window in that it shows up when enumerating the child windows of the frame I passed to SetParent.
Is it possible to change the owner of a window after calling CreateEx where I pass in the initial owner?
I have two windows in my application (document based), a main and secondary window. I want to keep the secondary window behind the main window unless the user clicks on it or the main window decides to show it (via a user pressed button).
The issue is that the secondary window has a modal sheet which makes it come to the foreground. I want to stop it from doing that.
Current solution:
Before the sheet appears I increase the main window's level by 1
After the sheet is done I decrease the main window's level by 1
Problems:
My timing of knowing when these sheets occur is bad and unreliable
The window flickers a bit
Notes:
I have tried making the secondary window a child window of the main one, however this links them too strongly, where dragging one drags the other and I do want the secondary window to surface when the user clicks on it.
I have seen several tools adding a custom button and/or drawing on the title bar of all windows of all applications in Windows. How is that done?
Extra points for an example in Delphi.
EDIT:
I found something for dotNET that does this:
http://www.thecodeking.co.uk/2007/09/adding-caption-buttons-to-non-client.html#.VdmioEDenqQ
How I see this job:
First of all we should be able to paint this button on the our own window caption. This procedure will be used later
This part of the program enumerates the active and visible windows
This part of the program using injection attach our dll to enumerated windows
From injected dll we can draw the button on the window caption
Inside this dll we should process the click on the button
We should have mechanism to send result to our main program
I haven't done this, so the following is what I would investigate if I were to try:
For each application / each top-level window:
Create a floating window and position it over the title bar wherever you want it to sit. Set up the parent / child relationship, but this window is part of your own process. (There are occasionally problems parenting a window from one process to one from another process, but try. I'd avoid injecting into other processes if possible.)
You can investigate the window flags to see if the window has a title bar (ie if you should add a button) via GetWindowLong with GWL_STYLE looking for WS_CAPTION. The same call will also let you see the type of caption / frame, which you can combine with GetSystemMetrics with, eg, SM_CYDLGFRAME to figure out the right size for your button on this specific window's title bar.
This window is now your button: paint, handle clicks etc as appropriate.
Make it a non-focusable window so that clicks to it don't take focus away from the window is is on the title bar of. You don't want clicking it to make the title bar change colour, for example. Do this by setting the WS_EX_NOACTIVATE window flag, something like: SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) orWS_EX_NOACTIVATE).
The main problem is to keep it positioned correctly when the window moves, is resized, etc. To do this, install a hook for the system move events. You can also hook minimize and restore via EVENT_SYSTEM_MINIMIZESTART and EVENT_SYSTEM_MINIMIZEEND. This will allow you to keep track of all windows moving around onscreen, such that you can adjust the button-window position if necessary.
That gives you a window which you can paint as a button (and respond to clicks etc), that visually is "attached" to other windows so it stays in the same place as the user drags the title bar, minimizes or maximises the app, etc, and that is in your own process without cross-process problems.
My application window does not cover the task bar. When I launch the application, it works fine. After launching the application, when I change the position of the task bar, the application does not change accordingly. Is there a window message which notifies the change in task bar position so I can update my window?
When the taskbar is moved/resized, a WM_SETTINGCHANGE message with its wParam parameter set to SPI_SETWORKAREA is sent to all top-level windows. You can then call SystemParametersInfo() with its uiAction parameter set to SPI_GETWORKAREA to retrieve the new dimensions of the work area (the area not covered by the taskbar or toolbars) of the primary monitor, then update your window to stay within that area as needed. If you need to support work areas across multiple monitors, use GetMonitorInfo() instead of SystemParametersInfo().
Working with a double-buffered window, I have a problem that when I make my parent window fullscreen (just covering the whole screen using the method in this answer, or using ChangeDisplaySettings with CDS_FULLSCREEN both show the problem), any child windows it has are not drawn/visible. However, this only happens if the window has focus / is the active window. I have been banging my head against this for a very long time (2+ years) and have finally started caring enough to try and figure this out.
Specific setup:
This is an OpenGL window, double-buffered
Parent is drawn before child is drawn and both are receiving WM_PAINT messages
Drawing is done outside WM_PAINT BeginPaint/EndPaint pairs by simply making the Device Context of the window to draw current. However, an older version of the code did confine all drawing to inside Begin-/EndPaint, and I had the same problem.
Parent window styles when fullscreen, as given by WinSpy++ (consistent with what i request in code): WS_OVERLAPPEDWINDOW, WS_VISIBLE, WSCLIPSIBLINGS, WS_CLIPCHILDREN (though caption removed by this method and is indeed not present, seems winspy doesn't show this), no active WS_EX styles
Child window: WS_CHILD, WS_VISIBLE, WSCLIPSIBLINGS, WS_CLIPCHILDREN, no WS_EX
Code handling WM_SETFOCUS: DefWindowProc() for return value of my window proc, SetActiveWindow(), UpdateWindow()
Code handling WM_KILLFOCUS: only DefWindowProc() for return value of my window proc
WM_ACTIVATE is passed to DefWindowProc().
I have seen this problem on at least windows 7 and 8, with various versions of MSVC and the windows SDK.
Is there any other info i can add?
Lastly, this concerns the code of FreeGLUT, try the resizer demo in svn trunk should you want to see the problem in action. After starting the demo, press c to open a child window, and then f to make things fullscreen.