The meaning of SW_SHOW and SW_SHOWNORMAL - winapi

In my apps I use sometimes: ShowWindow(MyForm.Handle, SW_SHOW).
The documentation for ShowWindow function has a section for SW_SHOWNORMAL that says
"An application should specify this flag when displaying the window
for the first time".
Does it means that for every form (that I pass to ShowWindow) I need to keep a boolean var to see if the form was displayed or not and based on that I should use SW_SHOW or SW_SHOWNORMAL?
What is the deep meaning of SW_SHOWNORMAL?

The term normal is synonymous with restored. This terminology dates back to older versions of windows and nowadays all the MSDN documentation uses restored rather than normal or normalized.
So, SW_SHOWNORMAL sets the window state to restored and makes the window visible. On the other hand, SW_SHOW simply makes the window visible.
Back in the day, restored was called normalized, minimized was called iconic, and maximized was called full screen. If memory serves, that older terminology was still in use in Windows 3.1, but was changed with Windows 95 and NT.

SW_SHOW is often used in conjunction with SW_HIDE so if you were showing/hiding a window for some reason (e.g. based on a user action) you would use them in tandem. SW_SHOWNORMAL was originally used in the 'old' days when first showing a window.
SW_SHOWNORMAL is sometimes valuable if you want to make sure a window is not minimized (or maximized) at some particular point in the program (e.g. if the window might be minimized but you want to 'restore' it so the user can interact with it).

Related

Can I improve upon window redraw and if so how can I?

