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.

272 lines
6.8 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MMENU.CPP: Defines custom menu interface for multimedia applet
  4. //
  5. // Copyright (c) Microsoft Corporation 1998
  6. //
  7. // 1/28/98 David Stewart / dstewart
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. #include "windows.h"
  11. #include "mmenu.h"
  12. #include "tchar.h"
  13. #include "resource.h"
  14. #define ICON_SPACING 3
  15. extern HINSTANCE hInst;
  16. typedef struct ownermenu
  17. {
  18. TCHAR szText[MAX_PATH];
  19. HICON hIcon;
  20. } OWNERMENU, *LPOWNERMENU;
  21. HRESULT AllocCustomMenu(CustomMenu** ppMenu)
  22. {
  23. *ppMenu = new CCustomMenu();
  24. if (*ppMenu==NULL)
  25. {
  26. return E_OUTOFMEMORY;
  27. }
  28. return S_OK;
  29. }
  30. CCustomMenu::CCustomMenu()
  31. {
  32. m_hMenu = CreatePopupMenu();
  33. //get system font for any owner drawing
  34. NONCLIENTMETRICS metrics;
  35. metrics.cbSize = sizeof(metrics);
  36. SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(metrics),&metrics,0);
  37. m_hFont = CreateFontIndirect(&metrics.lfMenuFont);
  38. if (metrics.lfMenuFont.lfCharSet == ANSI_CHARSET)
  39. {
  40. metrics.lfMenuFont.lfWeight = FW_BOLD;
  41. }
  42. m_hBoldFont = CreateFontIndirect(&metrics.lfMenuFont);
  43. }
  44. CCustomMenu::~CCustomMenu()
  45. {
  46. //clean up string data in menus
  47. int x = GetMenuItemCount(m_hMenu);
  48. for (int i = 0; i < x; i++)
  49. {
  50. MENUITEMINFO mii;
  51. ZeroMemory(&mii,sizeof(mii));
  52. mii.cbSize = sizeof(mii);
  53. mii.fMask = MIIM_DATA|MIIM_TYPE;
  54. GetMenuItemInfo(m_hMenu,i,TRUE,&mii);
  55. if ((mii.dwItemData!=0) && (mii.fType & MFT_OWNERDRAW))
  56. {
  57. OWNERMENU* pMenu = (OWNERMENU*)mii.dwItemData;
  58. if (pMenu)
  59. {
  60. DestroyIcon(pMenu->hIcon);
  61. delete [] pMenu;
  62. }
  63. }
  64. }
  65. DestroyMenu(m_hMenu);
  66. DeleteObject(m_hFont);
  67. DeleteObject(m_hBoldFont);
  68. }
  69. void CCustomMenu::Destroy()
  70. {
  71. delete this;
  72. }
  73. BOOL CCustomMenu::AppendMenu(HINSTANCE hInst, int nStringID, CustomMenu* pMenu)
  74. {
  75. TCHAR szMenu[MAX_PATH];
  76. LoadString(hInst,nStringID,szMenu,sizeof(szMenu)/sizeof(TCHAR));
  77. return ::AppendMenu(m_hMenu,MF_STRING|MF_POPUP,(UINT_PTR)pMenu->GetMenuHandle(),szMenu);
  78. }
  79. BOOL CCustomMenu::AppendMenu(int nMenuID, TCHAR* szMenu)
  80. {
  81. return ::AppendMenu(m_hMenu,MF_STRING,nMenuID,szMenu);
  82. }
  83. BOOL CCustomMenu::AppendMenu(int nMenuID, HINSTANCE hInst, int nStringID)
  84. {
  85. TCHAR szMenu[MAX_PATH];
  86. LoadString(hInst,nStringID,szMenu,sizeof(szMenu)/sizeof(TCHAR));
  87. return ::AppendMenu(m_hMenu,MF_STRING,nMenuID,szMenu);
  88. }
  89. BOOL CCustomMenu::AppendSeparator()
  90. {
  91. return ::AppendMenu(m_hMenu,MF_SEPARATOR,0,0);
  92. }
  93. BOOL CCustomMenu::AppendMenu(int nMenuID, HINSTANCE hInst, int nIconID, int nStringID)
  94. {
  95. OWNERMENU* pMenu = new OWNERMENU;
  96. if (!pMenu)
  97. {
  98. return FALSE;
  99. }
  100. LoadString(hInst,nStringID,pMenu->szText,sizeof(pMenu->szText)/sizeof(TCHAR));
  101. int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
  102. int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);
  103. pMenu->hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(nIconID), IMAGE_ICON, cxMiniIcon, cyMiniIcon, LR_DEFAULTCOLOR);
  104. return ::AppendMenu(m_hMenu,MF_OWNERDRAW,nMenuID,(LPTSTR)pMenu);
  105. }
  106. BOOL CCustomMenu::TrackPopupMenu(UINT uFlags, int x, int y, HWND hwnd, CONST RECT* pRect)
  107. {
  108. TPMPARAMS tpm;
  109. tpm.cbSize = sizeof(tpm);
  110. memcpy(&(tpm.rcExclude),pRect,sizeof(RECT));
  111. return ::TrackPopupMenuEx(m_hMenu,uFlags,x,y,hwnd,&tpm);
  112. }
  113. BOOL CCustomMenu::SetMenuDefaultItem(UINT uItem, UINT fByPos)
  114. {
  115. return ::SetMenuDefaultItem(m_hMenu,uItem,fByPos);
  116. }
  117. void CCustomMenu::MeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT pMeasure)
  118. {
  119. OWNERMENU* szMenu = (OWNERMENU*)pMeasure->itemData;
  120. int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
  121. int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);
  122. HDC hdc = GetDC(hwnd);
  123. HFONT hOrgFont = (HFONT)SelectObject(hdc,m_hBoldFont);
  124. SIZE size;
  125. GetTextExtentPoint32(hdc, szMenu->szText, _tcslen(szMenu->szText), &size );
  126. pMeasure->itemWidth = size.cx + cxMiniIcon + (ICON_SPACING*2);
  127. pMeasure->itemHeight = max(cyMiniIcon,size.cy);
  128. SelectObject(hdc,hOrgFont);
  129. ReleaseDC(hwnd,hdc);
  130. }
  131. void CCustomMenu::DrawItem(HWND hwnd, LPDRAWITEMSTRUCT pDraw)
  132. {
  133. OWNERMENU* szMenu = (OWNERMENU*)pDraw->itemData;
  134. HDC hdc = pDraw->hDC;
  135. COLORREF colorFill = GetSysColor(COLOR_MENU);
  136. COLORREF colorText = GetSysColor(COLOR_MENUTEXT);
  137. if (pDraw->itemState & ODS_SELECTED)
  138. {
  139. colorFill = GetSysColor(COLOR_HIGHLIGHT);
  140. colorText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  141. }
  142. HBRUSH hbrBack = CreateSolidBrush(GetSysColor(COLOR_MENU));
  143. //blit the icon, always with menu color background
  144. int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
  145. int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);
  146. DrawIconEx(hdc,pDraw->rcItem.left,pDraw->rcItem.top,szMenu->hIcon,cxMiniIcon,cyMiniIcon,0,hbrBack,DI_NORMAL);
  147. DeleteObject(hbrBack);
  148. hbrBack = CreateSolidBrush(colorFill);
  149. HFONT hOrgFont;
  150. if (pDraw->itemState & ODS_DEFAULT)
  151. {
  152. hOrgFont = (HFONT)SelectObject(hdc,m_hBoldFont);
  153. }
  154. else
  155. {
  156. hOrgFont = (HFONT)SelectObject(hdc,m_hFont);
  157. }
  158. pDraw->rcItem.left += (cxMiniIcon + ICON_SPACING);
  159. FillRect(hdc,&pDraw->rcItem,hbrBack);
  160. DeleteObject(hbrBack);
  161. pDraw->rcItem.left += ICON_SPACING;
  162. SetBkMode(hdc,TRANSPARENT);
  163. SetTextColor(hdc,colorText);
  164. DrawText(hdc, szMenu->szText, -1, &pDraw->rcItem, DT_SINGLELINE);
  165. SelectObject(hdc,hOrgFont);
  166. }
  167. LRESULT CCustomMenu::MenuChar(TCHAR tChar, UINT fuFlag, HMENU hMenu)
  168. {
  169. //go through the menus one-by-one looking for the accel key
  170. int nReturn = 0;
  171. int nCode = MNC_IGNORE;
  172. int x = GetMenuItemCount(m_hMenu);
  173. TCHAR teststr[3];
  174. wsprintf(teststr,TEXT("&%c"),tChar);
  175. _tcsupr(teststr);
  176. for (int i = 0; i < x; i++)
  177. {
  178. MENUITEMINFO mii;
  179. ZeroMemory(&mii,sizeof(mii));
  180. mii.cbSize = sizeof(mii);
  181. mii.fMask = MIIM_DATA|MIIM_TYPE;
  182. GetMenuItemInfo(m_hMenu,i,TRUE,&mii);
  183. if ((mii.dwItemData!=0) && (mii.fType & MFT_OWNERDRAW))
  184. {
  185. OWNERMENU* szMenu = (OWNERMENU*)mii.dwItemData;
  186. TCHAR* pMenu = new TCHAR[_tcslen(szMenu->szText)+sizeof(TCHAR)];
  187. _tcscpy(pMenu,szMenu->szText);
  188. _tcsupr(pMenu);
  189. if (_tcsstr(pMenu,teststr)!=NULL)
  190. {
  191. nReturn = i;
  192. nCode = MNC_EXECUTE;
  193. if (pMenu)
  194. {
  195. delete [] pMenu;
  196. pMenu = NULL;
  197. }
  198. break;
  199. }
  200. if (pMenu)
  201. {
  202. delete [] pMenu;
  203. pMenu = NULL;
  204. }
  205. } //end if not separator
  206. }
  207. return (MAKELRESULT(nReturn, nCode));
  208. }