Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

minmax.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define CMS_ANIMATION   250
#define DX_GAP   (SYSMET(CXMINSPACING) - SYSMET(CXMINIMIZED))
#define DY_GAP   (SYSMET(CYMINSPACING) - SYSMET(CYMINIMIZED))

Functions

void xxxInitSendValidateMinMaxInfo (PWND pwnd, LPMINMAXINFO lpmmi)
VOID ParkIcon (PWND pwnd, PCHECKPOINT pcp)
ULONG_PTR SaveScreen (PWND pwnd, ULONG iMode, ULONG_PTR iSave, int x, int y, int cx, int cy)
VOID xxxAnimateCaption (PWND pwnd, HDC hdc, LPRECT lprcStart, LPRECT lprcEnd)
BOOL xxxDrawAnimatedRects (PWND pwndClip, int idAnimation, LPRECT lprcStart, LPRECT lprcEnd)
PWND CalcMinZOrder (PWND pwndMinimize)
BOOL xxxActivateOnMinimize (PWND pwnd)
PWND xxxMinMaximize (PWND pwnd, UINT cmd, DWORD dwFlags)
void xxxMinimizeHungWindow (PWND pwnd)


Define Documentation

#define CMS_ANIMATION   250
 

Definition at line 16 of file minmax.c.

Referenced by xxxAnimateCaption().

#define DX_GAP   (SYSMET(CXMINSPACING) - SYSMET(CXMINIMIZED))
 

Definition at line 17 of file minmax.c.

#define DY_GAP   (SYSMET(CYMINSPACING) - SYSMET(CYMINIMIZED))
 

Definition at line 18 of file minmax.c.


Function Documentation

PWND CalcMinZOrder PWND  pwndMinimize  ) 
 

Definition at line 1180 of file minmax.c.

References BYTE, NULL, tagWND::spwndNext, tagWND::spwndOwner, TestWF, WEFTOPMOST, and WFBOTTOMMOST.

Referenced by xxxMinMaximize().

01182 { 01183 BYTE bTopmost; 01184 PWND pwndAfter; 01185 PWND pwnd; 01186 01187 bTopmost = TestWF(pwndMinimize, WEFTOPMOST); 01188 pwndAfter = NULL; 01189 01190 for (pwnd = pwndMinimize->spwndNext; pwnd && !TestWF(pwnd, WFBOTTOMMOST); pwnd = pwnd->spwndNext) { 01191 01192 /* 01193 * If we've enumerated a window that isn't the same topmost-wise 01194 * as pwndMinimize, we've gone as far as we can. 01195 */ 01196 if (TestWF(pwnd, WEFTOPMOST) != bTopmost) 01197 break; 01198 01199 if (pwnd->spwndOwner == pwndMinimize->spwndOwner) 01200 pwndAfter = pwnd; 01201 } 01202 01203 return pwndAfter; 01204 }

VOID ParkIcon PWND  pwnd,
PCHECKPOINT  pcp
 

Definition at line 324 of file minmax.c.

References _GetProp(), BOOL, DX_GAP, DY_GAP, FALSE, tagCHECKPOINT::fDragged, tagCHECKPOINT::fMinInitialized, GetRealClientRect(), GetRect(), GRC_SCROLLS, GRECT_PARENTCOORDS, GRECT_WINDOW, IntersectRect(), IsTrayWindow(), max, NULL, PCHECKPOINT, PROP_CHECKPOINT, PROPF_INTERNAL, tagCHECKPOINT::ptMin, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, SYSMET, TestWF, TRUE, UINT, VOID(), WFMINIMIZED, WFVISIBLE, and WHERE_NOONE_CAN_SEE_ME.

Referenced by xxxMinMaximize().

00327 { 00328 RECT rcTest; 00329 RECT rcT; 00330 UINT xIconPositions; 00331 UINT xIconT; 00332 PWND pwndTest; 00333 PWND pwndParent; 00334 int xOrg; 00335 int yOrg; 00336 int dx; 00337 int dy; 00338 int dxSlot; 00339 int dySlot; 00340 int iteration; 00341 BOOL fHorizontal; 00342 PCHECKPOINT pncp; 00343 00344 /* 00345 * Put these into local vars immediately. The compiler is too dumb to 00346 * know that we're using a constant offset into a constant address, and 00347 * thus a resulting constant address. 00348 */ 00349 dxSlot = SYSMET(CXMINSPACING); 00350 dySlot = SYSMET(CYMINSPACING); 00351 00352 if (IsTrayWindow(pwnd)) { 00353 00354 pcp->fMinInitialized = TRUE; 00355 pcp->ptMin.x = WHERE_NOONE_CAN_SEE_ME; 00356 pcp->ptMin.y = WHERE_NOONE_CAN_SEE_ME; 00357 00358 return; 00359 } 00360 00361 /* We need to adjust the client rectangle for scrollbars, just like we 00362 * do in ArrangeIconicWindows(). If one thing is clear, it is that 00363 * parking and arranging must follow the same principles. This is to 00364 * avoid the user arranging some windows, creating a new one, and parking 00365 * it in a place not consistent with the arrangement of the others. 00366 */ 00367 pwndParent = pwnd->spwndParent; 00368 GetRealClientRect(pwndParent, &rcT, GRC_SCROLLS, NULL); 00369 00370 /* 00371 * Get gravity & move vars. We want gaps to start on the sides that 00372 * we begin arranging from. 00373 * 00374 * Horizontal gravity 00375 */ 00376 if (SYSMET(ARRANGE) & ARW_STARTRIGHT) { 00377 00378 /* 00379 * Starting on right side 00380 */ 00381 rcTest.left = xOrg = rcT.right - dxSlot; 00382 dx = -dxSlot; 00383 00384 } else { 00385 00386 /* 00387 * Starting on left 00388 */ 00389 rcTest.left = xOrg = rcT.left + DX_GAP; 00390 dx = dxSlot; 00391 } 00392 00393 /* 00394 * Vertical gravity 00395 */ 00396 if (SYSMET(ARRANGE) & ARW_STARTTOP) { 00397 00398 /* 00399 * Starting on top side 00400 */ 00401 rcTest.top = yOrg = rcT.top + DY_GAP; 00402 dy = dySlot; 00403 00404 } else { 00405 00406 /* 00407 * Starting on bottom 00408 */ 00409 rcTest.top = yOrg = rcT.bottom - dySlot; 00410 dy = -dySlot; 00411 } 00412 00413 /* 00414 * Get arrangement direction. Note that ARW_HORIZONTAL is 0, so we 00415 * can't test for it. 00416 */ 00417 fHorizontal = ((SYSMET(ARRANGE) & ARW_DOWN) ? FALSE : TRUE); 00418 00419 if (fHorizontal) 00420 xIconPositions = xIconT = max(1, (rcT.right / dxSlot)); 00421 else 00422 xIconPositions = xIconT = max(1, (rcT.bottom / dySlot)); 00423 00424 /* 00425 * BOGUS 00426 * LauraBu 10/15/92 00427 * What happens if the parent is scrolled over horizontally or 00428 * vertically? Just like when you drop an object... 00429 */ 00430 iteration = 0; 00431 while (iteration < 5000) { 00432 00433 /* 00434 * Make a rectangle representing this position, in screen coords 00435 */ 00436 rcTest.right = rcTest.left + dxSlot; 00437 rcTest.bottom = rcTest.top + dySlot; 00438 00439 /* 00440 * Look for intersections with existing iconic windows 00441 */ 00442 for (pwndTest = pwndParent->spwndChild; pwndTest; pwndTest = pwndTest->spwndNext) { 00443 00444 if (!TestWF(pwndTest, WFVISIBLE)) 00445 continue; 00446 00447 if (pwndTest == pwnd) 00448 continue; 00449 00450 if (!TestWF(pwndTest, WFMINIMIZED)) { 00451 00452 /* 00453 * This is a non-minimized window. See if it has a checkpoint 00454 * and find out where it would be if it were minimized. We 00455 * will try not to park an icon in this spot. 00456 */ 00457 pncp = (PCHECKPOINT)_GetProp(pwndTest, 00458 PROP_CHECKPOINT, 00459 PROPF_INTERNAL); 00460 00461 if (!pncp || !pncp->fDragged || !pncp->fMinInitialized) 00462 continue; 00463 00464 /* 00465 * Get parent coordinates of minimized window pos. 00466 */ 00467 rcT.right = rcT.left = pncp->ptMin.x; 00468 rcT.right += dxSlot; 00469 rcT.bottom = rcT.top = pncp->ptMin.y; 00470 rcT.bottom += dySlot; 00471 00472 } else { 00473 00474 /* 00475 * Get parent coordinates of currently minimized window 00476 */ 00477 GetRect(pwndTest, &rcT, GRECT_WINDOW | GRECT_PARENTCOORDS); 00478 } 00479 00480 iteration++; 00481 /* 00482 * Get out of loop if they overlap 00483 */ 00484 if (IntersectRect(&rcT, &rcT, &rcTest)) 00485 break; 00486 } 00487 00488 /* 00489 * Found a position that doesn't overlap, so get out of search loop 00490 */ 00491 if (!pwndTest) 00492 break; 00493 00494 /* 00495 * Else setup to process the next position 00496 */ 00497 if (--xIconT == 0) { 00498 00499 /* 00500 * Setup next pass 00501 */ 00502 xIconT = xIconPositions; 00503 00504 if (fHorizontal) { 00505 rcTest.left = xOrg; 00506 rcTest.top += dy; 00507 } else { 00508 rcTest.left += dx; 00509 rcTest.top = yOrg; 00510 } 00511 00512 } else { 00513 00514 /* 00515 * Same pass. 00516 */ 00517 if (fHorizontal) 00518 rcTest.left += dx; 00519 else 00520 rcTest.top += dy; 00521 } 00522 } 00523 00524 /* 00525 * Note that rcTest is in parent coordinates already. 00526 */ 00527 pcp->fMinInitialized = TRUE; 00528 pcp->ptMin.x = rcTest.left; 00529 pcp->ptMin.y = rcTest.top; 00530 }

