windows-nt/Source/XPSP1/NT/admin/activec/conui/sysmenu.cpp
2020-09-26 16:20:57 +08:00

191 lines
5.3 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*--------------------------------------------------------------------------*
*
* 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 <list>
#include <algorithm>
typedef std::list<HWND> 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);
}