You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.5 KiB
190 lines
5.5 KiB
/*--------------------------------------------------------------------------*
|
|
*
|
|
* 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);
|
|
}
|