ULONG_PTR SaveScreen PWND  pwnd,
ULONG  iMode,
ULONG_PTR  iSave,
int  x,
int  y,
int  cx,
int  cy
 

Definition at line 538 of file minmax.c.

References cy, gpDispInfo, tagDISPLAYINFO::hDev, IntersectRect(), tagDISPLAYINFO::rcScreen, and tagWND::rcWindow.

Referenced by xxxAnimateCaption().

00539 { 00540 RECT rc; 00541 00542 /* 00543 * x and y are in the DC coordinates, make the screen in the 00544 * (meta hdev) coordinates for the call to Gre/driver. 00545 */ 00546 rc.left = x + pwnd->rcWindow.left; 00547 rc.right = x + cx; 00548 rc.top = y + pwnd->rcWindow.top; 00549 rc.bottom = y + cy; 00550 00551 if (IntersectRect(&rc, &rc, &gpDispInfo->rcScreen)) { 00552 return GreSaveScreenBits(gpDispInfo->hDev, iMode, iSave, (RECTL*)&rc); 00553 } else { 00554 return 0; 00555 } 00556 }

BOOL xxxActivateOnMinimize PWND  pwnd  ) 
 

Definition at line 1218 of file minmax.c.

References _GetDesktopWindow(), BOOL, FALSE, GetFullScreen, GetLastTopMostWindow(), HIBYTE, HMIsMarkDestroy, LOBYTE, NULL, tagTHREADINFO::pq, PtiCurrent, tagQ::spwndActivePrev, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, TestWF, ThreadLockAlwaysWithPti, ThreadUnlock, TRUE, WEFNOACTIVATE, WEFTOOLWINDOW, WFDISABLED, WFMINIMIZED, WFVISIBLE, and xxxSetForegroundWindow().

Referenced by xxxMinimizeHungWindow(), and xxxMinMaximize().

01219 { 01220 PTHREADINFO ptiCurrent = PtiCurrent(); 01221 PWND pwndStart, pwndFirstTool, pwndT; 01222 BOOL fTryTopmost = TRUE; 01223 BOOL fPrevCheck = (ptiCurrent->pq->spwndActivePrev != NULL); 01224 TL tlpwndT; 01225 01226 /* 01227 * We should always have a last-topmost window. 01228 */ 01229 pwndStart = GetLastTopMostWindow(); 01230 if (pwndStart) { 01231 pwndStart = pwndStart->spwndNext; 01232 } else { 01233 pwndStart = pwnd->spwndParent->spwndChild; 01234 } 01235 01236 UserAssert(HIBYTE(WFMINIMIZED) == HIBYTE(WFVISIBLE)); 01237 UserAssert(HIBYTE(WFVISIBLE) == HIBYTE(WFDISABLED)); 01238 01239 SearchAgain: 01240 01241 pwndT = (fPrevCheck ? ptiCurrent->pq->spwndActivePrev : pwndStart); 01242 pwndFirstTool = NULL; 01243 01244 for ( ; pwndT ; pwndT = pwndT->spwndNext) { 01245 01246 TryThisWindow: 01247 01248 /* 01249 * Use the first nonminimized, visible, nondisabled, and 01250 * nonbottommost window 01251 */ 01252 if (!HMIsMarkDestroy(pwndT) && 01253 !TestWF(pwndT, WEFNOACTIVATE) && 01254 (TestWF(pwndT, WFVISIBLE | WFDISABLED) == LOBYTE(WFVISIBLE)) && 01255 (!TestWF(pwndT, WFMINIMIZED) || GetFullScreen(pwndT) == FULLSCREEN)) { 01256 01257 if (TestWF(pwndT, WEFTOOLWINDOW)) { 01258 if (!pwndFirstTool) { 01259 pwndFirstTool = pwndT; 01260 } 01261 } else { 01262 break; 01263 } 01264 } 01265 01266 if (fPrevCheck) { 01267 fPrevCheck = FALSE; 01268 pwndT = pwndStart; 01269 goto TryThisWindow; 01270 } 01271 } 01272 01273 if (!pwndT) { 01274 01275 if (fTryTopmost) { 01276 01277 fTryTopmost = FALSE; 01278 if (pwndStart != NULL) { 01279 pwndStart = pwndStart->spwndParent->spwndChild; 01280 } else { 01281 PWND pwndDesktop = _GetDesktopWindow(); 01282 pwndStart = (pwndDesktop != NULL) ? pwndDesktop->spwndChild : NULL; 01283 } 01284 goto SearchAgain; 01285 } 01286 01287 pwndT = pwndFirstTool; 01288 } 01289 01290 if (pwndT) { 01291 ThreadLockAlwaysWithPti(ptiCurrent, pwndT, &tlpwndT); 01292 xxxSetForegroundWindow(pwndT, FALSE); 01293 ThreadUnlock(&tlpwndT); 01294 } else { 01295 return FALSE; 01296 } 01297 01298 return TRUE; 01299 }

VOID xxxAnimateCaption PWND  pwnd,
HDC  hdc,
LPRECT  lprcStart,
LPRECT  lprcEnd
 

Definition at line 558 of file minmax.c.

References _WindowFromDC(), CheckLock, CMS_ANIMATION, CreateCaptionStrip(), cy, DWORD, FALSE, gbRemoteSession, GetWindowBorders(), ghbmCaption, ghdcMem, max, MultDiv, NtGetTickCount(), NULL, SaveScreen(), SYSMET, TestALPHA, TRUE, UserSleep(), VOID(), and xxxDrawCaptionTemp().

Referenced by xxxDrawAnimatedRects().

