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

mnsys.c

Go to the documentation of this file.
00001 /**************************** Module Header ********************************\ 00002 * Module Name: mnsys.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * System Menu Routines 00007 * 00008 * History: 00009 * 10-10-90 JimA Cleanup. 00010 * 03-18-91 IanJa Window revalidation added (none required) 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 void _SetCloseDefault(PMENU pSubMenu); 00017 PWND FindFakeMDIChild(PWND pwndParent); 00018 00019 /***************************************************************************\ 00020 * LoadSysDesktopMenu 00021 * 00022 * Loads and locks a desktop system menu. Since we have to call the client 00023 * to load the menu, while thread 1 is loading the menu, thread 2 00024 * might grab the critical section, check pdesk->spmenu* and decide that 00025 * the menu needs to be loaded. Hence we could load the menu more than once. 00026 * this function handles that case to avoid leaking menus. 00027 * 00028 * 10/24/97 Gerardob Created 00029 \***************************************************************************/ 00030 PMENU xxxLoadSysDesktopMenu (PMENU * ppmenu, UINT uMenuId) 00031 { 00032 PMENU pmenu; 00033 /* 00034 * This should only be called when the menu hasn't been loaded 00035 */ 00036 UserAssert(*ppmenu == NULL); 00037 00038 pmenu = xxxLoadSysMenu(uMenuId); 00039 if (pmenu == NULL) { 00040 return NULL; 00041 } 00042 /* 00043 * If someone beat us loading the menu, destroy this one 00044 * and return the one already loaded 00045 */ 00046 if (*ppmenu != NULL) { 00047 UserAssert(TestMF(*ppmenu, MFSYSMENU)); 00048 RIPMSG1(RIP_WARNING, 00049 "LoadSysDesktopMenu: Menu loaded during callback. ppmenu:%#p", 00050 ppmenu); 00051 _DestroyMenu(pmenu); 00052 return *ppmenu; 00053 } 00054 /* 00055 * Mark it, lock it and done 00056 */ 00057 SetMF(pmenu, MFSYSMENU); 00058 LockDesktopMenu(ppmenu, pmenu); 00059 return pmenu; 00060 } 00061 /***************************************************************************\ 00062 * Lock/UnlockDesktopMenu 00063 * 00064 * These functions lock/unlock a pmenu into a desktop structure (spmenuSys or 00065 * spmenuDialogSys) and mark/clear it as such. 00066 * We mark these menus so we can identify them quickly on single bit test. 00067 * We also don't want any one to modify these menus or any submenu. 00068 * 00069 * Note that this assumes that there is only one submenu. If more are added, 00070 * these functions have to be fixed accordingly. 00071 * 00072 * 08/18/97 Gerardob Created 00073 \***************************************************************************/ 00074 PVOID LockDesktopMenu(PMENU * ppmenu, PMENU pmenu) 00075 { 00076 PMENU pSubMenu; 00077 PTHREADINFO ptiDesktop; 00078 /* 00079 * We only load desktop sys menus once. 00080 */ 00081 UserAssert(*ppmenu == NULL); 00082 00083 if (pmenu == NULL) { 00084 return NULL; 00085 } 00086 00087 SetMF(pmenu, MFDESKTOP); 00088 /* 00089 * This is awful but this is the real owner of this object. We used to set it 00090 * to NULL but that was forcing us to handle the NULL owner all over the place 00091 */ 00092 ptiDesktop = PtiCurrent()->rpdesk->rpwinstaParent->pTerm->ptiDesktop; 00093 HMChangeOwnerProcess(pmenu, ptiDesktop); 00094 00095 pSubMenu = pmenu->rgItems->spSubMenu; 00096 UserAssert(pSubMenu != NULL); 00097 00098 SetMF(pSubMenu, MFDESKTOP); 00099 HMChangeOwnerProcess(pSubMenu, ptiDesktop); 00100 00101 #if DBG 00102 { 00103 /* 00104 * Assert that there are no other submenus that would need to be 00105 * marked as MFDESKTOP. 00106 */ 00107 PITEM pitem; 00108 UINT uItems; 00109 00110 UserAssert(pmenu->cItems == 1); 00111 00112 pitem = pSubMenu->rgItems; 00113 uItems = pSubMenu->cItems; 00114 while (uItems--) { 00115 UserAssert(pitem->spSubMenu == NULL); 00116 pitem++; 00117 } 00118 } 00119 #endif 00120 00121 return Lock(ppmenu, pmenu); 00122 } 00123 00124 PVOID UnlockDesktopMenu(PMENU * ppmenu) 00125 { 00126 UserAssert(*ppmenu != NULL); 00127 UserAssert(TestMF(*ppmenu, MFDESKTOP)); 00128 ClearMF(*ppmenu, MFDESKTOP); 00129 UserAssert(TestMF((*ppmenu)->rgItems->spSubMenu, MFDESKTOP)); 00130 ClearMF((*ppmenu)->rgItems->spSubMenu, MFDESKTOP); 00131 return Unlock(ppmenu); 00132 } 00133 /***************************************************************************\ 00134 * GetSysMenuHandle 00135 * 00136 * Returns a handle to the system menu of the given window. NULL if 00137 * the window doesn't have a system menu. 00138 * 00139 * History: 00140 \***************************************************************************/ 00141 00142 PMENU xxxGetSysMenuHandle( 00143 PWND pwnd) 00144 { 00145 PMENU pMenu; 00146 00147 CheckLock(pwnd); 00148 00149 if (TestWF(pwnd, WFSYSMENU)) { 00150 pMenu = pwnd->spmenuSys; 00151 00152 /* 00153 * If the window doesn't have a System Menu, use the default one. 00154 */ 00155 if (pMenu == NULL) { 00156 00157 /* 00158 * Grab the menu from the desktop. If the desktop menu 00159 * has not been loaded and this is not a system thread, 00160 * load it now. Callbacks cannot be made from a system 00161 * thread or when a thread is in cleanup. 00162 */ 00163 pMenu = pwnd->head.rpdesk->spmenuSys; 00164 00165 /* 00166 * Do not do callbacks if the thread is exiting. We ran into this when 00167 * destroying a thread's window and the window it was promoting to 00168 * foreground was a hard error popup. 00169 */ 00170 if (pMenu == NULL && !(PtiCurrent()->TIF_flags & (TIF_SYSTEMTHREAD | TIF_INCLEANUP))) { 00171 00172 pMenu = xxxLoadSysDesktopMenu (&pwnd->head.rpdesk->spmenuSys, ID_SYSMENU); 00173 } 00174 } 00175 } else { 00176 pMenu = NULL; 00177 } 00178 00179 return pMenu; 00180 } 00181 00182 /***************************************************************************\ 00183 * 00184 * GetSysMenu() 00185 * 00186 * Sets up the system menu first, then returns it. 00187 * 00188 \***************************************************************************/ 00189 PMENU xxxGetSysMenu(PWND pwnd, BOOL fSubMenu) 00190 { 00191 PMENU pMenu; 00192 00193 CheckLock(pwnd); 00194 xxxSetSysMenu(pwnd); 00195 if ((pMenu = xxxGetSysMenuHandle(pwnd)) != NULL) { 00196 if (fSubMenu) 00197 pMenu = _GetSubMenu(pMenu, 0); 00198 } 00199 00200 return(pMenu); 00201 } 00202 00203 /***************************************************************************\ 00204 * IsSmallerThanScreen 00205 * 00206 \***************************************************************************/ 00207 00208 BOOL IsSmallerThanScreen(PWND pwnd) 00209 { 00210 int dxMax, dyMax; 00211 PMONITOR pMonitor; 00212 00213 pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY); 00214 dxMax = pMonitor->rcWork.right - pMonitor->rcWork.left; 00215 dyMax = pMonitor->rcWork.bottom - pMonitor->rcWork.top; 00216 00217 if ((pwnd->rcWindow.right - pwnd->rcWindow.left < dxMax) || 00218 (pwnd->rcWindow.bottom - pwnd->rcWindow.top < dyMax)) { 00219 return TRUE; 00220 } 00221 return FALSE; 00222 } 00223 00224 /***************************************************************************\ 00225 * SetSysMenu 00226 * 00227 * ! 00228 * 00229 * History: 00230 \***************************************************************************/ 00231 00232 void xxxSetSysMenu( 00233 PWND pwnd) 00234 { 00235 PMENU pMenu; 00236 UINT wSize; 00237 UINT wMinimize; 00238 UINT wMaximize; 00239 UINT wMove; 00240 UINT wRestore; 00241 UINT wDefault; 00242 BOOL fFramedDialogBox; 00243 TL tlmenu; 00244 00245 CheckLock(pwnd); 00246 /* 00247 * Get the handle of the current system menu. 00248 */ 00249 if ((pMenu = xxxGetSysMenuHandle(pwnd)) != NULL) { 00250 00251 pMenu = _GetSubMenu(pMenu, 0); 00252 if (!pMenu) 00253 return; 00254 00255 ThreadLockAlways(pMenu, &tlmenu); 00256 00257 /* 00258 * System modal window: no size, icon, zoom, or move. 00259 */ 00260 00261 // No system modal windows on NT. 00262 // wSize = wMaximize = wMinimize = wMove = 00263 // (UINT)((_GetSysModalWindow() == NULL) || hTaskLockInput ? 0: MFS_GRAYED); 00264 wSize = wMaximize = wMinimize = wMove = 0; 00265 wRestore = MFS_GRAYED; 00266 00267 // 00268 // Default menu command is close. 00269 // 00270 wDefault = SC_CLOSE; 00271 00272 /* 00273 * Minimized exceptions: no minimize, restore. 00274 */ 00275 00276 // we need to reverse these because VB has a "special" window 00277 // that is both minimized but without a minbox. 00278 if (TestWF(pwnd, WFMINIMIZED)) 00279 { 00280 wRestore = 0; 00281 wMinimize = MFS_GRAYED; 00282 wSize = MFS_GRAYED; 00283 wDefault = SC_RESTORE; 00284 00285 if (IsTrayWindow(pwnd)) 00286 wMove = MFS_GRAYED; 00287 } 00288 else if (!TestWF(pwnd, WFMINBOX)) 00289 wMinimize = MFS_GRAYED; 00290 00291 /* 00292 * Maximized exceptions: no maximize, restore. 00293 */ 00294 if (!TestWF(pwnd, WFMAXBOX)) 00295 wMaximize = MFS_GRAYED; 00296 else if (TestWF(pwnd, WFMAXIMIZED)) { 00297 wRestore = 0; 00298 00299 /* 00300 * If the window is maximized but it isn't larger than the 00301 * screen, we allow the user to move the window around the 00302 * desktop (but we don't allow resizing). 00303 */ 00304 wMove = MFS_GRAYED; 00305 if (!TestWF(pwnd, WFCHILD)) { 00306 if (IsSmallerThanScreen(pwnd)) { 00307 wMove = 0; 00308 } 00309 } 00310 00311 wSize = MFS_GRAYED; 00312 wMaximize = MFS_GRAYED; 00313 } 00314 00315 if (!TestWF(pwnd, WFSIZEBOX)) 00316 wSize = MFS_GRAYED; 00317 00318 /* 00319 * Are we dealing with a framed dialog box with a sys menu? 00320 * Dialogs with min/max/size boxes get a regular system menu 00321 * (as opposed to the dialog menu) 00322 */ 00323 fFramedDialogBox = 00324 (((TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFDLGFRAME)) 00325 || (TestWF(pwnd, WEFDLGMODALFRAME))) 00326 && !TestWF(pwnd, WFSIZEBOX | WFMINBOX | WFMAXBOX)); 00327 00328 if (!fFramedDialogBox) { 00329 xxxEnableMenuItem(pMenu, (UINT)SC_SIZE, wSize); 00330 if (!TestWF(pwnd, WEFTOOLWINDOW)) 00331 { 00332 xxxEnableMenuItem(pMenu, (UINT)SC_MINIMIZE, wMinimize); 00333 xxxEnableMenuItem(pMenu, (UINT)SC_MAXIMIZE, wMaximize); 00334 xxxEnableMenuItem(pMenu, (UINT)SC_RESTORE, wRestore); 00335 } 00336 } 00337 00338 xxxEnableMenuItem(pMenu, (UINT)SC_MOVE, wMove); 00339 00340 #if DBG 00341 /* 00342 * Assert that nobody managed to change the desktop menus. 00343 */ 00344 if (TestMF(pMenu, MFSYSMENU)) { 00345 PITEM pItem = MNLookUpItem(pMenu, SC_CLOSE, FALSE, NULL); 00346 UserAssert((pItem != NULL) && !TestMFS(pItem, MFS_GRAYED)); 00347 } 00348 #endif 00349 00350 if (wDefault == SC_CLOSE) 00351 _SetCloseDefault(pMenu); 00352 else 00353 _SetMenuDefaultItem(pMenu, wDefault, MF_BYCOMMAND); 00354 00355 ThreadUnlock(&tlmenu); 00356 } 00357 } 00358 00359 00360 /***************************************************************************\ 00361 * GetSystemMenu 00362 * 00363 * ! 00364 * 00365 * History: 00366 \***************************************************************************/ 00367 00368 PMENU xxxGetSystemMenu( 00369 PWND pwnd, 00370 BOOL fRevert) 00371 { 00372 PMENU pmenu; 00373 CheckLock(pwnd); 00374 00375 /* 00376 * Should we start with a fresh copy? 00377 */ 00378 00379 pmenu = pwnd->spmenuSys; 00380 if (fRevert) { 00381 00382 /* 00383 * Destroy the old system menu. 00384 */ 00385 if ((pmenu != NULL) && !TestMF(pmenu, MFSYSMENU)) { 00386 00387 if (UnlockWndMenu(pwnd, &pwnd->spmenuSys)) { 00388 _DestroyMenu(pmenu); 00389 } 00390 } 00391 } else { 00392 00393 /* 00394 * Do we need to load a new system menu? 00395 */ 00396 if (((pmenu == NULL) || TestMF(pmenu, MFSYSMENU)) 00397 && TestWF(pwnd, WFSYSMENU)) { 00398 00399 PPOPUPMENU pGlobalPopupMenu; 00400 UINT uMenuId = (pwnd->spmenuSys == NULL ? ID_SYSMENU : ID_DIALOGSYSMENU); 00401 pmenu = xxxLoadSysMenu(uMenuId); 00402 if (pmenu == NULL) { 00403 RIPMSG1(RIP_WARNING, "_GetSystemMenu: xxxLoadSysMenu Failed. pwnd:%#p", pwnd); 00404 } 00405 LockWndMenu(pwnd, &pwnd->spmenuSys, pmenu); 00406 00407 pmenu = pwnd->spmenuSys; 00408 pGlobalPopupMenu = GetpGlobalPopupMenu(pwnd); 00409 if ((pGlobalPopupMenu != NULL) 00410 && !pGlobalPopupMenu->fIsTrackPopup 00411 && (pGlobalPopupMenu->spwndPopupMenu == pwnd)) { 00412 00413 UserAssert(pGlobalPopupMenu->spwndNotify == pwnd); 00414 if (pGlobalPopupMenu->fIsSysMenu) { 00415 Lock(&pGlobalPopupMenu->spmenu, pmenu); 00416 } else { 00417 Lock(&pGlobalPopupMenu->spmenuAlternate, pmenu); 00418 } 00419 } 00420 } 00421 } 00422 00423 /* 00424 * Return the handle to the system menu. 00425 */ 00426 if (pwnd->spmenuSys != NULL) { 00427 /* 00428 * The app is probably going to modify this menu and then we'll need to 00429 * redraw the caption buttons. Hence we need to store the window pointer 00430 * in this pmenu or we won't be able to know what window to repaint. 00431 * The bogus thing is that we cannot call LockWndMenu here because this is 00432 * not the actual pmenuSys. 00433 */ 00434 pmenu = _GetSubMenu(pwnd->spmenuSys, 0); 00435 if (pmenu) { 00436 SetMF(pmenu, MFAPPSYSMENU); 00437 Lock(&pmenu->spwndNotify, pwnd); 00438 } 00439 return pmenu; 00440 } 00441 00442 return NULL; 00443 } 00444 00445 /***************************************************************************\ 00446 * MenuItemState 00447 * 00448 * Sets the menu item flags identified by wMask to the states identified 00449 * by wFlags. 00450 * 00451 * History: 00452 * 10-11-90 JimA Translated from ASM 00453 \***************************************************************************/ 00454 00455 DWORD MenuItemState( 00456 PMENU pMenu, 00457 UINT wCmd, 00458 DWORD wFlags, 00459 DWORD wMask, 00460 PMENU *ppMenu) 00461 { 00462 PITEM pItem; 00463 DWORD wRet; 00464 00465 /* 00466 * Get a pointer the the menu item 00467 */ 00468 if ((pItem = MNLookUpItem(pMenu, wCmd, (BOOL) (wFlags & MF_BYPOSITION), ppMenu)) == NULL) 00469 return (DWORD)-1; 00470 00471 /* 00472 * Return previous state 00473 */ 00474 wRet = pItem->fState & wMask; 00475 00476 /* 00477 * Set new state 00478 */ 00479 pItem->fState ^= ((wRet ^ wFlags) & wMask); 00480 00481 return wRet; 00482 } 00483 00484 00485 /***************************************************************************\ 00486 * EnableMenuItem 00487 * 00488 * Enable, disable or gray a menu item. 00489 * 00490 * History: 00491 * 10-11-90 JimA Translated from ASM 00492 \***************************************************************************/ 00493 00494 DWORD xxxEnableMenuItem( 00495 PMENU pMenu, 00496 UINT wIDEnableItem, 00497 UINT wEnable) 00498 { 00499 DWORD dres; 00500 PMENU pRealMenu; 00501 PPOPUPMENU ppopup; 00502 00503 CheckLock(pMenu); 00504 00505 dres = MenuItemState(pMenu, wIDEnableItem, wEnable, 00506 MFS_GRAYED, &pRealMenu); 00507 00508 /* 00509 * If enabling/disabling a system menu item, redraw the caption buttons 00510 */ 00511 if (TestMF(pMenu, MFAPPSYSMENU) && (pMenu->spwndNotify != NULL)) { 00512 00513 TL tlpwnd; 00514 00515 switch (wIDEnableItem) { 00516 case SC_SIZE: 00517 case SC_MOVE: 00518 case SC_MINIMIZE: 00519 case SC_MAXIMIZE: 00520 case SC_CLOSE: 00521 case SC_RESTORE: 00522 ThreadLock(pMenu->spwndNotify, &tlpwnd); 00523 xxxRedrawTitle(pMenu->spwndNotify, DC_BUTTONS); 00524 ThreadUnlock(&tlpwnd); 00525 } 00526 } 00527 00528 /* 367162: If the menu is already being displayed we need to redraw it */ 00529 if(pRealMenu && (ppopup = MNGetPopupFromMenu(pRealMenu, NULL))){ 00530 xxxMNUpdateShownMenu(ppopup, NULL, MNUS_DEFAULT); 00531 } 00532 00533 return dres; 00534 } 00535 00536 00537 /***************************************************************************\ 00538 * CheckMenuItem (API) 00539 * 00540 * Check or un-check a popup menu item. 00541 * 00542 * History: 00543 * 10-11-90 JimA Translated from ASM 00544 \***************************************************************************/ 00545 00546 DWORD _CheckMenuItem( 00547 PMENU pMenu, 00548 UINT wIDCheckItem, 00549 UINT wCheck) 00550 { 00551 return MenuItemState(pMenu, wIDCheckItem, wCheck, (UINT)MF_CHECKED, NULL); 00552 } 00553 00554 00555 /***************************************************************************\ 00556 * 00557 * SetMenuDefaultItem() - 00558 * 00559 * Sets the default item in the menu, by command or by position based on the 00560 * fByPosition flag. 00561 * We unset all the other items as the default, then set the given one. 00562 * 00563 * The return value is TRUE if the given item was set as default, FALSE 00564 * if not. 00565 * 00566 \***************************************************************************/ 00567 BOOL _SetMenuDefaultItem(PMENU pMenu, UINT wID, BOOL fByPosition) 00568 { 00569 UINT iItem; 00570 UINT cItems; 00571 PITEM pItem; 00572 PITEM pItemFound; 00573 PMENU pMenuFound; 00574 00575 // 00576 // We need to check if wId actually exists on this menu. 0xFFFF means 00577 // clear all default items. 00578 // 00579 00580 if (wID != MFMWFP_NOITEM) 00581 { 00582 pItemFound = MNLookUpItem(pMenu, wID, fByPosition, &pMenuFound); 00583 00584 // item must be on same menu and can't be a separator 00585 if ((pItemFound == NULL) || (pMenuFound != pMenu) || TestMFT(pItemFound, MFT_SEPARATOR)) 00586 return(FALSE); 00587 00588 } 00589 else 00590 pItemFound = NULL; 00591 00592 pItem = pMenu->rgItems; 00593 cItems = pMenu->cItems; 00594 00595 // Walk the menu list, clearing MFS_DEFAULT from all other items, and 00596 // setting MFS_DEFAULT on the requested one. 00597 for (iItem = 0; iItem < cItems; iItem++, pItem++) { 00598 // 00599 // Note we don't change the state of lpItemFound if it exists. This 00600 // is so that below, where we try to set the default, we can tell 00601 // if we need to recalculate the underline. 00602 // 00603 00604 if (TestMFS(pItem, MFS_DEFAULT) && (pItem != pItemFound)) 00605 { 00606 // 00607 // We are changing the default item. As such, it will be drawn 00608 // with a different font than the one used to calculate it, if 00609 // the menu has already been drawn once. We need to ensure 00610 // that the underline gets drawn in the right place the next 00611 // time the menu comes up. Cause it to recalculate. 00612 // 00613 // We do NOT do this if the item 00614 // (a) isn't default--otherwise we'll recalculate the 00615 // underline for every system menu item every time we go into 00616 // menu mode because sysmenu init will call SetMenuDefaultItem. 00617 // (b) isn't the item we're going to set as the default. 00618 // That way we don't recalculate the underline when the item 00619 // isn't changing state. 00620 // 00621 ClearMFS(pItem, MFS_DEFAULT); 00622 pItem->ulX = UNDERLINE_RECALC; 00623 pItem->ulWidth = 0; 00624 } 00625 } 00626 00627 if (wID != MFMWFP_NOITEM) 00628 { 00629 if (!TestMFS(pItemFound, MFS_DEFAULT)) 00630 { 00631 // 00632 // We are changing from non-default to default. Clear out 00633 // the underline info. If the menu has never painted, this 00634 // won't do anything. But it matters a lot if it has. 00635 // 00636 SetMFS(pItemFound, MFS_DEFAULT); 00637 pItemFound->ulX = UNDERLINE_RECALC; 00638 pItemFound->ulWidth = 0; 00639 } 00640 } 00641 00642 return(TRUE); 00643 } 00644 00645 // -------------------------------------------------------------------------- 00646 // 00647 // SetCloseDefault() 00648 // 00649 // Tries to find a close item in the first level of menu items. Looks 00650 // for SC_CLOSE, then a couple other IDs. We'd rather not do lstrstri's 00651 // for "Close", which is slow. 00652 // 00653 // -------------------------------------------------------------------------- 00654 void _SetCloseDefault(PMENU pSubMenu) 00655 { 00656 if (!_SetMenuDefaultItem(pSubMenu, SC_CLOSE, MF_BYCOMMAND)) 00657 { 00658 // 00659 // Bloody hell. Let's try a couple other values. 00660 // * Project -- 0x7000 less 00661 // * FoxPro -- 0xC070 00662 // 00663 if (!_SetMenuDefaultItem(pSubMenu, SC_CLOSE - 0x7000, MF_BYCOMMAND)) 00664 _SetMenuDefaultItem(pSubMenu, 0xC070, MF_BYCOMMAND); 00665 } 00666 } 00667 00668 00669 // -------------------------------------------------------------------------- 00670 // 00671 // FindFakeMDIChild() 00672 // 00673 // Attempts to find first child visible child window in the zorder that 00674 // has a system menu or is maxed. We can't check for an exact system 00675 // menu match because several apps make their own copy of the sys menu. 00676 // 00677 // -------------------------------------------------------------------------- 00678 PWND FindFakeMDIChild(PWND pwnd) 00679 { 00680 PWND pwndReturn; 00681 00682 // Skip invisible windows and their descendants 00683 if (!TestWF(pwnd, WFVISIBLE)) 00684 return(NULL); 00685 00686 // Did we hit pay dirt? 00687 if (TestWF(pwnd, WFCHILD) && (TestWF(pwnd, WFMAXIMIZED) || (pwnd->spmenuSys))) 00688 return(pwnd); 00689 00690 // Check our children 00691 for (pwnd = pwnd->spwndChild; pwnd; pwnd = pwnd->spwndNext) 00692 { 00693 pwndReturn = FindFakeMDIChild(pwnd); 00694 if (pwndReturn) 00695 return(pwndReturn); 00696 } 00697 00698 return(NULL); 00699 } 00700 00701 00702 00703 // -------------------------------------------------------------------------- 00704 // 00705 // SetupFakeMDIAppStuff() 00706 // 00707 // For apps that dork around with their own MDI (Excel, Word, Project, 00708 // Quattro Pro), we want to make them a little more Chicago friendly. 00709 // Namely we: 00710 // 00711 // (1) Set the default menu item to SC_CLOSE if there isn't one (this 00712 // won't help FoxPro, but they do so much wrong stuff it doesn't 00713 // really matter). 00714 // That way double-clicks will still work. 00715 // 00716 // (2) Get the right small icon. 00717 // 00718 // The way we do this is to go find the child window of the menu bar parent 00719 // who has a system menu that is this one. 00720 // 00721 // If the system menu is the standard one, then we can't do (2). 00722 // 00723 // -------------------------------------------------------------------------- 00724 void SetupFakeMDIAppStuff(PMENU lpMenu, PITEM lpItem) 00725 { 00726 PMENU pSubMenu; 00727 PWND pwndParent; 00728 PWND pwndChild; 00729 00730 if (!(pSubMenu = lpItem->spSubMenu)) 00731 return; 00732 00733 pwndParent = lpMenu->spwndNotify; 00734 00735 // 00736 // Set up the default menu item. Project and FoxPro renumber their 00737 // IDs so we do some special stuff for them, among others. 00738 // 00739 if (!TestWF(pwndParent, WFWIN40COMPAT)) 00740 { 00741 if (_GetMenuDefaultItem(pSubMenu, TRUE, GMDI_USEDISABLED) == -1L) 00742 _SetCloseDefault(pSubMenu); 00743 } 00744 00745 // 00746 // Don't touch the HIWORD if we don't find an HWND. That way apps 00747 // like Excel which have starting-up maxed children can benefit a little. 00748 // The first time the menu bar is redrawn, the child isn't visible/ 00749 // around (they add the item too early). But if it redraws later, or 00750 // you max a child, the icon will kick in. 00751 // 00752 if (pwndChild = FindFakeMDIChild(pwndParent)) { 00753 lpItem->dwItemData = (ULONG_PTR)HWq(pwndChild); 00754 // lpItem->dwTypeData = MAKELONG(LOWORD(lpItem->dwTypeData), HW16(hwndChild)); 00755 } 00756 }

Generated on Sat May 15 19:40:52 2004 for test by doxygen 1.3.7