Source code of Windows XP (NT5)
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.3 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: sysmenu.cpp
  7. *
  8. * Contents: Implementation file for system menu modification functions
  9. *
  10. * History: 04-Feb-98 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #include "stdafx.h"
  14. #include "sysmenu.h"
  15. #include "mmcres.h"
  16. #include <list>
  17. #include <algorithm>
  18. typedef std::list<HWND> WindowList;
  19. /*--------------------------------------------------------------------------*
  20. * GetWindowList
  21. *
  22. *
  23. *--------------------------------------------------------------------------*/
  24. static WindowList& GetWindowList()
  25. {
  26. static WindowList List;
  27. return (List);
  28. }
  29. /*--------------------------------------------------------------------------*
  30. * WipeWindowList
  31. *
  32. * Removes no-longer-valid windows from the Window-to-addition map.
  33. *--------------------------------------------------------------------------*/
  34. void WipeWindowList ()
  35. {
  36. WindowList& List = GetWindowList();
  37. WindowList::iterator it = List.begin();
  38. while (it != List.end())
  39. {
  40. // if the window isn't valid, erase it
  41. if (!::IsWindow (*it))
  42. {
  43. WindowList::iterator itErase = it++;
  44. List.erase(itErase);
  45. }
  46. // this one's OK, check the next one
  47. else
  48. ++it;
  49. }
  50. }
  51. /*--------------------------------------------------------------------------*
  52. * AppendToSystemMenu
  53. *
  54. * Returns number of menu items appended.
  55. *--------------------------------------------------------------------------*/
  56. int AppendToSystemMenu (CWnd* pwnd, int nSubmenuIndex)
  57. {
  58. DECLARE_SC(sc, TEXT("AppendToSystemMenu"));
  59. CMenu menuSysAdditions;
  60. sc = menuSysAdditions.LoadMenu (IDR_SYSMENU_ADDITIONS) ? S_OK : E_FAIL;
  61. if (sc)
  62. return 0;
  63. CMenu* pSubMenu = menuSysAdditions.GetSubMenu (nSubmenuIndex);
  64. sc = ScCheckPointers(pSubMenu, E_UNEXPECTED);
  65. if (sc)
  66. return 0;
  67. return (AppendToSystemMenu (pwnd, pSubMenu));
  68. }
  69. /*--------------------------------------------------------------------------*
  70. * AppendToSystemMenu
  71. *
  72. * Returns number of menu items appended.
  73. *
  74. *--------------------------------------------------------------------------*/
  75. int AppendToSystemMenu (CWnd* pwnd, CMenu* pMenuToAppend, CMenu* pSysMenu)
  76. {
  77. DECLARE_SC(sc, TEXT("AppendToSystemMenu"));
  78. sc = ScCheckPointers(pwnd, pMenuToAppend);
  79. if (sc)
  80. return 0;
  81. if ( (!::IsWindow (pwnd->m_hWnd)) ||
  82. (!::IsMenu (pMenuToAppend->m_hMenu)) )
  83. {
  84. sc = E_UNEXPECTED;
  85. return 0;
  86. }
  87. // no system menu? get one
  88. if (pSysMenu == NULL)
  89. pSysMenu = pwnd->GetSystemMenu (FALSE);
  90. // still no system menu? bail
  91. if (pSysMenu == NULL)
  92. return (0);
  93. // clean out the map
  94. WipeWindowList ();
  95. // if this is the first addition to this window, append a separator
  96. WindowList& List = GetWindowList();
  97. WindowList::iterator itEnd = List.end();
  98. if (std::find (List.begin(), itEnd, pwnd->m_hWnd) == itEnd)
  99. {
  100. List.push_back (pwnd->m_hWnd);
  101. // If this is a child window & the next window item has not yet been added
  102. if ( (pwnd->GetStyle() & WS_CHILD) &&
  103. (pSysMenu->GetMenuState (SC_NEXTWINDOW, MF_BYCOMMAND) == 0xFFFFFFFF))
  104. {
  105. // Windows exhibits odd behavior by always handing us a non-child system menu
  106. // The text is currently wrong and diaplays "alt-f4" as the shortcut
  107. // instead of "ctrl-f4". The following code fixes that.
  108. CString strClose;
  109. LoadString(strClose, IDS_CLOSE);
  110. sc = pSysMenu->ModifyMenu( SC_CLOSE, MF_STRING | MF_BYCOMMAND, SC_CLOSE, strClose ) ? S_OK : E_FAIL;
  111. sc.TraceAndClear();
  112. // Add a separator
  113. sc = pSysMenu->AppendMenu (MF_SEPARATOR) ? S_OK : E_FAIL;
  114. sc.TraceAndClear();
  115. // Add the "Next" item
  116. CString strNext;
  117. LoadString(strNext, IDS_NEXTWINDOW);
  118. sc = pSysMenu->AppendMenu( MF_STRING, SC_NEXTWINDOW, strNext ) ? S_OK : E_FAIL;
  119. sc.TraceAndClear();
  120. }
  121. sc = pSysMenu->AppendMenu (MF_SEPARATOR) ? S_OK : E_FAIL;
  122. sc.TraceAndClear();
  123. }
  124. int cAppendedItems = 0;
  125. int cItemsToAppend = pMenuToAppend->GetMenuItemCount ();
  126. TCHAR szMenuText[64];
  127. MENUITEMINFO mii;
  128. mii.cbSize = sizeof (mii);
  129. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
  130. mii.dwTypeData = szMenuText;
  131. for (int i = 0; i < cItemsToAppend; i++)
  132. {
  133. ASSERT (mii.dwTypeData == szMenuText);
  134. mii.cch = countof (szMenuText);
  135. if (! ::GetMenuItemInfo (pMenuToAppend->m_hMenu, i, TRUE, &mii))
  136. sc.FromLastError().TraceAndClear();
  137. // this code can't handle cascaded additions to the system menu
  138. ASSERT (mii.hSubMenu == NULL);
  139. // if the menu item is a separator or isn't already there, append it
  140. if ((mii.fType & MFT_SEPARATOR) ||
  141. (pSysMenu->GetMenuState (mii.wID, MF_BYCOMMAND) == 0xFFFFFFFF))
  142. {
  143. pSysMenu->AppendMenu (mii.fType, mii.wID, szMenuText);
  144. cAppendedItems++;
  145. }
  146. }
  147. // return the number of items appended
  148. return (cAppendedItems);
  149. }