00563 { 00564 DWORD dwTimeStart; 00565 DWORD iTimeElapsed; 00566 int iLeftStart; 00567 int iTopStart; 00568 int cxStart; 00569 int dLeft; 00570 int dTop; 00571 int dcx; 00572 int iLeft; 00573 int iTop; 00574 int cx; 00575 int iLeftNew; 00576 int iTopNew; 00577 int cxNew; 00578 int cBorders; 00579 HBITMAP hbmpOld; 00580 RECT rc; 00581 int cy; 00582 HDC hdcMem; 00583 ULONG_PTR uSave; 00584 PWND pwndOrg; 00585 00586 CheckLock(pwnd); 00587 00588 if ((pwndOrg = _WindowFromDC(hdc)) == NULL) { 00589 RIPMSG0(RIP_WARNING, "SaveScreen: invalid DC passed in"); 00590 return; 00591 } 00592 00593 cy = SYSMET(CYCAPTION) - 1; 00594 00595 /* 00596 * kurtp: 29-Jan-1997 00597 * 00598 * We don't do anything when animating the caption, 00599 * because we couldn't get the desired effect at the 00600 * client. If we do use it then the 00601 * cache gets a bunch of bitmaps (size: 2xCaption by CXScreen) 00602 * that are never re-used. This slows down clients 00603 * because the GreBitBlts always generate new bitmaps 00604 * and the cache is displaced by the new bitmaps (yuk!). 00605 */ 00606 00607 if (gbRemoteSession) 00608 return; 00609 00610 if ((hdcMem = GreCreateCompatibleDC(ghdcMem)) == NULL) 00611 return; 00612 00613 /* 00614 * If the caption strip doesn't exist, then attempt to recreate it. This 00615 * might be necessary if the user does a mode-switch during low memory 00616 * and is not able to recreate the surface. When the memory becomes 00617 * available, we'll attempt to recreate it here. 00618 */ 00619 if (ghbmCaption == NULL) { 00620 ghbmCaption = CreateCaptionStrip(); 00621 } 00622 00623 hbmpOld = GreSelectBitmap(hdcMem, ghbmCaption); 00624 00625 /* 00626 * initialize start values 00627 */ 00628 iTopStart = lprcStart->top; 00629 iLeftStart = lprcStart->left; 00630 cxStart = lprcStart->right - iLeftStart; 00631 00632 /* 00633 * initialize delta values to the destination dimensions 00634 */ 00635 dLeft = lprcEnd->left; 00636 dTop = lprcEnd->top; 00637 dcx = lprcEnd->right - dLeft; 00638 00639 /* 00640 * adjust for window borders as appropriate 00641 */ 00642 cBorders = GetWindowBorders(pwnd->style, 00643 pwnd->ExStyle, 00644 TRUE, 00645 FALSE); 00646 00647 if ((lprcStart->bottom - iTopStart) > SYSMET(CYCAPTION)) { 00648 00649 iLeftStart += cBorders; 00650 iTopStart += cBorders; 00651 cxStart -= 2*cBorders; 00652 } 00653 00654 if ((lprcEnd->bottom - dTop) > SYSMET(CYCAPTION)) { 00655 00656 dLeft += cBorders; 00657 dTop += cBorders; 00658 dcx -= 2*cBorders; 00659 } 00660 00661 /* 00662 * initialize step values 00663 */ 00664 iLeft = iLeftStart; 00665 iTop = iTopStart; 00666 cx = cxStart; 00667 00668 /* 00669 * initialize off screen bitmap with caption drawing and first saved rect 00670 */ 00671 rc.left = 0; 00672 rc.top = cy; 00673 rc.right = max(cxStart, dcx); 00674 rc.bottom = cy * 2; 00675 00676 xxxDrawCaptionTemp(pwnd, 00677 hdcMem, 00678 &rc, 00679 NULL, 00680 NULL, 00681 NULL, 00682 DC_ACTIVE | DC_ICON | DC_TEXT | 00683 (TestALPHA(GRADIENTCAPTIONS) ? DC_GRADIENT : 0)); 00684 00685 if ((uSave = SaveScreen(pwndOrg, SS_SAVE, 0,iLeft, iTop, cx, cy)) == 0) { 00686 if (!GreBitBlt(hdcMem, 00687 0, 00688 0, 00689 cx, 00690 cy, 00691 hdc, 00692 iLeft, 00693 iTop, 00694 SRCCOPY, 00695 0)) { 00696 goto Cleanup; 00697 } 00698 } 00699 00700 /* 00701 * compute delta values by subtracting source dimensions 00702 */ 00703 dLeft -= iLeftStart; 00704 dTop -= iTopStart; 00705 dcx -= cxStart; 00706 00707 /* 00708 * blt and time first caption on screen 00709 * WARNING: If you use *lpSystemTickCount here, 00710 * the compiler may not generate code to do a DWORD fetch; 00711 */ 00712 dwTimeStart = NtGetTickCount(); 00713 GreBitBlt(hdc, 00714 iLeft, 00715 iTop, 00716 cx, 00717 cy, 00718 hdcMem, 00719 0, 00720 cy, 00721 SRCCOPY, 00722 0); 00723 00724 iTimeElapsed = (NtGetTickCount() - dwTimeStart); 00725 00726 while (LOWORD(iTimeElapsed) <= CMS_ANIMATION) { 00727 00728 iLeftNew = iLeftStart + MultDiv(dLeft, LOWORD(iTimeElapsed), CMS_ANIMATION); 00729 iTopNew = iTopStart + MultDiv(dTop, LOWORD(iTimeElapsed), CMS_ANIMATION); 00730 cxNew = cxStart + MultDiv(dcx, LOWORD(iTimeElapsed), CMS_ANIMATION); 00731 00732 /* 00733 * Delay before next frame 00734 */ 00735 UserSleep(1); 00736 00737 /* 00738 * restore saved rect 00739 */ 00740 if (uSave != 0) { 00741 SaveScreen(pwndOrg, SS_RESTORE, uSave, iLeft, iTop, cx, cy); 00742 } else { 00743 GreBitBlt(hdc, 00744 iLeft, 00745 iTop, 00746 cx, 00747 cy, 00748 hdcMem, 00749 0, 00750 0, 00751 SRCCOPY, 00752 0); 00753 } 00754 00755 iLeft = iLeftNew; 00756 iTop = iTopNew; 00757 cx = cxNew; 00758 00759 /* 00760 * save new rect offscreen and then draw over it onscreen. 00761 */ 00762 if (uSave != 0) { 00763 uSave = SaveScreen(pwndOrg, SS_SAVE, 0, iLeft, iTop, cx, cy); 00764 } else { 00765 GreBitBlt(hdcMem, 00766 0, 00767 0, 00768 cx, 00769 cy, 00770 hdc, 00771 iLeft, 00772 iTop, 00773 SRCCOPY, 00774 0); 00775 } 00776 GreBitBlt(hdc, 00777 iLeft, 00778 iTop, 00779 cx, 00780 cy, 00781 hdcMem, 00782 0, 00783 cy, 00784 SRCCOPY, 00785 0); 00786 00787 /* 00788 * update elapsed time 00789 * WARNING: If you use *lpSystemTickCount here, 00790 * the compiler may not generate code to do a DWORD fetch; 00791 */ 00792 iTimeElapsed = (NtGetTickCount() - dwTimeStart); 00793 } 00794 00795 /* 00796 * restore saved rect 00797 */ 00798 if (uSave != 0) { 00799 SaveScreen(pwndOrg, SS_RESTORE, uSave, iLeft, iTop, cx, cy); 00800 } else { 00801 GreBitBlt(hdc, 00802 iLeft, 00803 iTop, 00804 cx, 00805 cy, 00806 hdcMem, 00807 0, 00808 0, 00809 SRCCOPY, 00810 0); 00811 } 00812 00813 Cleanup: 00814 GreSelectBitmap(hdcMem, hbmpOld); 00815 GreDeleteDC(hdcMem); 00816 }

BOOL xxxDrawAnimatedRects PWND  pwndClip,
int  idAnimation,
LPRECT  lprcStart,
LPRECT  lprcEnd
 

Definition at line 1042 of file minmax.c.

References _GetDCEx(), _GetDesktopWindow(), _ReleaseDC(), BOOL, CheckLock, CopyRect, FALSE, HRGN_FULL, NULL, PWNDDESKTOP, TRUE, and xxxAnimateCaption().

Referenced by NtUserDrawAnimatedRects(), xxxMinimizeHungWindow(), and xxxMinMaximize().

