|
|
/**************************** Module Header ********************************\
* Module Name: mnstate.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Menu State Routines * * History: * 10-10-90 JimA Cleanup. * 03-18-91 IanJa Windowrevalidation added \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
PMENU xxxGetInitMenuParam(PWND pwndMenu, BOOL *lpfSystem);
/***************************************************************************\
* MNPositionSysMenu * * History: * 4-25-91 Mikehar Port for 3.1 merge \***************************************************************************/ VOID MNPositionSysMenu( PWND pwnd, PMENU pmenusys) { RECT rc; PITEM pItem;
if (pmenusys == NULL) { RIPERR0(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid menu handle pmenusys (NULL) to MNPositionSysMenu");
return; }
/*
* Whoever positions the menu becomes the owner */ if (pwnd != pmenusys->spwndNotify) { Lock(&pmenusys->spwndNotify, pwnd); }
/*
* Setup the SysMenu hit rectangle. */ rc.top = rc.left = 0;
if (TestWF(pwnd, WEFTOOLWINDOW)) { rc.right = SYSMET(CXSMSIZE); rc.bottom = SYSMET(CYSMSIZE); } else { rc.right = SYSMET(CXSIZE); rc.bottom = SYSMET(CYSIZE); }
if (!TestWF(pwnd, WFMINIMIZED)) { int cBorders;
cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); OffsetRect(&rc, cBorders*SYSMET(CXBORDER), cBorders*SYSMET(CYBORDER)); }
/*
* Offset the System popup menu. */ if (!TestMF(pmenusys, MF_POPUP) && (pmenusys->cItems > 0)) { pItem = pmenusys->rgItems; if (pItem) { pItem->yItem = rc.top; pItem->xItem = rc.left; pItem->cyItem = rc.bottom - rc.top; pItem->cxItem = rc.right - rc.left; } } else { // BOGUS -- MF_POPUP should never be set on a MENU -- only a MENU ITEM
RIPMSG1(RIP_ERROR, "pmenu %#p has MF_POPUP set or 0 items", pmenusys); } }
/***************************************************************************\
* MNFlushDestroyedPopups * * Walk the ppmDelayedFree list freeing those marked as destroyed. * * 05-14-96 GerardoB Created \***************************************************************************/ VOID MNFlushDestroyedPopups( PPOPUPMENU ppopupmenu, BOOL fUnlock) { PPOPUPMENU ppmDestroyed, ppmFree;
UserAssert(IsRootPopupMenu(ppopupmenu));
/*
* Walk ppmDelayedFree */ ppmDestroyed = ppopupmenu; while (ppmDestroyed->ppmDelayedFree != NULL) { /*
* If it's marked as destroyed, unlink it and free it */ if (ppmDestroyed->ppmDelayedFree->fDestroyed) { ppmFree = ppmDestroyed->ppmDelayedFree; ppmDestroyed->ppmDelayedFree = ppmFree->ppmDelayedFree; UserAssert(ppmFree != ppmFree->ppopupmenuRoot); MNFreePopup(ppmFree); } else { /*
* fUnlock is TRUE if the root popup is being destroyed; if * so, reset fDelayedFree and unlink it. */ if (fUnlock) { /*
* This means that the root popup is going away before * some of the hierarchical popups have been destroyed. * * This can happen if someone destroys one of the menu * windows breaking the spwndNextPopup chain. */ ppmDestroyed->ppmDelayedFree->fDelayedFree = FALSE;
/*
* Stop here so we can figure how this happened. */ UserAssert(ppmDestroyed->ppmDelayedFree->fDelayedFree); ppmDestroyed->ppmDelayedFree = ppmDestroyed->ppmDelayedFree->ppmDelayedFree; } else { /*
* Not fDestroyed so move to the next one. */ ppmDestroyed = ppmDestroyed->ppmDelayedFree; } } } }
/***************************************************************************\
* MNAllocPopup * \***************************************************************************/ PPOPUPMENU MNAllocPopup( BOOL fForceAlloc) { PPOPUPMENU ppm;
if (!fForceAlloc && !TEST_PUDF(PUDF_POPUPINUSE)) { SET_PUDF(PUDF_POPUPINUSE); ppm = &gpopupMenu; } else { ppm = (PPOPUPMENU)UserAllocPoolWithQuota(sizeof(POPUPMENU), TAG_POPUPMENU); }
if (ppm) { RtlZeroMemory(ppm, sizeof(POPUPMENU)); }
return ppm; }
/***************************************************************************\
* MNFreePopup * \***************************************************************************/ VOID MNFreePopup( PPOPUPMENU ppopupmenu) { Validateppopupmenu(ppopupmenu);
if (IsRootPopupMenu(ppopupmenu)) { MNFlushDestroyedPopups(ppopupmenu, TRUE); }
if (ppopupmenu->spwndPopupMenu && GETFNID(ppopupmenu->spwndPopupMenu) == FNID_MENU && ppopupmenu != &gpopupMenu) { ((PMENUWND)ppopupmenu->spwndPopupMenu)->ppopupmenu = NULL; }
Unlock(&ppopupmenu->spwndPopupMenu); /*
* If spwndNextPopup is not NULL, we're breaking the chain and spwndNext * won't get closed. I won't remove the unlock since it has always been * there. */ UserAssert(ppopupmenu->spwndNextPopup == NULL); Unlock(&ppopupmenu->spwndNextPopup);
Unlock(&ppopupmenu->spwndPrevPopup); UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenu); UnlockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate); Unlock(&ppopupmenu->spwndNotify); Unlock(&ppopupmenu->spwndActivePopup);
#if DBG
ppopupmenu->fFreed = TRUE; #endif
if (ppopupmenu == &gpopupMenu) { UserAssert(TEST_PUDF(PUDF_POPUPINUSE)); CLEAR_PUDF(PUDF_POPUPINUSE); } else { UserFreePool(ppopupmenu); } }
/***************************************************************************\
* MNEndMenuStateNotify * * spwndNotify might have been created by a thread other than the one * the menu mode is running on. If this is the case, this function * NULLs out pMenuState for the thread that owns spwndNotify. * * It returns TRUE if the menu state owner doesn't own the notification * window (multiple threads involved). * * 05-21-96 GerardoB Created \***************************************************************************/ BOOL MNEndMenuStateNotify( PMENUSTATE pMenuState) { PTHREADINFO ptiNotify;
if (pMenuState->pGlobalPopupMenu->spwndNotify != NULL) { ptiNotify = GETPTI(pMenuState->pGlobalPopupMenu->spwndNotify); if (ptiNotify != pMenuState->ptiMenuStateOwner) { /*
* Later5.0 GerardoB. xxxMNStartMenuState no longer allows this. * This is dead code that I'll remove eventually */ UserAssert(ptiNotify == pMenuState->ptiMenuStateOwner);
UserAssert(ptiNotify->pMenuState == pMenuState); UserAssert(pMenuState->pmnsPrev == NULL); ptiNotify->pMenuState = NULL; return TRUE; } }
return FALSE; }
/***************************************************************************\
* xxxMNEndMenuState * * This funtion must be called to clean up pMenuState after getting out * of menu mode. It must be called by the same thread that initialized * pMenuState either manually or by calling xxxMNStartMenuState. * * 05-20-96 GerardoB Created \***************************************************************************/ VOID xxxMNEndMenuState( BOOL fFreePopup) { PTHREADINFO ptiCurrent = PtiCurrent(); PMENUSTATE pMenuState; pMenuState = ptiCurrent->pMenuState; UserAssert(ptiCurrent->pMenuState != NULL); UserAssert(ptiCurrent == pMenuState->ptiMenuStateOwner);
/*
* If the menu is locked, someone doesn't want it to go just yet. */ if (pMenuState->dwLockCount != 0) { RIPMSG1(RIP_WARNING, "xxxMNEndMenuState Locked:%#p", pMenuState); return; }
MNEndMenuStateNotify(pMenuState);
/*
* pMenuState->pGlobalPopupMenu could be NULL if xxxMNAllocMenuState failed */ if (pMenuState->pGlobalPopupMenu != NULL) { if (fFreePopup) { UserAssert(pMenuState->pGlobalPopupMenu->fIsMenuBar || pMenuState->pGlobalPopupMenu->fDestroyed);
MNFreePopup(pMenuState->pGlobalPopupMenu); } else { /*
* This means that we're ending the menustate but the popup menu * window is still around. This can happen when called from * xxxDestroyThreadInfo. */ UserAssert(pMenuState->pGlobalPopupMenu->fIsTrackPopup); pMenuState->pGlobalPopupMenu->fDelayedFree = FALSE; } }
/*
* Unlock MFMWFP windows. */ UnlockMFMWFPWindow(&pMenuState->uButtonDownHitArea); UnlockMFMWFPWindow(&pMenuState->uDraggingHitArea);
/*
* Restore the previous state, if any */ ptiCurrent->pMenuState = pMenuState->pmnsPrev;
/*
* This (modal) menu mode is off */ if (!pMenuState->fModelessMenu) { DecSFWLockCount(); DBGDecModalMenuCount(); }
if (pMenuState->hbmAni != NULL) { MNDestroyAnimationBitmap(pMenuState); }
/*
* Free the menu state */ if (pMenuState == &gMenuState) { UserAssert(TEST_PUDF(PUDF_MENUSTATEINUSE)); CLEAR_PUDF(PUDF_MENUSTATEINUSE); GreSetDCOwner(gMenuState.hdcAni, OBJECT_OWNER_PUBLIC); } else { if (pMenuState->hdcAni != NULL) { GreDeleteDC(pMenuState->hdcAni); } UserFreePool(pMenuState); }
/*
* If returning to a modeless menu, make sure we have activation. * If returning to a modal menu, make sure we have capture. */ if (ptiCurrent->pMenuState != NULL) { if (ptiCurrent->pMenuState->fModelessMenu) { xxxActivateThisWindow(ptiCurrent->pMenuState->pGlobalPopupMenu->spwndActivePopup, 0, 0); } else { xxxMNSetCapture(ptiCurrent->pMenuState->pGlobalPopupMenu); } }
#if DBG
/*
* No pti should point to this pMenuState anymore. * If guModalMenuStateCount is zero, all pMenuState must be NULL or * modeless. */ { PLIST_ENTRY pHead, pEntry; PTHREADINFO ptiT;
pHead = &(ptiCurrent->rpdesk->PtiList); for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { ptiT = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); UserAssert(ptiT->pMenuState != pMenuState); if (guModalMenuStateCount == 0) { UserAssert(ptiT->pMenuState == NULL || ptiT->pMenuState->fModelessMenu); } } } #endif
}
/***************************************************************************\
* MNCreateAnimationBitmap * \***************************************************************************/ BOOL MNCreateAnimationBitmap( PMENUSTATE pMenuState, UINT cx, UINT cy) { HBITMAP hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, cx, cy); if (hbm == NULL) { RIPMSG0(RIP_WARNING, "MNSetupAnimationBitmap: Failed to create hbmAni"); return FALSE; }
#if DBG
if (pMenuState->hdcAni == NULL) { RIPMSG0(RIP_WARNING, "MNCreateAnimationBitmap: hdcAni is NULL"); } if (pMenuState->hbmAni != NULL) { RIPMSG0(RIP_WARNING, "MNCreateAnimationBitmap: hbmAni already exists"); } #endif // DBG
GreSelectBitmap(pMenuState->hdcAni, hbm); pMenuState->hbmAni = hbm; return TRUE; }
/***************************************************************************\
* MNDestroyAnimationBitmap * \***************************************************************************/ VOID MNDestroyAnimationBitmap( PMENUSTATE pMenuState) { GreSelectBitmap(pMenuState->hdcAni, GreGetStockObject(PRIV_STOCK_BITMAP)); UserVerify(GreDeleteObject(pMenuState->hbmAni)); pMenuState->hbmAni = NULL; }
/***************************************************************************\
* MNSetupAnimationDC * * 9/20/96 GerardoB Created \***************************************************************************/ BOOL MNSetupAnimationDC( PMENUSTATE pMenuState) { pMenuState->hdcAni = GreCreateCompatibleDC(gpDispInfo->hdcScreen); if (pMenuState->hdcAni == NULL) { RIPMSG0(RIP_WARNING, "MNSetupAnimationDC: Failed to create hdcAnimate"); UserAssert(pMenuState != &gMenuState); return FALSE; } GreSelectFont(pMenuState->hdcAni, ghMenuFont); return TRUE; }
/***************************************************************************\
* xxxUnlockMenuState * * 11/24/96 GerardoB Created \***************************************************************************/ BOOL xxxUnlockMenuState( PMENUSTATE pMenuState) { UserAssert(pMenuState->dwLockCount != 0);
(pMenuState->dwLockCount)--; if ((pMenuState->dwLockCount == 0) && ExitMenuLoop(pMenuState, pMenuState->pGlobalPopupMenu)) { xxxMNEndMenuState(TRUE); return TRUE; }
return FALSE; }
/***************************************************************************\
* xxxMNAllocMenuState * * Allocates and initializes a pMenuState. * * 5-21-96 GerardoB Created \***************************************************************************/ PMENUSTATE xxxMNAllocMenuState( PTHREADINFO ptiCurrent, PTHREADINFO ptiNotify, PPOPUPMENU ppopupmenuRoot) { BOOL fAllocate; PMENUSTATE pMenuState;
UserAssert(PtiCurrent() == ptiCurrent); UserAssert(ptiCurrent->rpdesk == ptiNotify->rpdesk);
/*
* If gMenuState is already taken, allocate one. */ fAllocate = TEST_PUDF(PUDF_MENUSTATEINUSE); if (fAllocate) { pMenuState = (PMENUSTATE)UserAllocPoolWithQuota(sizeof(MENUSTATE), TAG_MENUSTATE); if (pMenuState == NULL) { return NULL; } } else { /*
* Use chache global which already has the animation DC setup */ SET_PUDF(PUDF_MENUSTATEINUSE); pMenuState = &gMenuState; UserAssert(gMenuState.hdcAni != NULL); GreSetDCOwner(gMenuState.hdcAni, OBJECT_OWNER_CURRENT); }
/*
* Prevent anyone from changing the foreground while this menu is active */ IncSFWLockCount(); DBGIncModalMenuCount();
/*
* Initialize pMenuState. * Animation DC stuff is already setup so don't zero init it. */ RtlZeroMemory(pMenuState, sizeof(MENUSTATE) - sizeof(MENUANIDC)); pMenuState->pGlobalPopupMenu = ppopupmenuRoot; pMenuState->ptiMenuStateOwner = ptiCurrent;
/*
* Save previous state, if any. Then set new state. */ pMenuState->pmnsPrev = ptiCurrent->pMenuState; ptiCurrent->pMenuState = pMenuState;
if (ptiNotify != ptiCurrent) { UserAssert(ptiNotify->pMenuState == NULL); ptiNotify->pMenuState = pMenuState; }
/*
* If the menustate was allocated, set up animation stuff. * This is done here because in case of failure, MNEndMenuState * will find ptiCurrent->pMenuState properly. */ if (fAllocate) { RtlZeroMemory((PBYTE)pMenuState + sizeof(MENUSTATE) - sizeof(MENUANIDC), sizeof(MENUANIDC)); if (!MNSetupAnimationDC(pMenuState)) { xxxMNEndMenuState(TRUE); return NULL; } }
return pMenuState; }
/***************************************************************************\
* xxxMNStartMenuState * * This function is called when the menu bar is about to be activated (the * app's main menu). It makes sure that the threads involved are not in * menu mode already, finds the owner/notification window, initializes * pMenuState and sends the WM_ENTERMENULOOP message. * It successful, it returns a pointer to a pMenuState. If so, the caller * must call MNEndMenuState when done. * * History: * 4-25-91 Mikehar Port for 3.1 merge * 5-20-96 GerardoB Renamed and changed (Old name: xxxMNGetPopup) \***************************************************************************/ PMENUSTATE xxxMNStartMenuState( PWND pwnd, DWORD cmd, LPARAM lParam) { PPOPUPMENU ppopupmenu; PTHREADINFO ptiCurrent, ptiNotify; PMENUSTATE pMenuState; TL tlpwnd; PWND pwndT;
CheckLock(pwnd);
/*
* Bail if the current thread is already in menu mode */ ptiCurrent = PtiCurrent(); if (ptiCurrent->pMenuState != NULL) { return NULL; }
/*
* If pwnd is not owned by ptiCurrent, the _PostMessage call below might * send us in a loop */ UserAssert(ptiCurrent == GETPTI(pwnd));
/*
* If this is not a child window, use the active window on its queue */ if (!TestwndChild(pwnd)) { pwnd = GETPTI(pwnd)->pq->spwndActive; } else { /*
* Search up the parents for a window with a System Menu. */ while (TestwndChild(pwnd)) { if (TestWF(pwnd, WFSYSMENU)) { break; } pwnd = pwnd->spwndParent; } }
if (pwnd == NULL) { return NULL; }
if (!TestwndChild(pwnd) && (pwnd->spmenu != NULL)) { goto hasmenu; }
if (!TestWF(pwnd, WFSYSMENU)) { return NULL; }
hasmenu:
/*
* If the owner/notification window was created by another thread, * make sure that it's not in menu mode already * This can happen if PtiCurrent() is attached to other threads, one of * which created pwnd. */ ptiNotify = GETPTI(pwnd); if (ptiNotify->pMenuState != NULL) { return NULL; }
/*
* If the notification window is owned by another thread, * then the menu loop wouldn't get any keyboard or mouse * messages because we set capture to the notification window. * So we pass the WM_SYSCOMMAND to that thread and bail */ if (ptiNotify != ptiCurrent) { RIPMSG2(RIP_WARNING, "Passing WM_SYSCOMMAND SC_*MENU from thread %#p to %#p", ptiCurrent, ptiNotify); _PostMessage(pwnd, WM_SYSCOMMAND, cmd, lParam); return NULL; }
/*
* Allocate ppoupmenu and pMenuState. */ ppopupmenu = MNAllocPopup(FALSE); if (ppopupmenu == NULL) { return NULL; }
pMenuState = xxxMNAllocMenuState(ptiCurrent, ptiNotify, ppopupmenu); if (pMenuState == NULL) { MNFreePopup(ppopupmenu); return NULL; }
ppopupmenu->fIsMenuBar = TRUE; ppopupmenu->fHasMenuBar = TRUE; Lock(&(ppopupmenu->spwndNotify), pwnd); ppopupmenu->posSelectedItem = MFMWFP_NOITEM; Lock(&(ppopupmenu->spwndPopupMenu), pwnd); ppopupmenu->ppopupmenuRoot = ppopupmenu;
pwndT = pwnd; while(TestwndChild(pwndT)) pwndT = pwndT->spwndParent;
if (pwndT->spmenu) { ppopupmenu->fRtoL = TestMF(pwndT->spmenu, MFRTL) ?TRUE:FALSE; } else { //
// No way to know, no menu, but there is a system menu. Thus arrow
// keys are really not important. However lets take the next best
// thing just to be safe.
//
ppopupmenu->fRtoL = TestWF(pwnd, WEFRTLREADING) ?TRUE :FALSE; }
/*
* Notify the app we are entering menu mode. wParam is always 0 since this * procedure will only be called for menu bar menus not TrackPopupMenu * menus. */ ThreadLockAlways(pwnd, &tlpwnd); xxxSendMessage(pwnd, WM_ENTERMENULOOP, 0, 0); ThreadUnlock(&tlpwnd);
return pMenuState; }
/***************************************************************************\
* xxxMNStartMenu * * Note that this function calls back many times so we might be forced * out of menu mode at any time. We don't want to check this after * each callback so we lock what we need and go on. Be careful. * * History: * 4-25-91 Mikehar Port for 3.1 merge \***************************************************************************/ BOOL xxxMNStartMenu( PPOPUPMENU ppopupmenu, int mn) { PWND pwndMenu; PMENU pMenu; PMENUSTATE pMenuState; TL tlpwndMenu; TL tlpMenu;
UserAssert(IsRootPopupMenu(ppopupmenu));
if (ppopupmenu->fDestroyed) { return FALSE; }
pwndMenu = ppopupmenu->spwndNotify; ThreadLock(pwndMenu, &tlpwndMenu);
pMenuState = GetpMenuState(pwndMenu); if (pMenuState == NULL) { RIPMSG0(RIP_ERROR, "xxxMNStartMenu: pMenuState == NULL"); ThreadUnlock(&tlpwndMenu); return FALSE; } pMenuState->mnFocus = mn; pMenuState->fMenuStarted = TRUE; pMenuState->fButtonDown = pMenuState->fButtonAlwaysDown = ((_GetKeyState(VK_LBUTTON) & 0x8000) != 0);
xxxMNSetCapture(ppopupmenu);
xxxSendMessage(pwndMenu, WM_SETCURSOR, (WPARAM)HWq(pwndMenu), MAKELONG(MSGF_MENU, 0));
if (ppopupmenu->fIsMenuBar) { BOOL fSystemMenu;
pMenu = xxxGetInitMenuParam(pwndMenu, &fSystemMenu);
if (pMenu == NULL) { pMenuState->fMenuStarted = FALSE; xxxMNReleaseCapture(); ThreadUnlock(&tlpwndMenu); return FALSE; }
LockPopupMenu(ppopupmenu, &ppopupmenu->spmenu, pMenu);
ppopupmenu->fIsSysMenu = (fSystemMenu != 0); if (!fSystemMenu) { pMenu = xxxGetSysMenu(pwndMenu, FALSE); LockPopupMenu(ppopupmenu, &ppopupmenu->spmenuAlternate, pMenu); } }
pMenuState->fIsSysMenu = (ppopupmenu->fIsSysMenu != 0);
if (!ppopupmenu->fNoNotify) {
if (ppopupmenu->fIsTrackPopup && ppopupmenu->fIsSysMenu) { pMenu = xxxGetInitMenuParam(pwndMenu, NULL); } else { pMenu = ppopupmenu->spmenu; }
xxxSendMessage(pwndMenu, WM_INITMENU, (WPARAM)PtoH(pMenu), 0L); }
if (!ppopupmenu->fIsTrackPopup) { if (ppopupmenu->fIsSysMenu) { MNPositionSysMenu(pwndMenu, ppopupmenu->spmenu); } else if (ppopupmenu->fIsMenuBar) { ThreadLockMenuNoModify(ppopupmenu->spmenu, &tlpMenu); xxxMNRecomputeBarIfNeeded(pwndMenu, ppopupmenu->spmenu); ThreadUnlockMenuNoModify(&tlpMenu); MNPositionSysMenu(pwndMenu, ppopupmenu->spmenuAlternate); } }
/*
* If returning TRUE, set menu style in pMenuState */ if (!ppopupmenu->fDestroyed) { if (TestMF(ppopupmenu->spmenu, MNS_MODELESS)) { pMenuState->fModelessMenu = TRUE; }
if (TestMF(ppopupmenu->spmenu, MNS_DRAGDROP)) { if (NT_SUCCESS(xxxClientLoadOLE())) { pMenuState->fDragAndDrop = TRUE; } }
if (TestMF(ppopupmenu->spmenu, MNS_AUTODISMISS)) { pMenuState->fAutoDismiss = TRUE; }
if (TestMF(ppopupmenu->spmenu, MNS_NOTIFYBYPOS)) { pMenuState->fNotifyByPos = TRUE; }
}
/*
* Bogus! We don't always know that this is the system menu. We * will frequently pass on an OBJID_MENU even when you hit Alt+Space. * * Hence, MNSwitchToAlternate will send a EVENT_SYSTEM_MENUEND for the * menu bar and an EVENT_SYSTEM_MENUSTART for the sysmenu when we "switch". */ xxxWindowEvent(EVENT_SYSTEM_MENUSTART, pwndMenu, (ppopupmenu->fIsSysMenu ? OBJID_SYSMENU : (ppopupmenu->fIsMenuBar ? OBJID_MENU : OBJID_WINDOW)), INDEXID_CONTAINER, 0);
ThreadUnlock(&tlpwndMenu);
return !ppopupmenu->fDestroyed; }
/***************************************************************************\
* xxxGetInitMenuParam * * Gets the HMENU sent as the wParam of WM_INITMENU, and for menu bars, is * the actual menu to be interacted with. * * History: * ???? \***************************************************************************/ PMENU xxxGetInitMenuParam( PWND pwndMenu, BOOL *lpfSystem) { //
// Find out what menu we should be sending in WM_INITMENU:
// If minimized/child/empty menubar, use system menu
//
CheckLock(pwndMenu);
if (TestWF(pwndMenu, WFMINIMIZED) || TestwndChild(pwndMenu) || (pwndMenu->spmenu == NULL) || !pwndMenu->spmenu->cItems) { if (lpfSystem != NULL) *lpfSystem = TRUE;
return xxxGetSysMenu(pwndMenu, FALSE); } else { if (lpfSystem != NULL) { *lpfSystem = FALSE; }
return pwndMenu->spmenu; } }
|