MFC: Show or minimize (to hide) window on startup - winapi

In CWinApp::InitInstance() I have:
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(m_MinimizeOnStartup ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
m_pMainWnd->UpdateWindow();
But my ShowWindow call is not resulting in an OnSize() or OnShowWindow() callback? During the ProcessShellCommand() those are called a few times as the first OnShowWindow() restores the window size when last shutdown via SetWindowPlacement(). That all works good, restoring to last state, but ProcessShellCommand() afterwards calls ShowWindow with SW_SHOW which causes a my hidden when minimized window to show on the taskbar. Where is the proper place to either show the window or minimize it (to hide it). Basically what happens is the minimize comes in (on SetWindowPlacement(), window is hidden, MFC later calls SW_SHOW which makes it minimized on the taskbar instead of hidden, my forced ShowWindow() doesn't do anything.
TIA!!

There is no OnSize() nor OnShowWindow() callback on ShowWindow() when already in those states. Set m_nCmdShow=SW_HIDE in CAppWnd then at the end of the InitInstance() call the SetWindowPlacement()

Related

Stop being topmost window

My window should be on top of a specific "target" window that I don't have control over.
When the target window is activated, I call SetWindowPos with HWND_TOPMOST to place my window on top of it while the target can still be the active window.
When the target window is no longer the foreground window, I want my window to still be on top of the target window, but no longer topmost, so other windows are not covered by it.
Two ideas I had:
Call SetWindowPos with hWndInsertAfter to be the just activated window. This fails when the just activated window is topmost, because my window then does not lose the topmost status. Another issue with this: If the just activated window is the desktop, then my window is placed below the target window.
Call SetWindowPos with HWND_NOTOPMOST to lose the topmost status. However, this brings my window to the top of all non-topmost windows, so it covers the just activated window. To fix this I have to bring the just activated window on top again with another SetWindowPos with HWND_TOP. This feels like the wrong way to do it and may cause flicker.
Is it possible to have a window just stop being topmost and placing it below the current foreground window?
The only automatic method to make a window permanently on top of another one whether the target window is top-most or not is an owner/owned relationship. You could try using SetParent to create this relationship but note that Raymond Chen does say it's not recommended.
Assuming you're tracking window activations somehow, I think your SetWindowPos idea (the first one) is the way to do it, with the following modification:
When the target window is active, set your window to HWND_TOPMOST
When the target loses activation, insert your window after the target window's immediate predecessor in the z-order (i.e. effectively still on top of the target window, but not top-most)
Something like this psuedo-code:
if (foregroundwindow == targetwindow)
SetWindowPos(my_window, HWND_TOPMOST, ...);
else
{
HWND hwndPred = GetWindow(targetwindow, GW_HWNDPREV);
if (!hwndPred)
{
// no predecessor so my_window will still be on top, just not top-most any more
if (GetWindowLong(targetwindow, GWL_EXSTYLE) & WS_EX_TOPMOST)
hwndPred = HWND_NOTOPMOST;
}
SetWindowPos(my_window, hwndPred, ...);
}

Handle overlapping a window by the taskbar in WinAPI

I have a window which should pop up on top of any other windows (including the taskbar), stay on top while in focus, and become hidden completely when focus is lost.
To achieve this, I'm handling WM_ACTIVATEAPP with wParam being equal to FALSE. Nevertheless, sometimes the window falls in behind the taskbar, and since it's small, it's wholly overlapped by it. So, no way to reactivate it and take focus back to hide.
So, I'm looking for a way to handle that event, when the window Z-order changed relative to the taskbar one.
Regards,
UPDATE
I'm pointing to the fact, that this is not that type of questions, you know, how to stay on top forever. In fact, otherwise. It's about how to hide the window as soon as possible.
UPDATE 2
I have tried WM_WINDOWPOSCHANGING, but it never received, when I click on the taskbar and overlap my window.

ShowWindowAsync doesn't activate a hidden+minimized window?

A given external (not owned by the current process) window (hWnd) is first minimized, then hidden:
ShowWindowAsync(hWnd, SW_MINIMIZE);
// wait loop inserted here
ShowWindowAsync(hWnd, SW_HIDE);
The following call properly restores it to the un-minimized (restored) state:
ShowWindow(hWnd, SW_RESTORE);
However, this call does not:
ShowWindowAsync(hWnd, SW_RESTORE);
In the second instance with ShowWindowAsync(), the window is un-minimized and no longer hidden, but it is not activated (remains behind other existing windows). Conversely, the first ShowWindow() call correctly activates the window.
Is this expected behavior? How can I restore the window (to the foreground) without relying on ShowWindow(), which is synchronous (blocking)? (The wait loop in the example can have a timeout, while ShowWindow() does not allow specification of a timeout.)
(WinXP SP3)
ShowWindowAsync posts a show-window event to the message queue of the given window. In particular, the window is shown by its thread, rather than your thread. And the difference is that your thread is the foreground thread, and can therefore activate another window, which it can't do itself.
Here's the solution as used:
ShowWindowAsync(hWnd, SW_SHOW);
// wait loop inserted here
ShowWindowAsync(hWnd, SW_RESTORE);
This is essentially an inversion of the snippet used to hide the window:
ShowWindowAsync(hWnd, SW_MINIMIZE);
// wait loop inserted here
ShowWindowAsync(hWnd, SW_HIDE);

Problem when maximizing window in C++

My program needs to arbitrarily maximize any window on the current desktop. I achieve this by calling ShowWindow(hWnd, SW_MAXIMIZE), where hWnd is the HWND of the window I want to maximize. When that line of code executes, the window in question (here, Notepad) looks like this:
Everything seems fine, except for the fact that the window has not been positioned correctly, i.e. the window seems to be a few pixels to low, and the title bar does not look "squashed" like it should. Compared to how it should look when the maximize button is clicked, the problem is clearly visible:
Does anyone know why this behaviour occurs, and what I can do to fix it?
Telling the window to maximize itself might bypass some internal adjustments that the program makes when it maximizes via a system menu command. To emulate clicking on the maximize button, send it a SC_MAXIMIZE command:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
Antoher way to use SetWindowPos(); For example you got HWND handleWnd;
RECT rcWnd;
GetWindowRect(handleWnd,&rcWnd);
SetWindowPos(handleWnd,WHND_TOP,rcWnd.left,rcWnd.top,(rcWnd.right-rcWnd.left),(rcWnd.bottom-rcWnd.top),SWP_SHOWWINDOW);
So you got your previous position, place window on top of Z and show

CloseWindow() vs ShowWindow(hWnd, SW_MINIMIZE)

Does anyone know the difference between those two?
CloseWindow() calls ShowWindow() with SW_SHOWMINIMIZED if the window is not already minimized.
Like IsIconic() and IsZoomed(), CloseWindow() is one of the old school window manipulation functions.
From MSDN:
CloseWindow
Minimizes (but does not destroy) the specified window.
ShowWindow (SW_MINIMIZE)
Minimizes the specified window and activates the
next top-level window in the Z order.
My guess is CloseWindow doesn't activate next top-level window.

Resources