01047 { 01048 HDC hdc; 01049 POINT rgPt[4]; 01050 RECT rcClip; 01051 HRGN hrgn; 01052 PWND pwndAnimate = NULL; 01053 int iPt; 01054 01055 CheckLock(pwndClip); 01056 01057 /* 01058 * Get rects into variables 01059 */ 01060 CopyRect((LPRECT)&rgPt[0], lprcStart); 01061 CopyRect((LPRECT)&rgPt[2], lprcEnd); 01062 01063 /* 01064 * DISABLE OLD ANIMATION FOR M7 01065 */ 01066 if (idAnimation != IDANI_CAPTION) 01067 return TRUE; 01068 01069 pwndAnimate = pwndClip; 01070 if (!pwndAnimate || pwndAnimate == PWNDDESKTOP(pwndAnimate)) 01071 return FALSE; 01072 01073 pwndClip = pwndClip->spwndParent; 01074 if (!pwndClip) { 01075 RIPMSG0(RIP_WARNING, "xxxDrawAnimatedRects: pwndClip->spwndParent is NULL"); 01076 } else if (pwndClip == PWNDDESKTOP(pwndClip)) { 01077 pwndClip = NULL; 01078 } 01079 01080 /* 01081 * NOTE: 01082 * We do NOT need to do LockWindowUpdate(). We never yield within this 01083 * function! Anything that was invalid will stay invalid, etc. So our 01084 * XOR drawing won't leave remnants around. 01085 * 01086 * WIN32NT may need to take display critical section or do LWU(). 01087 * 01088 * Get clipping area 01089 * Neat feature: 01090 * NULL window means whole screen, don't clip out children 01091 * hwndDesktop means working area, don't clip out children 01092 */ 01093 if (pwndClip == NULL) { 01094 pwndClip = _GetDesktopWindow(); 01095 CopyRect(&rcClip, &pwndClip->rcClient); 01096 if ((hrgn = GreCreateRectRgnIndirect(&rcClip)) == NULL) { 01097 hrgn = HRGN_FULL; 01098 } 01099 01100 /* 01101 * Get drawing DC 01102 */ 01103 hdc = _GetDCEx(pwndClip, 01104 hrgn, 01105 DCX_WINDOW | 01106 DCX_CACHE | 01107 DCX_INTERSECTRGN | 01108 DCX_LOCKWINDOWUPDATE); 01109 } else { 01110 01111 hdc = _GetDCEx(pwndClip, 01112 HRGN_FULL, 01113 DCX_WINDOW | DCX_USESTYLE | DCX_INTERSECTRGN); 01114 01115 /* 01116 * We now have a window DC. We need to convert client coords 01117 * to window coords. 01118 */ 01119 for (iPt = 0; iPt < 4; iPt++) { 01120 01121 rgPt[iPt].x += (pwndClip->rcClient.left - pwndClip->rcWindow.left); 01122 rgPt[iPt].y += (pwndClip->rcClient.top - pwndClip->rcWindow.top); 01123 } 01124 } 01125 01126 /* 01127 * Get drawing DC: 01128 * Unclipped if desktop, clipped otherwise. 01129 * Note that ReleaseDC() will free the region if needed. 01130 */ 01131 if (idAnimation == IDANI_CAPTION) { 01132 CheckLock(pwndAnimate); 01133 xxxAnimateCaption(pwndAnimate, hdc, (LPRECT)&rgPt[0], (LPRECT)&rgPt[2]); 01134 } 01135 01136 /* 01137 * DISABLE OLD ANIMATION FOR M7 01138 */ 01139 #if 0 01140 else { 01141 AnimateFrame(hdc, 01142 (LPRECT)&rgPt[0], 01143 (LPRECT)&rgPt[2], 01144 (idAnimation == IDANI_OPEN)); 01145 } 01146 #endif 01147 /* 01148 * END DISABLE OLD ANIMATION FOR M7 01149 */ 01150 01151 /* 01152 * Clean up 01153 */ 01154 _ReleaseDC(hdc); 01155 01156 return TRUE; 01157 }

void xxxInitSendValidateMinMaxInfo PWND  pwnd,
LPMINMAXINFO  lpmmi
 

Definition at line 32 of file minmax.c.

References _GetClientRect(), _GetProp(), _HasCaptionIcon(), _MonitorFromWindow(), CheckLock, ClrWF, FALSE, tagCHECKPOINT::fMaxInitialized, gcxCaptionFontChar, GetMonitorMaxArea(), GetPrimaryMonitor(), GetWindowBorders(), InflateRect(), max, NULL, PROP_CHECKPOINT, PROPF_INTERNAL, PtiCurrent, tagCHECKPOINT::ptMax, PWNDDESKTOP, tagMONITOR::rcMonitor, SetWF, tagWND::spwndParent, SYSMET, TestWF, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, TRUE, WEFCONTEXTHELP, WEFTOOLWINDOW, WFCAPTION, WFCPRESENT, WFMAXBOX, WFMINBOX, WFREALLYMAXIMIZABLE, WFSIZEBOX, WFSYSMENU, and xxxSendMessage().

Referenced by xxxAdjustSize(), xxxMinMaximize(), and xxxMoveSize().

00033 { 00034 PTHREADINFO ptiCurrent; 00035 PMONITOR pMonitorReal; 00036 PMONITOR pMonitorPrimary; 00037 TL tlpMonitorReal; 00038 TL tlpMonitorPrimary; 00039 CHECKPOINT * pcp; 00040 RECT rcParent; 00041 int cBorders; 00042 int xMin, yMin; 00043 00044 CheckLock(pwnd); 00045 00046 ptiCurrent = PtiCurrent(); 00047 00048 /* 00049 * FILL IN THE MINMAXINFO WE THINK IS APPROPRIATE 00050 */ 00051 00052 /* 00053 * Minimized Size 00054 */ 00055 lpmmi->ptReserved.x = SYSMET(CXMINIMIZED); 00056 lpmmi->ptReserved.y = SYSMET(CYMINIMIZED); 00057 00058 /* 00059 * Maximized Position and Size 00060 * Figure out where the window would be maximized within its parent. 00061 */ 00062 pMonitorPrimary = GetPrimaryMonitor(); 00063 if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 00064 /* What monitor is the window really going to maximize to? */ 00065 pMonitorReal = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY); 00066 00067 /* Send dimensions based on the primary only. */ 00068 rcParent = pMonitorPrimary->rcMonitor; 00069 } else { 00070 pMonitorReal = NULL; 00071 _GetClientRect(pwnd->spwndParent, &rcParent); 00072 } 00073 00074 cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); 00075 00076 InflateRect(&rcParent, 00077 cBorders * SYSMET(CXBORDER), 00078 cBorders * SYSMET(CYBORDER)); 00079 00080 rcParent.right -= rcParent.left; 00081 rcParent.bottom -= rcParent.top; 00082 00083 /* rcParent.right, bottom are width and height now. */ 00084 lpmmi->ptMaxSize.x = rcParent.right; 00085 lpmmi->ptMaxSize.y = rcParent.bottom; 00086 00087 pcp = (CHECKPOINT *)_GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL); 00088 if (pcp && pcp->fMaxInitialized) { 00089 /* 00090 * Note: For top level windows, we will fix this point up after 00091 * the fact if it has gotten out of date because the size border 00092 * changed. 00093 */ 00094 lpmmi->ptMaxPosition = pcp->ptMax; 00095 } else { 00096 lpmmi->ptMaxPosition = *((LPPOINT)&rcParent.left); 00097 } 00098 00099 /* 00100 * Normal minimum tracking size 00101 * Only enforce min tracking size for windows with captions 00102 */ 00103 xMin = cBorders*SYSMET(CXEDGE); 00104 yMin = cBorders*SYSMET(CYEDGE); 00105 00106 if (TestWF(pwnd, WFCAPTION) && !TestWF(pwnd, WEFTOOLWINDOW)) { 00107 lpmmi->ptMinTrackSize.x = SYSMET(CXMINTRACK); 00108 lpmmi->ptMinTrackSize.y = SYSMET(CYMINTRACK); 00109 } else { 00110 lpmmi->ptMinTrackSize.x = max(SYSMET(CXEDGE), xMin); 00111 lpmmi->ptMinTrackSize.y = max(SYSMET(CYEDGE), yMin); 00112 } 00113 00114 /* 00115 * Normal maximum tracking size 00116 */ 00117 lpmmi->ptMaxTrackSize.x = SYSMET(CXMAXTRACK); 00118 lpmmi->ptMaxTrackSize.y = SYSMET(CYMAXTRACK); 00119 00120 /* 00121 * SEND THE WM_GETMINMAXINFO MESSAGE 00122 */ 00123 00124 ThreadLockWithPti(ptiCurrent, pMonitorReal, &tlpMonitorReal); 00125 ThreadLockAlwaysWithPti(ptiCurrent, pMonitorPrimary, &tlpMonitorPrimary); 00126 xxxSendMessage(pwnd, WM_GETMINMAXINFO, 0, (LPARAM)lpmmi); 00127 00128 /* 00129 * VALIDATE THE MINMAXINFO 00130 */ 00131 00132 /* 00133 * Minimized Size (this is read only) 00134 */ 00135 lpmmi->ptReserved.x = SYSMET(CXMINIMIZED); 00136 lpmmi->ptReserved.y = SYSMET(CYMINIMIZED); 00137 00138 /* 00139 * Maximized Postion and Size (only for top level windows) 00140 */ 00141 if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 00142 LPRECT lprcRealMax; 00143 00144 GetMonitorMaxArea(pwnd, pMonitorReal, &lprcRealMax); 00145 00146 /* 00147 * Is the window a TRUE maximized dude, or somebody like the DOS box 00148 * who can maximize but not take up the entire screen? 00149 * 00150 * Is the window really maximizeable? 00151 */ 00152 if ((lpmmi->ptMaxSize.x >= (pMonitorPrimary->rcMonitor.right - pMonitorPrimary->rcMonitor.left)) && 00153 (lpmmi->ptMaxSize.y >= (pMonitorPrimary->rcMonitor.bottom - pMonitorPrimary->rcMonitor.top))) { 00154 00155 SetWF(pwnd, WFREALLYMAXIMIZABLE); 00156 00157 /* 00158 * Need to reload the checkpoint here, since it might have gotten 00159 * blown away while we were in the xxxSendMessage call above. 00160 */ 00161 pcp = (CHECKPOINT *)_GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL); 00162 00163 if ( pcp && 00164 pcp->fMaxInitialized && 00165 TestWF(pwnd, WFSIZEBOX) && 00166 (lpmmi->ptMaxPosition.x != rcParent.left) && 00167 (pcp->ptMax.x == lpmmi->ptMaxPosition.x)) { 00168 00169 /* 00170 * If this window has a weird maximize point that doesn't jibe 00171 * with what we'd expect and it has a checkpoint, fix up the 00172 * checkpoint. It means that somebody's WINDOWPLACEMENT 00173 * got out of date when the size border changed dimensions. 00174 */ 00175 pcp->fMaxInitialized = FALSE; 00176 00177 lpmmi->ptMaxPosition.y += (rcParent.left - lpmmi->ptMaxPosition.x); 00178 lpmmi->ptMaxPosition.x = rcParent.left; 00179 } 00180 00181 /* 00182 * Transfer the maximum size over to the monitor we are REALLY 00183 * moving to. And fix up guys going fullscreen. A whole bunch 00184 * of Consumer titles + Word '95 and XL '95 move their caption 00185 * above the top of the monitor when going fullscreen. Detect 00186 * these guys now, and let them take up the monitor. 00187 */ 00188 if ( lpmmi->ptMaxPosition.y + SYSMET(CYCAPTION) <= 00189 pMonitorPrimary->rcMonitor.top 00190 && 00191 lpmmi->ptMaxPosition.y + lpmmi->ptMaxSize.y >= 00192 pMonitorPrimary->rcMonitor.bottom) { 00193 00194 lprcRealMax = &pMonitorReal->rcMonitor; 00195 } 00196 00197 /* 00198 * Compensate for the difference between the primary monitor 00199 * and the monitor we are actually on. 00200 */ 00201 lpmmi->ptMaxSize.x = lpmmi->ptMaxSize.x - 00202 (pMonitorPrimary->rcMonitor.right - pMonitorPrimary->rcMonitor.left) + 00203 (lprcRealMax->right - lprcRealMax->left); 00204 00205 lpmmi->ptMaxSize.y = lpmmi->ptMaxSize.y - 00206 (pMonitorPrimary->rcMonitor.bottom - pMonitorPrimary->rcMonitor.top) + 00207 (lprcRealMax->bottom - lprcRealMax->top); 00208 } else { 00209 ClrWF(pwnd, WFREALLYMAXIMIZABLE); 00210 } 00211 00212 /* 00213 * Now transfer the max position over to the monitor we are REALLY 00214 * moving to. 00215 */ 00216 lpmmi->ptMaxPosition.x += lprcRealMax->left; 00217 lpmmi->ptMaxPosition.y += lprcRealMax->top; 00218 } 00219 00220 ThreadUnlock(&tlpMonitorPrimary); 00221 ThreadUnlock(&tlpMonitorReal); 00222 00223 /* 00224 * Normal minimum tracking size. 00225 */ 00226 00227 /* 00228 * WFCAPTION == WFBORDER | WFDLGFRAME; So, when we want to test for the 00229 * presence of CAPTION, we must test for both the bits. Otherwise we 00230 * might mistake WFBORDER or WFDLGFRAME to be a CAPTION. 00231 * 00232 * 00233 * We must not allow a window to be sized smaller than the border 00234 * thickness -- SANKAR -- 06/12/91 -- 00235 */ 00236 if (TestWF(pwnd, WFCPRESENT)) { 00237 00238 /* 00239 * NOTE THAT IF YOU CHANGE THE SPACING OF STUFF IN THE CAPTION, 00240 * YOU NEED TO KEEP THE FOLLOWING IN SSYNC: 00241 * (1) Default CXMINTRACK, CYMINTRACK in inctlpan.c 00242 * (2) The default minimum right below 00243 * (3) Hit testing 00244 * 00245 * The minimum size should be space for: 00246 * * The borders 00247 * * The buttons 00248 * * Margins 00249 * * 4 chars of text 00250 * * Caption icon 00251 */ 00252 yMin = SYSMET(CYMINTRACK); 00253 00254 /* 00255 * Min track size is determined by the number of buttons in 00256 * the caption. 00257 */ 00258 if (TestWF(pwnd, WEFTOOLWINDOW)) { 00259 00260 /* 00261 * Add in space for close button. 00262 */ 00263 if (TestWF(pwnd, WFSYSMENU)) 00264 xMin += SYSMET(CXSMSIZE); 00265 00266 /* 00267 * DON'T add in space for 2 characters--breaks 00268 * MFC toolbar stuff. They want to make vertical undocked 00269 * toolbars narrower than what that would produce. 00270 */ 00271 xMin += (2 * SYSMET(CXEDGE)); 00272 00273 } else { 00274 00275 if (TestWF(pwnd, WFSYSMENU)) { 00276 00277 /* 00278 * Add in space for min/max/close buttons. Otherwise, 00279 * if it's a contexthelp window, then add in space 00280 * for help/close buttons. 00281 */ 00282 if (TestWF(pwnd, (WFMINBOX | WFMAXBOX))) 00283 xMin += 3 * SYSMET(CXSIZE); 00284 else if (TestWF(pwnd, WEFCONTEXTHELP)) 00285 xMin += 2 * SYSMET(CXSIZE); 00286 00287 00288 /* 00289 * Add in space for system menu icon. 00290 */ 00291 if (_HasCaptionIcon(pwnd)) 00292 xMin += SYSMET(CYSIZE); 00293 } 00294 00295 /* 00296 * Add in space for 4 characters and margins. 00297 */ 00298 xMin += 4 * gcxCaptionFontChar + 2 * SYSMET(CXEDGE); 00299 } 00300 } 00301 00302 lpmmi->ptMinTrackSize.x = max(lpmmi->ptMinTrackSize.x, xMin); 00303 lpmmi->ptMinTrackSize.y = max(lpmmi->ptMinTrackSize.y, yMin); 00304 }