Some years ago (2008) I wrote an online Child Support Calculator using PHP/Javascript/Ajax/css Advanced Child Support Calculator - May help to explain what I am replicating.
Some time after (2009 I think) I started writing an equivalent for Windows and am now revisiting this. The fundamentals of this version are working.
However, I have an issue with the window noticeably flickering/changing when controls are dynamically added and the window is redrawn/rebuilt.
Note! This calculator is specific to Australia.
In short I'm looking for a way, if possible, to only refresh/re-display/redraw the window after all components have been added.
Basically, the windows controls need to be dynamically added/removed depending upon the scenario (number of adults and children involved).
Adding or removing a child or adult or performing the calculation, results in a complete rebuild of the window. That is, all existing controls are destroyed and then all valid controls are added (this could perhaps be minimised via complex logic).
The issue is that controls are removed but briefly reappear (in an ordered fashion) causing the display to flicker (for want of a better description).
The following screen shots demonstrate the complexity factor (such as a child has a drop down for each defined adult), but not the flicckering(sic).
Here's a screen shot of the Initial display (OK pretty ugly at present) :-
And then if an Adult is added (note that the child now has an extra dropdown for Adult 3, the new adult):-
And now, an Adult (as above) and a Child:-
Coding wise, there is a RebuildAll function. This has two main stages. (1) The removal of the controls. (2) The rebuild (recreation) of the appropriate of the controls (Create Window, SendMessage's and then ShowWindow)
At a minimum there are 61 controls. The number of controls is
23 + ((#children * 12) - 2) + (#children * (#Adults * 8 )) + ((#adults * 10) -4). It's likely suffice to say that the number of controls increases rapidly/exponentially.
I suspect that it might be possible to postpone the ShowWindow untill after all of the builds have been done. Is the solution, as simple (theoretically) as this, assuming that this is feasible or is there another way that would circumvent the need to change all the code to remove the 'ShowWindow' and add a ShowWindow at the end of the builds?
Note replacing the individual ShowWindow's with one significantly reduced the "flicker" but didn't eliminate it. (as per Update below).
As an endnote I'm pretty sure that something should be feasible as the
windows program I have to date is a very poor reflection of the speed
of the browser/javascript version, which basically does the same thing
on windows (albeit 64bit).
Update
I went through and commented out the ShowWindows in all the AddItem???? functions and added a ShowWindows to the function that calls all the functions. This has improved matters. However, the numerous DestroyWindow calls still causes flickering when removing all of the controls. So now I guess that I'm looking for something that can disable them apparently doing an equivalent of ShowWindow.
Update 2
I have found SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); (TRUE to turn drawing back on). However, this appears to supress the DestroyWindow in that the display aspect of the control remains (the controls themselves don't appear to respond though).
By a process of elimination I have cured the flicker with a combination of ShowWindow's and WM_SETREDRAW's at pertinent points.
To briefly re-describe the issue. When adding a child or adult, or performing a calculation. The entire display is rebuilt. The rebuild basically consists of 2 phases. First, destroying the existing control windows and then adding the new/replacement set of window's controls.
The resolution was to :-
Issue a ShowWindow(hwnd,SW_SHOW); (for the main/containing
window) after all the pre-existing windows control's had been
destroyed.
Issue a WM_SETREDRAW FALSE message as per SendMessage(hwnd,
WM_SETREDRAW, FALSE, 0); before rebuilding the windows controls.
Without any ShowWindow's being used.
Build the windows controls via the various functions.
Finally, when all the windows controls have been built, issue a
ShowWindow(hwnd,SW_SHOW); (for the main/containing window).
Rather than seeing the controls appear and then disappear, "the flickering". The window is blank for a while and then the controls are displayed all at once.
I'm still confused about what is actually going on though, due to:-
After some thought I decided to use a MessageBox after all the destroys. When the message was displayed the window was blank. However, when the button was clicked and processing resumed then, in situations when the number of controls was relatively high, controls would appear and then disappear in an orderly fashion, albeit it momentarily.
My guess, is that creating a control in an area where an existing
control had been, was causing that previous control to momentarily
display.

CPropertySheet app lauched with CreateProcess steals focus [duplicate]

I was investigating an issue related to losing focus and changing activation of windows. What I found was that if I create an invisible property sheet, the active/foreground window changes and so does the focus window. Here is some sample MFC code:
// ignore CAutoDeleter, just a template that calls "delete this " in PostNcDestroy()
CPropertySheet* pSheet = new CAutoDeleter<CPropertySheet>(_T("Test Sheet"));
CTestPage* pPage = new CAutoDeleter<CTestPage>();
pSheet->AddPage(pPage);
DWORD style = WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | DS_CONTEXTHELP;
// style |= WS_DISABLED; //does nothing to help
DWORD exStyle = 0;
//exStyle = WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE; // does nothing to help
pSheet->Create(AfxGetMainWnd(), style, exStyle); // adding
After the call to pSheet->Create(), the active/foreground/focus window has changed and the application window is on top. If I use Spy++ and look at the window that is created, it turns out that a property sheet is a DIALOG window class. I am assuming it has a different WNDPROC, of course. What is interesting, is if I create an invisible modeless dialog using, it does not exhibit the problem. If I create the invisible modeless dialog, the active/foreground/focus window remains the same.
I tried setting various flags as in the code snippet, but alas they did not have any discernible effect--I still had the flashing and activation non-sense.
I could get some improvement by setting and clearing a hook (WH_CBT) before and after pSheet->Create()--and then eating the activation messages. When I do that, I don't have the horrible flashing and my application window does not come to the top. However, the focus (and caret for windows that have carets) does go away from whichever window had it before the Create().
Does anyone know a way to keep the focus and activation unchanged when creating an invisible property sheet? (At some point, the property sheet may or may not be set visible. And, if the property sheet is invisible when being destroyed, it also causes the blinking and activation changes.)
I tried using the values returned in GetUIThreadInfo() to try and restore things after the call to Create(), but it causes some flashing as well.
I just want to know how to create an invisible Property Sheet which won't cause the active, foreground, and focus window to change.
Unfortunately the underlying API function PropertySheet calls SetForegroundWindow on the main property sheet dialog after creation. There's no easy way around this - your kludge with the WH_CBT hook is probably your best option.
Edit: As suggested by #stephen in the comments on this duplicate question, you may be able to prevent the activation/focus change using LockSetForegroundWindow.
I have been struggling with this same issue for weeks, with a similar project, where my main application launches a secondary EXE process to act as a server in an audio application (which needs to be a separate process to shield the application from plugin faults, and so it can be high priority for real-time audio processing).
My secondary EXE is a modeless CPropertySheet, for status and diagnostic display, but is intended to be launched hidden and in the background. However it was always stealing the activation from the main application on launch, regardless of what workarounds I tried (such as overriding OnWindowPosChanging).
I thought I was going to go mad, so I was very happy to find this question. The WH_CBT trick is useful, but I found while it prevented activation of the secondary EXE, it did not prevent deactivation of the main application.
But then I discovered an excellent solution, in the LockSetForegroundWindow API (available since Win2K) which I had never heard of before. Looks like it is intended for exactly this purpose, to disable the change of foreground activation and prevent peer processes from stealing it.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
It works very well to nullify the internal call to SetForegroundWindow that happens deep within the property sheet common control, and works equally well whether used in the main application before CreateProcess or in the secondary EXE. I chose the latter case, to wrap the property sheet creation:
LockSetForegroundWindow(LSFW_LOCK);
pSheet->Create(NULL, dwStyle, dwExStyle);
LockSetForegroundWindow(LSFW_UNLOCK);
This minimises the scope of the intervention and keeps the fix localised to the process that is the source of the problem. I hope this will save others from wasting as much time on this tedious issue as I did.

Creating invisible and modeless property sheet causes focus change?

I was investigating an issue related to losing focus and changing activation of windows. What I found was that if I create an invisible property sheet, the active/foreground window changes and so does the focus window. Here is some sample MFC code:
// ignore CAutoDeleter, just a template that calls "delete this " in PostNcDestroy()
CPropertySheet* pSheet = new CAutoDeleter<CPropertySheet>(_T("Test Sheet"));
CTestPage* pPage = new CAutoDeleter<CTestPage>();
pSheet->AddPage(pPage);
DWORD style = WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | DS_CONTEXTHELP;
// style |= WS_DISABLED; //does nothing to help
DWORD exStyle = 0;
//exStyle = WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE; // does nothing to help
pSheet->Create(AfxGetMainWnd(), style, exStyle); // adding
After the call to pSheet->Create(), the active/foreground/focus window has changed and the application window is on top. If I use Spy++ and look at the window that is created, it turns out that a property sheet is a DIALOG window class. I am assuming it has a different WNDPROC, of course. What is interesting, is if I create an invisible modeless dialog using, it does not exhibit the problem. If I create the invisible modeless dialog, the active/foreground/focus window remains the same.
I tried setting various flags as in the code snippet, but alas they did not have any discernible effect--I still had the flashing and activation non-sense.
I could get some improvement by setting and clearing a hook (WH_CBT) before and after pSheet->Create()--and then eating the activation messages. When I do that, I don't have the horrible flashing and my application window does not come to the top. However, the focus (and caret for windows that have carets) does go away from whichever window had it before the Create().
Does anyone know a way to keep the focus and activation unchanged when creating an invisible property sheet? (At some point, the property sheet may or may not be set visible. And, if the property sheet is invisible when being destroyed, it also causes the blinking and activation changes.)
I tried using the values returned in GetUIThreadInfo() to try and restore things after the call to Create(), but it causes some flashing as well.
I just want to know how to create an invisible Property Sheet which won't cause the active, foreground, and focus window to change.
Unfortunately the underlying API function PropertySheet calls SetForegroundWindow on the main property sheet dialog after creation. There's no easy way around this - your kludge with the WH_CBT hook is probably your best option.
Edit: As suggested by #stephen in the comments on this duplicate question, you may be able to prevent the activation/focus change using LockSetForegroundWindow.
I have been struggling with this same issue for weeks, with a similar project, where my main application launches a secondary EXE process to act as a server in an audio application (which needs to be a separate process to shield the application from plugin faults, and so it can be high priority for real-time audio processing).
My secondary EXE is a modeless CPropertySheet, for status and diagnostic display, but is intended to be launched hidden and in the background. However it was always stealing the activation from the main application on launch, regardless of what workarounds I tried (such as overriding OnWindowPosChanging).
I thought I was going to go mad, so I was very happy to find this question. The WH_CBT trick is useful, but I found while it prevented activation of the secondary EXE, it did not prevent deactivation of the main application.
But then I discovered an excellent solution, in the LockSetForegroundWindow API (available since Win2K) which I had never heard of before. Looks like it is intended for exactly this purpose, to disable the change of foreground activation and prevent peer processes from stealing it.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
It works very well to nullify the internal call to SetForegroundWindow that happens deep within the property sheet common control, and works equally well whether used in the main application before CreateProcess or in the secondary EXE. I chose the latter case, to wrap the property sheet creation:
LockSetForegroundWindow(LSFW_LOCK);
pSheet->Create(NULL, dwStyle, dwExStyle);
LockSetForegroundWindow(LSFW_UNLOCK);
This minimises the scope of the intervention and keeps the fix localised to the process that is the source of the problem. I hope this will save others from wasting as much time on this tedious issue as I did.

SwitchToThisWindow sends current window to the back

So yes, I find myself in the dubious position of implementing a SwitchToThisWindow call to force my window to the front. I agree, its not ideal, but its not always possible to argue against product "features" that others deem necessary.
Now, I consider SwitchToThisWindow to be a win over the AttachThreadInput hack to do a forced window switch as its less likely to deadlock, and should SwitchToThisWindow be removed, or cease to function I won't complain.
However, SwitchToThisWindow has the unfortunate side effect of pushing the current foreground window to the bottom of the z-order in addition to bringing the target window to the top when FALSE is passed for the fAltTab parameter, and not doing anything if TRUE is passed.
How can I avoid this 'push current active to z-bottom' behavior without resorting to AttachThreadInput?
Alternatively, MS can just remove AttachThreadInput as a viable workaround and I can just tell my manager that the impossible, is in fact, actually, impossible.
I don't know if this helps, but the only way i found out to bring my window to top reliably is to make the following 2 calls:
ShowWindow(myhwnd, SW_MINIMIZE);
ShowWindow(myhwnd, SW_RESTORE);
Obviously these calls only should be made, when your window currently is not the topmost one in order to avoid flickering. But this also should not have the side effect of bringing the current front window to the bottom of the z order.
When passing fAltTab=FALSE you are actually emulating Alt+Esc. So you could reverse this z-order change with SetWindowPos and its hWndInsertAfter after the SwitchToThisWindow call, but then you are back in ugly hacky-land IMHO.
The question is, do you really need keyboard focus?
Let me suggest another alternative:
If your window is minimized, restore it
Set your window to be topmost, when your window is activated remove the style again.
Call SetForegroundWindow to flash the taskbar button (Or FlashWindowEx)
This should avoid the scenario where a user is typing and ends up performing some action in your UI without even looking at the screen.
Edit:
HWND hwndFgnd=GetForegroundWindow();
SetWindowPos(hwnd,hwndFgnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
SetWindowPos(hwndFgnd,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
..will probably work if you don't want to set the topmost bit at any point (Even if your window is at the top of the z-order, you still can't legally get the focus with SetForegroundWindow)
This is a bad problem I faced too. See my solution here. It works both for Show() and ShowDialog().

Can a window be always on top of just one other window?

In Windows, is it possible to set window A such that it is always on top of window B, yet allow other windows to work as normal and appear over the top of both, when active.
In other words, I want a parent-child relationship between two windows. Can this be done without making window A a child of window B, MDI-style? Window B isn't mine (Internet Explorer), and screws my dialog A's graphics up when I try to achieve this with SetParent.
I thought I'd cracked it with this idea from an MSDN forum post, but alas windows A is still always on top of everything, not just window B.
// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
Is it possible?
Wouldn't creating an ownership relationship do the trick?
SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)
The windows can be in different processes and you can call this from any process. This will ensure that the child window is always above the owner window. This is different than SetParent which actually creates a Parent / Child relationship. Read through this article (its from 1993 but still mostly correct) to see the distinction between ownership and parenting.
When your window's Z-order (or size or position) is changing, it should receive a WM_WINDOWPOSCHANGING message. If you process that message, you have an opportunity to modify the final Z-order (or size or position) to which the window is moved.
To illustrate, in hWndA's window procedure:
case WM_WINDOWPOSCHANGING:
DefWindowProc(hWnd, msg, wParam, lParam);
WINDOWPOS *p = (WINDOWPOS*)lParam;
p->hwndInsertAfter = hWndB;
p->flags &= ~SWP_NOZORDER;
return 0;
should insert hWndA after hWndB in the Z-order any time hWndA's position changes.
Until Vista, one way to do it would have been to use SetWindowsHookEx, and hook the WH_CBT or WH_CALLWNDPROC hook, and then take appropriate action when you detect the Z order changing. However this doesn't work with Vista (as far as I can tell from googling).
The only other solution I can think of is to set up a timer to fire every few seconds, and then when you receive a WM_TIMER, you interrogate the system using GetNextWindow to find out which window is behind yours. If it's not IE, then call SetWindowPos to position your window above IE (I assume you have a HWND for the IE window you care about - remember there can be multiple IE windows).
This will cause problems if people try to bring your window to the front - it will flip back to being just above IE. In this case, in your code you could handle WM_ACTIVATE and try to change the Z-order of IE's window so it's below your window (call SetWindowPos to move IE's window so it's above the window that is currently below your window). This solution may be fraught with problems as Windows may try to prevent you messing with the windows of another process, for security reasons. On the other hand, the MSDN docs for SetWindowPos don't explicitly mention that you can't manipulate the windows of another process. There may be obscure limitations though.
Even with this timer hack, you're going to effectively have a busy-waiting loop in your app (with the frequent WM_TIMER messages) and this is generally a bad thing to do, especially for battery life of laptops etc. (because you prevent the CPU from entering a sleep state, and so on).
I'd say there's no good way of doing this, and anything you're likely to get working will be brittle and cause problems. I strongly recommend not trying to do it. Is it possible to make your program into some kind of plug-in or toolbar for IE instead?
NB Be particularly aware that SetWindowsHookEx imposes a performance penalty at a system-wide level if you go down this route.
Maurice's answer is the best out of what's here but is missing an important step. When you call show on your window that you want as the overlay, you need to call the show method that has the parameter. You'll need to define a class that implements the IWin32Window interface and just make a new instance of that. The only thing that interface cares about is the Handle so just set that to the handle of the IE window and it should work pretty well
If the parent-child relationship is made by yourself with the SetWindowPos() function, your desire can be implemented.
Can you access the Z-order of the windows?
I cannot recall the default z-order of windows, but I think it is 1. You might be able to set IE to a -1 and your app to 0.
Try this:
// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
The second window handle parameter specifies the next window down in the Z order.
Note this doesn't actually change the window parent-child relationships - but you can simulate it.

Resources