Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

607 lines
19 KiB

/****************************** Module Header ******************************\
* Module Name: showwin.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Contains the xxxShowWindow API and related functions.
*
* History:
* 10-20-90 darrinm Created.
* 02-04-91 IanJa Window handle revalidation added
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* _ShowWindowAsync
*
* This queues a show window event in another thread's queue. Used mainly from
* within taskmgr, so that taskmgr doesn't hang waiting on hung apps.
*
* 04-23-93 ScottLu Created.
\***************************************************************************/
BOOL _ShowWindowAsync(PWND pwnd, int cmdShow, UINT uWPFlags)
{
return PostEventMessage(
GETPTI(pwnd),
GETPTI(pwnd)->pq,
QEVENT_SHOWWINDOW,
NULL,
uWPFlags,
(WPARAM)HWq(pwnd),
cmdShow | TEST_PUDF(PUDF_ANIMATE));
}
/***************************************************************************\
* xxxShowWindow (API)
*
* This function changes the "state" of a window based upon the cmdShow
* parameter. The action taken is:
*
* SW_HIDE 0 Hide the window and pass avtivation to someone else
*
* SW_SHOWNORMAL 1 Show a window in its most recent "normal"
* SW_RESTORE size and position. This will "restore" a iconic
* or zoomed window. This is compatible with 1.03
* SHOW_OPENWINDOW. This will also activate the window.
*
* SW_SHOWMINIMIZED 2 Show the window as iconic and make it active.
*
* SW_SHOWMAXIMIZED 3 Show the window as maximized and make it active.
*
* SW_SHOWNOACTIVATE 4 Same as SW_SHOWNORMAL except that it doesn't change
* the activation (currently active window stays active).
*
* All the above are compatible with 1.03 ShowWindow parameters. Now here are
* the new ones:
*
* SW_SHOW 5 Show the window in its current state (iconic, etc.)
* That is, if the window is iconic when hidden, it will
* still be iconic. This will activate the window.
* (This is one we don't have today)
*
* SW_MINIMIZE 6 minimize the window, activate the toplevel open window
*
* SW_SHOWMINNOACTIVE 7 show the icon, don't change activation.
*
* SW_SHOWNA 8 Same as SW_SHOW except that it doesn't change
* the activation.
*
* SW_SHOWDEFAULT 10 Use value obtained from STARTUPINFO.
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
* 04-16-91 JimA Added SW_SHOWDEFAULT support.
\***************************************************************************/
/*
* cmdShow now has fAnimate as the lower bit in the upper word. This puts it in the
* MINMAX_ANIMATE position for calling MinMaximize.
*/
BOOL xxxShowWindow(
PWND pwnd,
DWORD cmdShowAnimate)
{
BOOL fVisOld, fVisNew;
UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
PTHREADINFO pti;
BOOL bFirstMain = FALSE;
int cmdShow = LOWORD(cmdShowAnimate);
CheckLock(pwnd);
fVisOld = TestWF(pwnd, WFVISIBLE);
pti = PtiCurrent();
/*
* See if this is the first "main" top level
* window being created by this application - if show, assume it
* is showing with the SW_SHOWDEFAULT command.
*
* Checks for:
* - cmdShow is a "default" show command
* - we haven't done startupinfo yet (we only use it once)
* - this is not a child (it is a top level window)
* - this has a titlebar (indicator of the main window)
* - it isn't owned (indicator of the main window)
*/
if ((pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) &&
!TestwndChild(pwnd) &&
(TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) &&
(pwnd->spwndOwner == NULL)) {
bFirstMain = TRUE;
switch (cmdShow) {
case SW_SHOWNORMAL:
case SW_SHOW:
/*
* Then assume default!
*/
cmdShow = SW_SHOWDEFAULT;
break;
}
}
/*
* If this application specified SW_SHOWDEFAULT, then we get the
* real SW_* command from the application's STARTUPINFO structure
* (STARTUPINFO is passed to CreateProcess() when this application
* was launched).
*/
if (cmdShow == SW_SHOWDEFAULT) {
/*
* Call the client to get the SW_* command from the STARTUPINFO
* for this process.
*/
if (pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) {
bFirstMain = TRUE;
cmdShow = pti->ppi->usi.wShowWindow;
/*
* The following code was removed in 3.51
*
* switch (cmdShow) {
* case SW_SHOWMINIMIZED:
* case SW_MINIMIZE:
*
* *
* * If the default show was "minimized", then make sure it doesn't
* * become active. Minimized is effectively "background".
* *
* cmdShow = SW_SHOWMINNOACTIVE;
* break;
* }
*
*/
}
}
/*
* This is in case someone said SW_SHOWDEFAULT but has no startupinfo.
* Or in case cmdShow inside of STARTUPINFO is SW_SHOWDEFAULT.
*/
if (cmdShow == SW_SHOWDEFAULT)
cmdShow = SW_SHOWNORMAL;
/*
* Turn off startup info. We turn this off after the first call to
* ShowWindow. If we don't apps can be started by progman with
* the start info being minimized and then be restored and then
* call ShowWindow(SW_SHOW) and the app would minimize again.
* Notepad had that problem 2985.
*/
if (bFirstMain) {
pti->ppi->usi.dwFlags &=
~(STARTF_USESHOWWINDOW | STARTF_USESIZE | STARTF_USEPOSITION);
}
/*
* Take care of all the OLD show commands with columns & iconslot.
*/
if (cmdShow & 0xFF00) {
if ((cmdShow & 0xFF80) == (int)0xFF80)
cmdShow = SW_SHOWMINNOACTIVE;
else
cmdShow = SW_SHOW;
}
/*
* Change to new fullscreen if needed and in same desktop
*/
if ((GetFullScreen(pwnd) != WINDOWED)
&& (pwnd->head.rpdesk == grpdeskRitInput)) {
if ((cmdShow == SW_SHOWNORMAL) ||
(cmdShow == SW_RESTORE) ||
(cmdShow == SW_MAXIMIZE) ||
(cmdShow == SW_SHOWMAXIMIZED)) {
cmdShow = SW_SHOWMINIMIZED;
if (GetFullScreen(pwnd) == FULLSCREENMIN) {
SetFullScreen(pwnd, FULLSCREEN);
}
if (gpqForeground != NULL &&
gpqForeground->spwndActive == pwnd) {
xxxMakeWindowForegroundWithState(NULL, 0);
}
}
}
switch (cmdShow) {
case SW_SHOWNOACTIVATE:
case SW_SHOWNORMAL:
case SW_RESTORE:
/*
* If min/max, let xxxMinMaximize() do all the work.
*/
if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) {
xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
return fVisOld;
} else {
/*
* Ignore if the window is already visible.
*/
if (fVisOld) {
return fVisOld;
}
swpFlags |= SWP_SHOWWINDOW;
if ( cmdShow == SW_SHOWNOACTIVATE) {
swpFlags |= SWP_NOZORDER;
#ifdef NEVER
/*
* This is what win3.1 does. On NT, since each "queue" has
* its own active window, there is often no active window.
* In this case, win3.1 turns a SHOWNOACTIVATE into a "SHOW
* with activate". Since win3.1 almost always has an active
* window, this almost never happens. So on NT, we're not
* going to do this check - that way we'll be more compatible
* with win3.1 because we'll usally not activate (like win3.1).
* With this check, this causes FoxPro 2.5 for Windows to not
* properly activate its command window when first coming up.
*/
if (pti->pq->spwndActive != NULL)
swpFlags |= SWP_NOACTIVATE;
#else
swpFlags |= SWP_NOACTIVATE;
#endif
}
}
break;
case SW_FORCEMINIMIZE:
xxxMinimizeHungWindow(pwnd);
return fVisOld;
case SW_SHOWMINNOACTIVE:
case SW_SHOWMINIMIZED:
case SW_SHOWMAXIMIZED:
case SW_MINIMIZE:
xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
return fVisOld;
case SW_SHOWNA:
swpFlags |= SWP_SHOWWINDOW | SWP_NOACTIVATE;
/*
* LATER removed this to be compatible with SHOWNOACTIVATE
* if (pti->pq->spwndActive != NULL)
* swpFlags |= SWP_NOACTIVATE;
*/
break;
case SW_SHOW:
/*
* Don't bother if it is already visible.
*/
if (fVisOld)
return fVisOld;
swpFlags |= SWP_SHOWWINDOW;
UserAssert(cmdShow != SW_SHOWNOACTIVATE);
break;
case SW_HIDE:
/*
* Don't bother if it is already hidden.
*/
if (!fVisOld)
return fVisOld;
swpFlags |= SWP_HIDEWINDOW;
if (pwnd != pti->pq->spwndActive)
swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
break;
default:
RIPERR0(ERROR_INVALID_SHOWWIN_COMMAND, RIP_VERBOSE, "");
return fVisOld;
}
/*
* If we're changing from visible to hidden or vise-versa, send
* WM_SHOWWINDOW.
*/
fVisNew = !(cmdShow == SW_HIDE);
if (fVisNew != fVisOld) {
xxxSendMessage(pwnd, WM_SHOWWINDOW, fVisNew, 0L);
if (!TestWF(pwnd, WFWIN31COMPAT)) {
xxxSendMessage(pwnd, WM_SETVISIBLE, fVisNew, 0L);
}
}
if (!TestwndChild(pwnd)) {
if (TestCF(pwnd, CFSAVEBITS)) {
/*
* Activate to prevent discarding saved bits???
*/
if (cmdShow == SW_SHOW || cmdShow == SW_SHOWNORMAL) {
xxxActivateWindow(pwnd, AW_USE);
swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
}
}
} else {
/*
* Children can't get activation...
*/
swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
}
/*
* If our parent is hidden, don't bother to call xxxSetWindowPos.
*/
if (_FChildVisible(pwnd)) {
xxxSetWindowPos(pwnd, (PWND)NULL, 0, 0, 0, 0, swpFlags);
} else {
if (cmdShow == SW_HIDE) {
SetVisible(pwnd, SV_UNSET);
ClrWF(pwnd, WEFGHOSTMAKEVISIBLE);
}
else {
SetVisible(pwnd, SV_SET);
SetWF(pwnd, WEFGHOSTMAKEVISIBLE);
}
}
/*
* Send size and move messages AFTER repainting
*/
if (TestWF(pwnd, WFSENDSIZEMOVE)) {
ClrWF(pwnd, WFSENDSIZEMOVE);
if (TestWF(pwnd, WFMINIMIZED)) {
xxxSendSizeMessage(pwnd, SIZE_MINIMIZED);
} else if (TestWF(pwnd, WFMAXIMIZED)) {
xxxSendSizeMessage(pwnd, SIZE_MAXIMIZED);
} else {
xxxSendSizeMessage(pwnd, SIZE_RESTORED);
}
xxxSendMessage(pwnd, WM_MOVE, 0,
(pwnd->spwndParent == PWNDDESKTOP(pwnd)) ?
MAKELONG(pwnd->rcClient.left, pwnd->rcClient.top) :
MAKELONG(
pwnd->rcClient.left - pwnd->spwndParent->rcClient.left,
pwnd->rcClient.top - pwnd->spwndParent->rcClient. top));
}
/*
* If hiding and is active-foreground window, activate someone else.
* If hiding a active window make someone active.
*/
if (cmdShow == SW_HIDE) {
if ((pwnd == pti->pq->spwndActive) && (pti->pq == gpqForeground)) {
xxxActivateWindow(pwnd, AW_SKIP);
} else {
xxxCheckFocus(pwnd);
}
}
return fVisOld;
}
/***************************************************************************\
* xxxShowOwnedWindows
*
* xxxShowOwnedWindows is used to hide or show associated popups for the
* following reasons:
*
* 1. Window going iconic
* 2. Popup window being hidden
* 3. Iconic window being opened
* 4. Popup window being shown
* 5. Window being zoomed or unzoomed
*
* For cases 1 and 2, all popups associated with that window are hidden,
* and the WFHIDDENPOPUP bit is set. This bit is used to differentiate
* between windows hidded by xxxShowOwnedWindows and those hidden by the
* application.
*
* For cases 3 and 4, all popups associated with that window that have the
* WFHIDDENPOPUP bit set are shown.
*
* For case 5, all popups associated with any window BUT the supplied
* window are hidden or shown. In this case as well, the SW_OTHERZOOM
* or SW_OTHERUNZOOM message is send to all tiled windows to notify them
* that they are being covered or uncovered by the zoomed window.
*
* In all cases, the WM_SHOWWINDOW message is sent to the window to hide or
* show it.
*
* This routine works by simply enumerating all popup windows checking to see
* if the owner of the popup matches the pwndOwner parameter, and taking the
* appropriate action.
*
* We will eventually want 3 separate hide bits: one each for other zoom/unzoom,
* owner iconic/open, owner hide/show. Right now, there is only one bit, so
* we show windows sometimes when we shouldn't
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
\***************************************************************************/
void xxxShowOwnedWindows(
PWND pwndOwner,
UINT cmdShow,
HRGN hrgnHung)
{
BOOL fShow;
int cmdZoom;
HWND *phwnd;
PBWL pbwl;
PWND pwnd, pwndTopOwner;
TL tlpwnd;
CheckLock(pwndOwner);
/*
* Not interested in child windows
*/
if (TestwndChild(pwndOwner))
return;
if ((pbwl = BuildHwndList(PWNDDESKTOP(pwndOwner)->spwndChild, BWL_ENUMLIST, NULL)) == NULL)
return;
/*
* NOTE: The following code assumes the values of SW_* are 1, 2, 3, and 4
*/
fShow = (cmdShow >= SW_PARENTOPENING);
cmdZoom = 0;
if (cmdShow == SW_OTHERZOOM)
cmdZoom = SIZEZOOMHIDE;
if (cmdShow == SW_OTHERUNZOOM)
cmdZoom = SIZEZOOMSHOW;
/*
* If zoom/unzoom, then open/close all popups owned by all other
* windows. Otherwise, open/close popups owned by pwndOwner.
*/
for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
/*
* Lock the window before we play with it.
* If the window handle is invalid, skip it
*/
if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
continue;
/*
* Kanji windows can't be owned, so skip it.
*/
if (TestCF(pwnd, CFKANJIWINDOW))
continue;
/*
* If same as window passed in, skip it.
*/
if (pwnd == pwndOwner)
continue;
/*
* Find ultimate owner of popup, but only go up as far as pwndOwner.
*/
if ((pwndTopOwner = pwnd->spwndOwner) != NULL) {
/*
* The TestwndHI is needed since if it has an icon, pwndOwner
* is invalid.
*/
while (!TestwndHI(pwndTopOwner) && pwndTopOwner != pwndOwner &&
pwndTopOwner->spwndOwner != NULL)
pwndTopOwner = pwndTopOwner->spwndOwner;
}
/*
* Zoom/Unzoom case.
*/
if (cmdZoom != 0) {
/*
* If no parent, or parents are the same, skip.
*/
if (pwndTopOwner == NULL || pwndTopOwner == pwndOwner)
continue;
/*
* If owner is iconic, then this window should stay hidden,
* UNLESS the minimized window is disabled, in which case we'd
* better show the window.
*/
if ( cmdShow == SW_OTHERUNZOOM
&& pwndTopOwner != NULL
&& TestWF(pwndTopOwner, WFMINIMIZED)
&& !TestWF(pwndTopOwner, WFDISABLED)
)
continue;
} else {
/*
* Hide/Iconize/Show/Open case.
*/
/*
* If parents aren't the same, skip.
*/
if (pwndTopOwner != pwndOwner)
continue;
}
/*
* Hide or show if:
* Showing & this is a hidden popup
* OR
* Hiding & this is a visible window
*/
if ((fShow && TestWF(pwnd, WFHIDDENPOPUP)) ||
(!fShow && TestWF(pwnd, WFVISIBLE))) {
/*
* For hung minimization, just set the HIDDENPOPUP bit, clear
* the visible bit and add the window rect to the region to
* be repainted.
*/
if (hrgnHung != NULL) {
HRGN hrgn = GreCreateRectRgnIndirect(&pwnd->rcWindow);
UnionRgn(hrgnHung, hrgnHung, hrgn);
GreDeleteObject(hrgn);
UserAssert(!fShow);
SetWF(pwnd, WFHIDDENPOPUP);
SetVisible(pwnd, SV_UNSET);
} else {
ThreadLockAlways(pwnd, &tlpwnd);
xxxSendMessage(pwnd, WM_SHOWWINDOW, fShow, (LONG)cmdShow);
ThreadUnlock(&tlpwnd);
}
}
}
/*
* Free the window list.
*/
FreeHwndList(pbwl);
}
/***************************************************************************\
* xxxShowOwnedPopups (API)
*
* This routine is accessable to the user. It will either show or
* hide all popup windows owned by the window handle specified. If
* fShow if TRUE, all hidden popups will be shown. If it is FALSE, all
* visible popups will be hidden.
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
\***************************************************************************/
BOOL xxxShowOwnedPopups(
PWND pwndOwner,
BOOL fShow)
{
CheckLock(pwndOwner);
xxxShowOwnedWindows(pwndOwner,
(UINT)(fShow ? SW_PARENTOPENING : SW_PARENTCLOSING), NULL);
return TRUE;
}