void xxxMinimizeHungWindow PWND  pwnd  ) 
 

Definition at line 2005 of file minmax.c.

References CheckLock, GETPTI, IDC_DEFAULT, IsRectEmpty(), NULL, PostEventMessage(), PUDF_ANIMATE, PWNDDESKTOP, QEVENT_HUNGTHREAD, tagWND::rcWindow, SetRectEmpty, SetVisible(), tagWND::spwndParent, SV_UNSET, TEST_PUDF, TestWF, WFMINIMIZED, WFVISIBLE, xxxActivateOnMinimize(), xxxDrawAnimatedRects(), xxxRedrawWindow(), xxxSendMinRectMessages(), xxxShowOwnedWindows(), and zzzInvalidateDCCache().

Referenced by xxxDesktopThread(), and xxxShowWindow().

02006 { 02007 RECT rcMin; 02008 HRGN hrgnHung; 02009 02010 02011 CheckLock(pwnd); 02012 02013 /* 02014 * If the window is already minimized or not visible don't do anything. 02015 */ 02016 if (TestWF(pwnd, WFMINIMIZED) || !TestWF(pwnd, WFVISIBLE)) 02017 return; 02018 02019 /* 02020 * Animate the caption to the minimized state. 02021 */ 02022 if (TEST_PUDF(PUDF_ANIMATE)) { 02023 SetRectEmpty(&rcMin); 02024 xxxSendMinRectMessages(pwnd, &rcMin); 02025 if (!IsRectEmpty(&rcMin)) { 02026 xxxDrawAnimatedRects(pwnd, IDANI_CAPTION, &pwnd->rcWindow, &rcMin); 02027 } 02028 } 02029 02030 /* 02031 * Reset the visible bit on the window itself and ownees. At the same 02032 * time calculate how much needs to be repainted. We must invalidate 02033 * the DC cache to make sure that the visible regions get recalculated. 02034 */ 02035 SetVisible(pwnd, SV_UNSET); 02036 hrgnHung = GreCreateRectRgnIndirect(&pwnd->rcWindow); 02037 xxxShowOwnedWindows(pwnd, SW_PARENTCLOSING, hrgnHung); 02038 zzzInvalidateDCCache(pwnd, IDC_DEFAULT); 02039 xxxRedrawWindow(NULL, NULL, hrgnHung, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); 02040 GreDeleteObject(hrgnHung); 02041 02042 /* 02043 * Deal with activating some other window for top-level windows. 02044 */ 02045 if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 02046 xxxActivateOnMinimize(pwnd); 02047 } 02048 PostEventMessage(GETPTI(pwnd), GETPTI(pwnd)->pq, QEVENT_HUNGTHREAD, pwnd, 0, 0, 0); 02049 }

PWND xxxMinMaximize PWND  pwnd,
UINT  cmd,
DWORD  dwFlags
 

Definition at line 1329 of file minmax.c.

