/*--------------------------------------------------------------------------* * * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992 - 1999 * * File: sysmenu.cpp * * Contents: Implementation file for system menu modification functions * * History: 04-Feb-98 jeffro Created * *--------------------------------------------------------------------------*/ #include "stdafx.h" #include "sysmenu.h" #include "mmcres.h" #include #include typedef std::list WindowList; /*--------------------------------------------------------------------------* * GetWindowList * * *--------------------------------------------------------------------------*/ static WindowList& GetWindowList() { static WindowList List; return (List); } /*--------------------------------------------------------------------------* * WipeWindowList * * Removes no-longer-valid windows from the Window-to-addition map. *--------------------------------------------------------------------------*/ void WipeWindowList () { WindowList& List = GetWindowList(); WindowList::iterator it = List.begin(); while (it != List.end()) { // if the window isn't valid, erase it if (!::IsWindow (*it)) { WindowList::iterator itErase = it++; List.erase(itErase); } // this one's OK, check the next one else ++it; } } /*--------------------------------------------------------------------------* * AppendToSystemMenu * * Returns number of menu items appended. *--------------------------------------------------------------------------*/ int AppendToSystemMenu (CWnd* pwnd, int nSubmenuIndex) { DECLARE_SC(sc, TEXT("AppendToSystemMenu")); CMenu menuSysAdditions; sc = menuSysAdditions.LoadMenu (IDR_SYSMENU_ADDITIONS) ? S_OK : E_FAIL; if (sc) return 0; CMenu* pSubMenu = menuSysAdditions.GetSubMenu (nSubmenuIndex); sc = ScCheckPointers(pSubMenu, E_UNEXPECTED); if (sc) return 0; return (AppendToSystemMenu (pwnd, pSubMenu)); } /*--------------------------------------------------------------------------* * AppendToSystemMenu * * Returns number of menu items appended. * *--------------------------------------------------------------------------*/ int AppendToSystemMenu (CWnd* pwnd, CMenu* pMenuToAppend, CMenu* pSysMenu) { DECLARE_SC(sc, TEXT("AppendToSystemMenu")); sc = ScCheckPointers(pwnd, pMenuToAppend); if (sc) return 0; if ( (!::IsWindow (pwnd->m_hWnd)) || (!::IsMenu (pMenuToAppend->m_hMenu)) ) { sc = E_UNEXPECTED; return 0; } // no system menu? get one if (pSysMenu == NULL) pSysMenu = pwnd->GetSystemMenu (FALSE); // still no system menu? bail if (pSysMenu == NULL) return (0); // clean out the map WipeWindowList (); // if this is the first addition to this window, append a separator WindowList& List = GetWindowList(); WindowList::iterator itEnd = List.end(); if (std::find (List.begin(), itEnd, pwnd->m_hWnd) == itEnd) { List.push_back (pwnd->m_hWnd); // If this is a child window & the next window item has not yet been added if ( (pwnd->GetStyle() & WS_CHILD) && (pSysMenu->GetMenuState (SC_NEXTWINDOW, MF_BYCOMMAND) == 0xFFFFFFFF)) { // Windows exhibits odd behavior by always handing us a non-child system menu // The text is currently wrong and diaplays "alt-f4" as the shortcut // instead of "ctrl-f4". The following code fixes that. CString strClose; LoadString(strClose, IDS_CLOSE); sc = pSysMenu->ModifyMenu( SC_CLOSE, MF_STRING | MF_BYCOMMAND, SC_CLOSE, strClose ) ? S_OK : E_FAIL; sc.TraceAndClear(); // Add a separator sc = pSysMenu->AppendMenu (MF_SEPARATOR) ? S_OK : E_FAIL; sc.TraceAndClear(); // Add the "Next" item CString strNext; LoadString(strNext, IDS_NEXTWINDOW); sc = pSysMenu->AppendMenu( MF_STRING, SC_NEXTWINDOW, strNext ) ? S_OK : E_FAIL; sc.TraceAndClear(); } sc = pSysMenu->AppendMenu (MF_SEPARATOR) ? S_OK : E_FAIL; sc.TraceAndClear(); } int cAppendedItems = 0; int cItemsToAppend = pMenuToAppend->GetMenuItemCount (); TCHAR szMenuText[64]; MENUITEMINFO mii; mii.cbSize = sizeof (mii); mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU; mii.dwTypeData = szMenuText; for (int i = 0; i < cItemsToAppend; i++) { ASSERT (mii.dwTypeData == szMenuText); mii.cch = countof (szMenuText); if (! ::GetMenuItemInfo (pMenuToAppend->m_hMenu, i, TRUE, &mii)) sc.FromLastError().TraceAndClear(); // this code can't handle cascaded additions to the system menu ASSERT (mii.hSubMenu == NULL); // if the menu item is a separator or isn't already there, append it if ((mii.fType & MFT_SEPARATOR) || (pSysMenu->GetMenuState (mii.wID, MF_BYCOMMAND) == 0xFFFFFFFF)) { pSysMenu->AppendMenu (mii.fType, mii.wID, szMenuText); cAppendedItems++; } } // return the number of items appended return (cAppendedItems); }