References _DeferWindowPos(), _PostMessage(), tagSMWP::acvr, AW_SKIP, BOOL, CalcMinZOrder(), CheckLock, CkptRestore(), ClrFTrueVis(), ClrWF, tagDISPLAYINFO::cMonitors, CopyRect, dwFlags, DWORD, FALSE, FCallHookTray, FDoTray, tagCHECKPOINT::fDragged, tagCHECKPOINT::fMinInitialized, FPostTray, tagCHECKPOINT::fWasMaximizedBeforeMinimized, tagCHECKPOINT::fWasMinimizedBeforeMaximized, FWINABLE, GETPTI, GetRect(), gpDispInfo, gpqForeground, gptiForeground, GRECT_PARENTCOORDS, GRECT_WINDOW, HIBYTE, HRGN_FULL, HRGN_MONITOR, tagCVR::hrgnClip, HWq, InternalBeginDeferWindowPos(), IsHooked, IsRectEmpty(), IsTrayWindow(), IsVisible(), KeAttachProcess(), KeDetachProcess(), L, MINMAX_ANIMATE, MINMAX_KEEPHIDDEN, MmAdjustWorkingSetSize(), NT_SUCCESS, NTSTATUS(), NULL, ParkIcon(), _EPROCESS::Pcb, PostShellHookMessages(), tagTHREADINFO::ppi, tagTHREADINFO::pq, PtiCurrent, tagCHECKPOINT::ptMin, PtoHq, PWNDDESKTOP, tagCHECKPOINT::rcNormal, tagWND::rcWindow, RestoreForegroundActivate(), RevalidateHwnd, SetMinimize(), SetRectEmpty, SetWF, SFW_STARTUP, SMIN_CLEAR, SMIN_SET, tagQ::spwndActive, tagWND::spwndChild, tagQ::spwndFocus, tagWND::spwndNext, tagWND::spwndParent, Status, SW_MDIRESTORE, SYSMET, TestWF, TestwndChild, THREAD_TO_PROCESS, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, tagTHREADINFO::TIF_flags, TIF_SYSTEMTHREAD, TRUE, UINT, WEF_USEPWNDTHREAD, WFCHILD, WFHASPALETTE, WFMAXFAKEREGIONAL, WFMAXIMIZED, WFMINIMIZED, WFNOANIMATE, WFTOPLEVEL, WFVISIBLE, WFWIN40COMPAT, WHF_CBT, xxxActivateOnMinimize(), xxxActivateWindow(), xxxCallHook(), xxxDrawAnimatedRects(), xxxEndDeferWindowPosEx(), xxxFlushPalette(), xxxInitSendValidateMinMaxInfo(), xxxSendMessage(), xxxSendMinRectMessages(), xxxSetFocus(), xxxSetForegroundWindow2(), xxxShowOwnedWindows(), and xxxWindowEvent().

Referenced by NtUserMinMaximize(), xxxCreateWindowEx(), xxxProcessHungThreadEvent(), and xxxShowWindow().

01333 { 01334 RECT rc; 01335 RECT rcWindow; 01336 RECT rcRestore; 01337 BOOL fShow = FALSE; 01338 BOOL fSetFocus = FALSE; 01339 BOOL fShowOwned = FALSE; 01340 BOOL fSendActivate = FALSE; 01341 BOOL fMaxStateChanging = FALSE; 01342 int idAnimation = 0; 01343 BOOL fFlushPalette = FALSE; 01344 UINT swpFlags = 0; 01345 HWND hwndAfter = NULL; 01346 PWND pwndT; 01347 PCHECKPOINT pcp; 01348 PTHREADINFO ptiCurrent; 01349 TL tlpwndParent; 01350 TL tlpwndT; 01351 PSMWP psmwp; 01352 BOOL fIsTrayWindowNow = FALSE; 01353 NTSTATUS Status; 01354 MINMAXINFO mmi; 01355 UINT uEvent = 0; 01356 #if defined(USE_MIRRORING) 01357 PWND pwndParent = pwnd->spwndParent; 01358 BOOL bMirroredParent=FALSE; 01359 #endif 01360 01361 CheckLock(pwnd); 01362 01363 /* 01364 * Get window rect, in parent client coordinates. 01365 */ 01366 GetRect(pwnd, &rcWindow, GRECT_WINDOW | GRECT_PARENTCOORDS); 01367 01368 /* 01369 * If this is NULL, we're out of memory, so punt now. 01370 */ 01371 pcp = CkptRestore(pwnd, &rcWindow); 01372 if (!pcp) 01373 goto Exit; 01374 01375 #if defined(USE_MIRRORING) 01376 /* 01377 * If this top-level window is placed in a mirrored desktop, 01378 * its coordinates should be mirrored here so that xxxAnimateCaptions 01379 * works properly, however we shouldn't change the actual screen coordinates 01380 * of the window. This is why I do it after CkptRestore(...). [samera] 01381 */ 01382 if (TestWF(pwndParent,WEFLAYOUTRTL) && 01383 (!TestWF(pwnd,WFCHILD))) { 01384 int iLeft = rcWindow.left; 01385 rcWindow.left = pwndParent->rcWindow.right - rcWindow.right; 01386 rcWindow.right = pwndParent->rcWindow.right - iLeft; 01387 bMirroredParent = TRUE; 01388 } 01389 #endif 01390 01391 01392 /* 01393 * Save the previous restore size. 01394 */ 01395 CopyRect(&rcRestore, &pcp->rcNormal); 01396 01397 /* 01398 * First ask the CBT hook if we can do this operation. 01399 */ 01400 if ( IsHooked(PtiCurrent(), WHF_CBT) && 01401 xxxCallHook(HCBT_MINMAX, (WPARAM)HWq(pwnd), (DWORD)cmd, WH_CBT)) { 01402 01403 goto Exit; 01404 } 01405 01406 /* 01407 * If another MDI window is being maximized, and we want to restore this 01408 * one to its previous state, we can't change the zorder or the 01409 * activation. We'd screw things up that way. BTW, this SW_ value is 01410 * internal. 01411 */ 01412 if (cmd == SW_MDIRESTORE) { 01413 01414 swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE; 01415 01416 cmd = (pcp->fWasMinimizedBeforeMaximized ? 01417 SW_SHOWMINIMIZED : SW_SHOWNORMAL); 01418 } 01419 01420 ptiCurrent = PtiCurrent(); 01421 01422 switch (cmd) { 01423 case SW_MINIMIZE: // Bottom of zorder, make top-level active 01424 case SW_SHOWMINNOACTIVE: // Bottom of zorder, don't change activation 01425 01426 if (gpqForeground && gpqForeground->spwndActive) 01427 swpFlags |= SWP_NOACTIVATE; 01428 01429 if ((pwndT = CalcMinZOrder(pwnd)) == NULL) { 01430 swpFlags |= SWP_NOZORDER; 01431 } else { 01432 hwndAfter = PtoHq(pwndT); 01433 } 01434 01435 01436 /* 01437 * FALL THRU 01438 */ 01439 01440 case SW_SHOWMINIMIZED: // Top of zorder, make active 01441 01442 /* 01443 * Force a show. 01444 */ 01445 fShow = TRUE; 01446 01447 /* 01448 * If already minimized, then don't change the existing 01449 * parking spot. 01450 */ 01451 if (TestWF(pwnd, WFMINIMIZED)) { 01452 01453 /* 01454 * If we're already minimized and we're properly visible 01455 * or not visible, don't do anything 01456 */ 01457 if (TestWF(pwnd, WFVISIBLE)) 01458 return NULL; 01459 01460 swpFlags |= SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE; 01461 01462 goto Showit; 01463 } 01464 01465 /* 01466 * We're becoming minimized although we currently are not. So 01467 * we want to draw the transition animation, and ALWAYS send 01468 * sizing messages. 01469 */ 01470 idAnimation = IDANI_CLOSE; 01471 01472 if (!pcp->fDragged) 01473 pcp->fMinInitialized = FALSE; 01474 01475 if (!pcp->fMinInitialized) 01476 ParkIcon(pwnd, pcp); 01477 01478 rc.left = pcp->ptMin.x; 01479 rc.top = pcp->ptMin.y; 01480 rc.right = pcp->ptMin.x + SYSMET(CXMINIMIZED); 01481 rc.bottom = pcp->ptMin.y + SYSMET(CYMINIMIZED); 01482 01483 xxxShowOwnedWindows(pwnd, SW_PARENTCLOSING, NULL); 01484 01485 pwndT = ptiCurrent->pq->spwndFocus; 01486 01487 while (pwndT) { 01488 01489 /* 01490 * if we or any child has the focus, punt it away 01491 */ 01492 if (pwndT != pwnd) { 01493 pwndT = pwndT->spwndParent; 01494 continue; 01495 } 01496 01497 ThreadLockAlwaysWithPti(ptiCurrent, pwndT, &tlpwndT); 01498 01499 if (TestwndChild(pwnd)) { 01500 01501 ThreadLockWithPti(ptiCurrent, pwnd->spwndParent, &tlpwndParent); 01502 xxxSetFocus(pwnd->spwndParent); 01503 ThreadUnlock(&tlpwndParent); 01504 01505 } else { 01506 xxxSetFocus(NULL); 01507 } 01508 01509 ThreadUnlock(&tlpwndT); 01510 break; 01511 } 01512 01513 /* 01514 * Save the maximized state so that we can restore the window maxed 01515 */ 01516 if (TestWF(pwnd, WFMAXIMIZED)) { 01517 pcp->fWasMaximizedBeforeMinimized = TRUE; 01518 fMaxStateChanging = TRUE; 01519 } else{ 01520 pcp->fWasMaximizedBeforeMinimized = FALSE; 01521 } 01522 01523 if (!TestWF(pwnd, WFWIN40COMPAT)) 01524 fIsTrayWindowNow = IsTrayWindow(pwnd); 01525 01526 /* 01527 * Decrement the visible-windows count only if the 01528 * window is visible. If the window is marked for 01529 * destruction, we will not decrement for that as 01530 * well. Let SetMinimize take care of this. 01531 */ 01532 SetMinimize(pwnd, SMIN_SET); 01533 ClrWF(pwnd, WFMAXIMIZED); 01534 01535 uEvent = EVENT_SYSTEM_MINIMIZESTART; 01536 01537 if (!TestWF(pwnd, WFWIN40COMPAT)) 01538 fIsTrayWindowNow = (fIsTrayWindowNow != IsTrayWindow(pwnd)); 01539 01540 /* 01541 * The children of this window are now no longer visible. 01542 * Ensure that they no longer have any update regions... 01543 */ 01544 for (pwndT = pwnd->spwndChild; pwndT; pwndT = pwndT->spwndNext) 01545 ClrFTrueVis(pwndT); 01546 01547 /* 01548 * B#2919 01549 * Ensure that the client area gets recomputed, and make 01550 * sure that no bits are copied when the size is changed. And 01551 * make sure that WM_SIZE messages get sent, even if our client 01552 * size is staying the same. 01553 */ 01554 swpFlags |= (SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_STATECHANGE); 01555 01556 /* 01557 * We are going minimized, so we want to give palette focus to 01558 * another app. 01559 */ 01560 if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 01561 fFlushPalette = (BOOL)TestWF(pwnd, WFHASPALETTE); 01562 } 01563 01564 break; 01565 01566 case SW_SHOWNOACTIVATE: 01567 if (gpqForeground && gpqForeground->spwndActive) 01568 swpFlags |= SWP_NOACTIVATE; 01569 01570 /* 01571 * FALL THRU 01572 */ 01573 01574 case SW_RESTORE: 01575 01576 /* 01577 * If restoring a minimized window that was maximized before 01578 * being minimized, go back to being maximized. 01579 */ 01580 if (TestWF(pwnd, WFMINIMIZED) && pcp->fWasMaximizedBeforeMinimized) 01581 cmd = SW_SHOWMAXIMIZED; 01582 else 01583 cmd = SW_NORMAL; 01584 01585 /* 01586 * FALL THRU 01587 */ 01588 01589 case SW_NORMAL: 01590 case SW_SHOWMAXIMIZED: 01591 01592 if (cmd == SW_SHOWMAXIMIZED) { 01593 01594 /* 01595 * If already maximized and visible, we have nothing to do 01596 * Otherwise, for the DOSbox, still set fMaxStateChanging 01597 * to TRUE so we recalc the monitor region if need be. 01598 * That way WinOldAp can change its "changing from maxed to 01599 * maxed with new bigger font" code to work right. 01600 */ 01601 if (TestWF(pwnd, WFMAXIMIZED)) { 01602 if (TestWF(pwnd, WFVISIBLE)) { 01603 return NULL; 01604 } 01605 } else { 01606 /* 01607 * We're changing from normal to maximized, so always 01608 * send WM_SIZE. 01609 */ 01610 swpFlags |= SWP_STATECHANGE; 01611 } 01612 fMaxStateChanging = TRUE; 01613 01614 /* 01615 * If calling from CreateWindow, don't let the thing become 01616 * activated by the SWP call below. Acitvation will happen 01617 * on the ShowWindow done by CreateWindow or the app. 01618 */ 01619 if (dwFlags & MINMAX_KEEPHIDDEN) 01620 swpFlags |= SWP_NOACTIVATE; 01621 01622 /* 01623 * This is for MDI's auto-restore behaviour (craigc) 01624 */ 01625 if (TestWF(pwnd, WFMINIMIZED)) 01626 pcp->fWasMinimizedBeforeMaximized = TRUE; 01627 01628 xxxInitSendValidateMinMaxInfo(pwnd, &mmi); 01629 01630 } else { 01631 01632 /* 01633 * We're changing state from non-normal to normal. Make 01634 * sure WM_SIZE gets sents. 01635 */ 01636 UserAssert(HIBYTE(WFMINIMIZED) == HIBYTE(WFMAXIMIZED)); 01637 if (TestWF(pwnd, WFMINIMIZED | WFMAXIMIZED)) { 01638 swpFlags |= SWP_STATECHANGE; 01639 } 01640 if (TestWF(pwnd, WFMAXIMIZED)) { 01641 fMaxStateChanging = TRUE; 01642 } 01643 } 01644 01645 /* 01646 * If currently minimized, show windows' popups 01647 */ 01648 if (TestWF(pwnd, WFMINIMIZED)) { 01649 01650 /* 01651 * Send WM_QUERYOPEN to make sure this guy should unminimize 01652 */ 01653 if (!xxxSendMessage(pwnd, WM_QUERYOPEN, 0, 0L)) 01654 return NULL; 01655 01656 idAnimation = IDANI_OPEN; 01657 fShowOwned = TRUE; 01658 fSetFocus = TRUE; 01659 01660 /* 01661 * JEFFBOG B#2868 01662 * Condition added before setting fSendActivate prevents 01663 * WM_ACTIVATE message from reaching a child window. Might 01664 * be backwards compatibility problems if a pre 3.1 app 01665 * relies on WM_ACTIVATE reaching a child. 01666 */ 01667 if (!TestWF(pwnd, WFCHILD)) 01668 fSendActivate = TRUE; 01669 01670 swpFlags |= SWP_NOCOPYBITS; 01671 } else { 01672 idAnimation = IDANI_CAPTION; 01673 } 01674 01675 if (cmd == SW_SHOWMAXIMIZED) { 01676 rc.left = mmi.ptMaxPosition.x; 01677 rc.top = mmi.ptMaxPosition.y; 01678 rc.right = rc.left + mmi.ptMaxSize.x; 01679 rc.bottom = rc.top + mmi.ptMaxSize.y; 01680 01681 SetWF(pwnd, WFMAXIMIZED); 01682 01683 } else { 01684 CopyRect(&rc, &rcRestore); 01685 ClrWF(pwnd, WFMAXIMIZED); 01686 } 01687 01688 /* 01689 * We do this TestWF again since we left the critical section 01690 * above and someone might have already 'un-minimized us'. 01691 */ 01692 if (TestWF(pwnd, WFMINIMIZED)) { 01693 01694 if (!TestWF(pwnd, WFWIN40COMPAT)) 01695 fIsTrayWindowNow = IsTrayWindow(pwnd); 01696 01697 /* 01698 * Mark it as minimized and adjust cVisWindows. 01699 */ 01700 SetMinimize(pwnd, SMIN_CLEAR); 01701 01702 uEvent = EVENT_SYSTEM_MINIMIZEEND; 01703 01704 /* 01705 * if we're unminimizing a window that is now 01706 * not seen in maximized/restore mode then remove him 01707 * from the tray 01708 */ 01709 if (!TestWF(pwnd, WFWIN40COMPAT) && 01710 (fIsTrayWindowNow != IsTrayWindow(pwnd)) && 01711 FDoTray()) { 01712 01713 HWND hw = HWq(pwnd); 01714 01715 if (FCallHookTray()) { 01716 xxxCallHook(HSHELL_WINDOWDESTROYED, 01717 (WPARAM)hw, 01718 (LPARAM)0, 01719 WH_SHELL); 01720 } 01721 01722 /* 01723 * NT specific code. Post the window-destroyed message 01724 * to the shell. 01725 */ 01726 if (FPostTray(pwnd->head.rpdesk)) 01727 PostShellHookMessages(HSHELL_WINDOWDESTROYED, (LPARAM)hw); 01728 } 01729 01730 fIsTrayWindowNow = FALSE; 01731 01732 /* 01733 * If we're un-minimizing a visible top-level window, cVisWindows 01734 * was zero, and we're either activating a window or showing 01735 * the currently active window, set ourselves into the 01736 * foreground. If the window isn't currently visible 01737 * then we can rely on SetWindowPos() to do the right 01738 * thing for us. 01739 */ 01740 if (!TestwndChild(pwnd) && 01741 TestWF(pwnd, WFVISIBLE) && 01742 (GETPTI(pwnd)->cVisWindows == 1) && 01743 (GETPTI(pwnd)->pq != gpqForeground) && 01744 (!(swpFlags & SWP_NOACTIVATE) 01745 || (GETPTI(pwnd)->pq->spwndActive == pwnd))) { 01746 01747 xxxSetForegroundWindow2(pwnd, GETPTI(pwnd), SFW_STARTUP); 01748 } 01749 } 01750 01751 /* 01752 * Ensure that client area gets recomputed, and that 01753 * the frame gets redrawn to reflect the new state. 01754 */ 01755 swpFlags |= SWP_DRAWFRAME; 01756 break; 01757 } 01758 01759 /* 01760 * For the iconic case, we need to also show the window because it 01761 * might not be visible yet. 01762 */ 01763 01764 Showit: 01765 01766 if (!(dwFlags & MINMAX_KEEPHIDDEN)) { 01767 01768 if (TestWF(pwnd, WFVISIBLE)) { 01769 01770 if (fShow) 01771 swpFlags |= SWP_SHOWWINDOW; 01772 01773 /* if we're full screening a DOS BOX then don't draw 01774 * the animation 'cause it looks bad. 01775 * overloaded WFFULLSCREEN bit for MDI child windows -- 01776 * use it to indicate to not animate size change. 01777 */ 01778 if (IsVisible(pwnd) && 01779 (dwFlags & MINMAX_ANIMATE) && 01780 idAnimation && 01781 (!TestWF(pwnd, WFCHILD) || !TestWF(pwnd, WFNOANIMATE))) { 01782 01783 #if defined(USE_MIRRORING) 01784 /* 01785 * If this top-level window is placed in a mirrored desktop, 01786 * its coordinates should be mirrored here so that xxxAnimateCaptions 01787 * works properly, however we shouldn't change the actual screen coordinates 01788 * of the window. This is why I do it here and restore it afterwards before 01789 * doing the _DeferWindowPos(...). [samera] 01790 */ 01791 RECT rcT; 01792 if (bMirroredParent) { 01793 int iLeft = rc.left; 01794 rcT = rc; 01795 rc.left = pwndParent->rcWindow.right - rc.right; 01796 rc.right = pwndParent->rcWindow.right - iLeft; 01797 } 01798 #endif 01799 01800 if ((idAnimation != IDANI_CAPTION) && IsTrayWindow(pwnd)) { 01801 01802 RECT rcMin; 01803 01804 SetRectEmpty(&rcMin); 01805 #if 0 // Win95 call. 01806 CallHook(HSHELL_GETMINRECT, (WPARAM)HW16(hwnd), (LPARAM)(LPRECT)&rcMin, WH_SHELL); 01807 #else 01808 xxxSendMinRectMessages(pwnd, &rcMin); 01809 #endif 01810 01811 if (!IsRectEmpty(&rcMin)) { 01812 01813 if (idAnimation == IDANI_CLOSE) { 01814 01815 xxxDrawAnimatedRects(pwnd, 01816 IDANI_CAPTION, 01817 &rcWindow, 01818 &rcMin); 01819 01820 } else { 01821 01822 xxxDrawAnimatedRects(pwnd, 01823 IDANI_CAPTION, 01824 &rcMin, 01825 &rc); 01826 } 01827 } 01828 01829 } else { 01830 xxxDrawAnimatedRects(pwnd, IDANI_CAPTION, &rcWindow, &rc); 01831 } 01832 01833 #if defined(USE_MIRRORING) 01834 /* 01835 * Restore the original rect, after doing the animation 01836 */ 01837 if (bMirroredParent) { 01838 rc = rcT; 01839 } 01840 #endif 01841 } 01842 01843 } else { 01844 swpFlags |= SWP_SHOWWINDOW; 01845 } 01846 } 01847 01848 /* 01849 * hack for VB - we add their window in when their minimizing. 01850 */ 01851 if (!TestWF(pwnd, WFWIN40COMPAT) && fIsTrayWindowNow && FDoTray()) { 01852 01853 HWND hw = HWq(pwnd); 01854 01855 if (FCallHookTray()) { 01856 xxxCallHook(HSHELL_WINDOWCREATED, 01857 (WPARAM)hw, 01858 (LPARAM)0, 01859 WH_SHELL); 01860 } 01861 01862 /* 01863 * NT specific code. Post the window-created message 01864 * to the shell. 01865 */ 01866 if (FPostTray(pwnd->head.rpdesk)) 01867 PostShellHookMessages(HSHELL_WINDOWCREATED, (LPARAM)hw); 01868 } 01869 01870 /* 01871 * BACKWARD COMPATIBILITY HACK: 01872 * 01873 * Because SetWindowPos() won't honor sizing, moving and SWP_SHOWWINDOW 01874 * at the same time in version 3.0 or below, we call DeferWindowPos() 01875 * directly here. 01876 */ 01877 if (psmwp = InternalBeginDeferWindowPos(1)) { 01878 01879 psmwp = _DeferWindowPos(psmwp, 01880 pwnd, 01881 ((hwndAfter != NULL) ? RevalidateHwnd(hwndAfter) : NULL), 01882 rc.left, rc.top, 01883 rc.right - rc.left, 01884 rc.bottom - rc.top, 01885 swpFlags); 01886 01887 if (psmwp) { 01888 01889 /* 01890 * HACK FOR MULTIPLE MONITOR TRUE MAXIMIZATION CLIPPING 01891 * On a multiple monitor system, we would like the 01892 * borders not to spill over onto another monitor when a 01893 * window 'really' maximizes. The only way to get this 01894 * to work right is to set a rectangular region, namely 01895 * a copy of the monitor region, on the window. We can 01896 * only do this if the window isn't currently regional. 01897 * 01898 * Going to maximized: Add the monitor region 01899 * Coming from maximized: Remove the monitor region 01900 */ 01901 if (fMaxStateChanging && gpDispInfo->cMonitors > 1) { 01902 if ( TestWF(pwnd, WFMAXIMIZED) && 01903 pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 01904 01905 psmwp->acvr[0].hrgnClip = HRGN_MONITOR; 01906 01907 } else if (TestWF(pwnd, WFMAXFAKEREGIONAL)) { 01908 UserAssert(pwnd->hrgnClip); 01909 psmwp->acvr[0].hrgnClip = HRGN_FULL; 01910 } 01911 } 01912 01913 xxxEndDeferWindowPosEx(psmwp, FALSE); 01914 } 01915 } 01916 01917 if (FWINABLE() && uEvent) { 01918 xxxWindowEvent(uEvent, pwnd, OBJID_WINDOW, 0, WEF_USEPWNDTHREAD); 01919 } 01920 01921 /* 01922 * COMPATIBILITY HACK: 01923 * Borland's OBEX expects a WM_PAINT message when it starts running 01924 * minimized and initializes all it's data during that message. 01925 * So, we generate a bogus WM_PAINT message here. 01926 * Also, Visionware's XServer can not handle getting a WM_PAINT msg, as it 01927 * would always get a WM_PAINTICON msg in 3.1, so make sure the logic is here 01928 * to generate the correct message. 01929 */ 01930 if((cmd == SW_SHOWMINIMIZED) && 01931 (!TestWF(pwnd, WFWIN40COMPAT)) && 01932 TestWF(pwnd, WFVISIBLE) && 01933 TestWF(pwnd, WFTOPLEVEL)) { 01934 01935 if (pwnd->pcls->spicn) 01936 _PostMessage(pwnd, WM_PAINTICON, (WPARAM)TRUE, 0L); 01937 else 01938 _PostMessage(pwnd, WM_PAINT, 0, 0L); 01939 } 01940 01941 if (fShowOwned) 01942 xxxShowOwnedWindows(pwnd, SW_PARENTOPENING, NULL); 01943 01944 if ((cmd == SW_MINIMIZE) && (pwnd->spwndParent == PWNDDESKTOP(pwnd))) { 01945 if (!xxxActivateOnMinimize(pwnd)) { 01946 xxxActivateWindow(pwnd, AW_SKIP); 01947 } 01948 01949 { 01950 PEPROCESS p; 01951 01952 if (gptiForeground && ptiCurrent->ppi != gptiForeground->ppi && !(ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD)) { 01953 01954 p = THREAD_TO_PROCESS(ptiCurrent->pEThread); 01955 KeAttachProcess(&p->Pcb); 01956 Status = MmAdjustWorkingSetSize((SIZE_T)-1, (SIZE_T)-1, FALSE); 01957 KeDetachProcess(); 01958 01959 if (!NT_SUCCESS(Status)) { 01960 RIPMSG1(RIP_ERROR, "Error adjusting working set, status = %x\n", Status); 01961 } 01962 } 01963 } 01964 01965 /* 01966 * If any app is starting, restore its right to foreground activate 01967 * (activate and come on top of everything else) because we just 01968 * minimized what we were working on. 01969 */ 01970 RestoreForegroundActivate(); 01971 } 01972 01973 /* 01974 * If going from iconic, insure the focus is in the window. 01975 */ 01976 if (fSetFocus) 01977 xxxSetFocus(pwnd); 01978 01979 /* 01980 * This was added for 1.03 compatibility reasons. If apps watch 01981 * WM_ACTIVATE to set their focus, sending this message will appear 01982 * as if the window just got activated (like in 1.03). Before this 01983 * was added, opening an iconic window never sent this message since 01984 * it was already active (but HIWORD(lParam) != 0). 01985 */ 01986 if (fSendActivate) 01987 xxxSendMessage(pwnd, WM_ACTIVATE, WA_ACTIVE, 0); 01988 01989 /* 01990 * Flush the palette. We do this on a minimize of a palette app. 01991 */ 01992 if (fFlushPalette) 01993 xxxFlushPalette(pwnd); 01994 01995 Exit: 01996 return NULL; 01997 }


Generated on Sat May 15 19:44:43 2004 for test by doxygen 1.3.7