Leaked source code of windows server 2003
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.

451 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: menuc.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains
  7. *
  8. * History:
  9. * 01-11-93 DavidPe Created
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. FUNCLOG3(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, CheckMenuItem, HMENU, hMenu, UINT, uIDCheckItem, UINT, uCheck)
  14. DWORD CheckMenuItem(
  15. HMENU hMenu,
  16. UINT uIDCheckItem,
  17. UINT uCheck)
  18. {
  19. PMENU pMenu;
  20. PITEM pItem;
  21. pMenu = VALIDATEHMENU(hMenu);
  22. if (pMenu == NULL) {
  23. return (DWORD)-1;
  24. }
  25. /*
  26. * Get a pointer the the menu item
  27. */
  28. if ((pItem = MNLookUpItem(pMenu, uIDCheckItem, (BOOL) (uCheck & MF_BYPOSITION), NULL)) == NULL)
  29. return (DWORD)-1;
  30. /*
  31. * If the item is already in the state we're
  32. * trying to set, just return.
  33. */
  34. if ((pItem->fState & MFS_CHECKED) == (uCheck & MFS_CHECKED)) {
  35. return pItem->fState & MF_CHECKED;
  36. }
  37. return NtUserCheckMenuItem(hMenu, uIDCheckItem, uCheck);
  38. }
  39. FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuDefaultItem, HMENU, hMenu, UINT, fByPosition, UINT, uFlags)
  40. UINT GetMenuDefaultItem(HMENU hMenu, UINT fByPosition, UINT uFlags)
  41. {
  42. PMENU pMenu;
  43. pMenu = VALIDATEHMENU(hMenu);
  44. if (pMenu == NULL) {
  45. return (DWORD)-1;
  46. }
  47. return _GetMenuDefaultItem(pMenu, (BOOL)fByPosition, uFlags);
  48. }
  49. /***************************************************************************\
  50. * SetMenuItemInfoStruct
  51. *
  52. * History:
  53. * 07-22-96 GerardoB - Added header and Fixed up for 5.0
  54. \***************************************************************************/
  55. void SetMenuItemInfoStruct(HMENU hMenu, UINT wFlags, UINT_PTR wIDNew, LPWSTR pwszNew, LPMENUITEMINFO pmii)
  56. {
  57. PMENU pMenu;
  58. PITEM pItem;
  59. UserAssert(sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA));
  60. RtlZeroMemory(pmii, sizeof(*pmii));
  61. pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
  62. /*
  63. * For compatibility, setting the bitmap drops the string and
  64. * viceversa; new apps that want to have sting and bitmaps
  65. * must use the MENUITEMINFO APIs
  66. */
  67. if (wFlags & MFT_BITMAP) {
  68. pmii->fMask |= MIIM_BITMAP | MIIM_STRING;
  69. pmii->hbmpItem = (HBITMAP)pwszNew;
  70. pmii->dwTypeData = 0;
  71. } else if (!(wFlags & MFT_NONSTRING)) {
  72. pmii->fMask |= MIIM_BITMAP | MIIM_STRING;
  73. pmii->dwTypeData = pwszNew;
  74. pmii->hbmpItem = NULL;
  75. }
  76. if (wFlags & MF_POPUP) {
  77. pmii->fMask |= MIIM_SUBMENU;
  78. pmii->hSubMenu = (HMENU)wIDNew;
  79. }
  80. if (wFlags & MF_OWNERDRAW) {
  81. pmii->fMask |= MIIM_DATA;
  82. pmii->dwItemData = (ULONG_PTR) pwszNew;
  83. }
  84. pmii->fState = wFlags & MFS_OLDAPI_MASK;
  85. pmii->fType = wFlags & MFT_OLDAPI_MASK;
  86. pMenu = VALIDATEHMENU(hMenu);
  87. if (pMenu && pMenu->cItems) {
  88. pItem = &((PITEM)REBASEALWAYS(pMenu, rgItems))[0];
  89. if (pItem && TestMFT(pItem, MFT_RIGHTORDER)) {
  90. pmii->fType |= MFT_RIGHTORDER;
  91. }
  92. }
  93. pmii->wID = (UINT)wIDNew;
  94. }
  95. /***************************************************************************\
  96. * SetMenuItemInfo
  97. *
  98. * History:
  99. * 07-22-96 GerardoB - Added header
  100. \***************************************************************************/
  101. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetMenuInfo, HMENU, hMenu, LPCMENUINFO, lpmi)
  102. BOOL SetMenuInfo(HMENU hMenu, LPCMENUINFO lpmi)
  103. {
  104. if (!ValidateMENUINFO(lpmi, MENUAPI_SET)) {
  105. return FALSE;
  106. }
  107. return NtUserThunkedMenuInfo(hMenu, (LPCMENUINFO)lpmi);
  108. }
  109. /***************************************************************************\
  110. * ChangeMenu
  111. *
  112. * Stub routine for compatibility with version < 3.0
  113. *
  114. * History:
  115. \***************************************************************************/
  116. FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ChangeMenuW, HMENU, hMenu, UINT, cmd, LPCWSTR, lpNewItem, UINT, IdItem, UINT, flags)
  117. BOOL ChangeMenuW(
  118. HMENU hMenu,
  119. UINT cmd,
  120. LPCWSTR lpNewItem,
  121. UINT IdItem,
  122. UINT flags)
  123. {
  124. /*
  125. * These next two statements take care of sleazyness needed for
  126. * compatability with old changemenu.
  127. */
  128. if ((flags & MF_SEPARATOR) && cmd == MFMWFP_OFFMENU && !(flags & MF_CHANGE))
  129. flags |= MF_APPEND;
  130. if (lpNewItem == NULL)
  131. flags |= MF_SEPARATOR;
  132. /*
  133. * MUST be MF_BYPOSITION for Win2.x compatability.
  134. */
  135. if (flags & MF_REMOVE)
  136. return(NtUserRemoveMenu(hMenu, cmd,
  137. (DWORD)((flags & ~MF_REMOVE) | MF_BYPOSITION)));
  138. if (flags & MF_DELETE)
  139. return(NtUserDeleteMenu(hMenu, cmd, (DWORD)(flags & ~MF_DELETE)));
  140. if (flags & MF_CHANGE)
  141. return(ModifyMenuW(hMenu, cmd, (DWORD)((flags & ~MF_CHANGE) &
  142. (0x07F | MF_HELP | MF_BYPOSITION | MF_BYCOMMAND |
  143. MF_SEPARATOR)), IdItem, lpNewItem));
  144. if (flags & MF_APPEND)
  145. return(AppendMenuW(hMenu, (UINT)(flags & ~MF_APPEND),
  146. IdItem, lpNewItem));
  147. /*
  148. * Default is insert
  149. */
  150. return(InsertMenuW(hMenu, cmd, (DWORD)(flags & ~MF_INSERT),
  151. IdItem, lpNewItem));
  152. }
  153. FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ChangeMenuA, HMENU, hMenu, UINT, cmd, LPCSTR, lpNewItem, UINT, IdItem, UINT, flags)
  154. BOOL ChangeMenuA(
  155. HMENU hMenu,
  156. UINT cmd,
  157. LPCSTR lpNewItem,
  158. UINT IdItem,
  159. UINT flags)
  160. {
  161. /*
  162. * These next two statements take care of sleazyness needed for
  163. * compatability with old changemenu.
  164. */
  165. if ((flags & MF_SEPARATOR) && cmd == MFMWFP_OFFMENU && !(flags & MF_CHANGE))
  166. flags |= MF_APPEND;
  167. if (lpNewItem == NULL)
  168. flags |= MF_SEPARATOR;
  169. /*
  170. * MUST be MF_BYPOSITION for Win2.x compatability.
  171. */
  172. if (flags & MF_REMOVE)
  173. return(NtUserRemoveMenu(hMenu, cmd,
  174. (DWORD)((flags & ~MF_REMOVE) | MF_BYPOSITION)));
  175. if (flags & MF_DELETE)
  176. return(NtUserDeleteMenu(hMenu, cmd, (DWORD)(flags & ~MF_DELETE)));
  177. if (flags & MF_CHANGE)
  178. return(ModifyMenuA(hMenu, cmd, (DWORD)((flags & ~MF_CHANGE) &
  179. (0x07F | MF_HELP | MF_BYPOSITION | MF_BYCOMMAND |
  180. MF_SEPARATOR)), IdItem, lpNewItem));
  181. if (flags & MF_APPEND)
  182. return(AppendMenuA(hMenu, (UINT)(flags & ~MF_APPEND),
  183. IdItem, lpNewItem));
  184. /*
  185. * Default is insert
  186. */
  187. return(InsertMenuA(hMenu, cmd, (DWORD)(flags & ~MF_INSERT),
  188. IdItem, lpNewItem));
  189. }
  190. LONG GetMenuCheckMarkDimensions()
  191. {
  192. return((DWORD)MAKELONG(SYSMET(CXMENUCHECK), SYSMET(CYMENUCHECK)));
  193. }
  194. /***************************************************************************\
  195. * GetMenuContextHelpId
  196. *
  197. * Return the help id of a menu.
  198. *
  199. \***************************************************************************/
  200. FUNCLOG1(LOG_GENERAL, WINUSERAPI DWORD, WINAPI, GetMenuContextHelpId, HMENU, hMenu)
  201. WINUSERAPI DWORD WINAPI GetMenuContextHelpId(
  202. HMENU hMenu)
  203. {
  204. PMENU pMenu;
  205. pMenu = VALIDATEHMENU(hMenu);
  206. if (pMenu == NULL)
  207. return 0;
  208. return pMenu->dwContextHelpId;
  209. }
  210. BOOL TrackPopupMenu(
  211. HMENU hMenu,
  212. UINT fuFlags,
  213. int x,
  214. int y,
  215. int nReserved,
  216. HWND hwnd,
  217. CONST RECT *prcRect)
  218. {
  219. UNREFERENCED_PARAMETER(nReserved);
  220. UNREFERENCED_PARAMETER(prcRect);
  221. return NtUserTrackPopupMenuEx(hMenu, fuFlags, x, y, hwnd, NULL);
  222. }
  223. /***************************************************************************\
  224. * GetSysMenuHandle
  225. *
  226. * Returns a handle to the system menu of the given window. NULL if
  227. * the window doesn't have a system menu.
  228. *
  229. * History:
  230. \***************************************************************************/
  231. PMENU xxxGetSysMenuHandle(
  232. PWND pwnd)
  233. {
  234. PMENU pMenu;
  235. if (TestWF(pwnd, WFSYSMENU)) {
  236. pMenu = pwnd->spmenuSys;
  237. /*
  238. * If the window doesn't have a System Menu, use the default one.
  239. */
  240. if (pMenu == NULL) {
  241. /*
  242. * Change owner so this app can access this menu.
  243. */
  244. pMenu = (PMENU)NtUserCallHwndLock(HWq(pwnd), SFI_XXXGETSYSMENUHANDLE);
  245. }
  246. } else {
  247. pMenu = NULL;
  248. }
  249. return pMenu;
  250. }
  251. BOOL WINAPI SetMenuItemBitmaps
  252. (
  253. HMENU hMenu,
  254. UINT nPosition,
  255. UINT uFlags,
  256. HBITMAP hbmpUnchecked,
  257. HBITMAP hbmpChecked
  258. )
  259. {
  260. MENUITEMINFO mii;
  261. mii.cbSize = sizeof(MENUITEMINFO);
  262. mii.fMask = MIIM_CHECKMARKS;
  263. mii.hbmpChecked = hbmpChecked;
  264. mii.hbmpUnchecked = hbmpUnchecked;
  265. return(SetMenuItemInfo(hMenu, nPosition, (BOOL) (uFlags & MF_BYPOSITION), &mii));
  266. }
  267. FUNCLOG5(LOG_GENERAL, int, WINAPI, DrawMenuBarTemp, HWND, hwnd, HDC, hdc, LPCRECT, lprc, HMENU, hMenu, HFONT, hFont)
  268. int WINAPI DrawMenuBarTemp(
  269. HWND hwnd,
  270. HDC hdc,
  271. LPCRECT lprc,
  272. HMENU hMenu,
  273. HFONT hFont)
  274. {
  275. HDC hdcr;
  276. if (IsMetaFile(hdc))
  277. return -1;
  278. hdcr = GdiConvertAndCheckDC(hdc);
  279. if (hdcr == (HDC)0)
  280. return -1;
  281. if (!hMenu)
  282. return -1;
  283. return NtUserDrawMenuBarTemp(
  284. hwnd,
  285. hdc,
  286. lprc,
  287. hMenu,
  288. hFont);
  289. }
  290. /***************************************************************************\
  291. *
  292. * CheckMenuRadioItem() -
  293. *
  294. * Checks one menu item in a range, unchecking the others. This can be
  295. * done either MF_BYCOMMAND or MF_BYPOSITION. It works similarly to
  296. * CheckRadioButton().
  297. *
  298. * The return value is TRUE if the given item was checked, FALSE if not.
  299. *
  300. * History
  301. * 04/04/97 GerardoB Moved to the client side
  302. \***************************************************************************/
  303. FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CheckMenuRadioItem, HMENU, hMenu, UINT, wIDFirst, UINT, wIDLast, UINT, wIDCheck, UINT, flags)
  304. BOOL CheckMenuRadioItem(HMENU hMenu, UINT wIDFirst, UINT wIDLast,
  305. UINT wIDCheck, UINT flags)
  306. {
  307. BOOL fByPosition = (BOOL) (flags & MF_BYPOSITION);
  308. PMENU pMenu, pMenuItemIsOn;
  309. PITEM pItem;
  310. UINT wIDCur;
  311. BOOL fChecked = FALSE;
  312. BOOL fFirst = TRUE;
  313. MENUITEMINFO mii;
  314. pMenu = VALIDATEHMENU(hMenu);
  315. if (pMenu == NULL) {
  316. return FALSE;
  317. }
  318. mii.cbSize = sizeof(mii);
  319. /*
  320. * Make sure we won't loop for ever
  321. */
  322. wIDLast = min(wIDLast, (UINT)0xFFFFFFFE);
  323. for (wIDCur = wIDFirst; wIDCur <= wIDLast; wIDCur++) {
  324. pItem = MNLookUpItem(pMenu, wIDCur, fByPosition, &pMenuItemIsOn);
  325. /*
  326. * Continue searching if it didn't find the item or it's a separator
  327. */
  328. if ((pItem == NULL) || TestMFT(pItem, MFT_SEPARATOR)) {
  329. continue;
  330. }
  331. /*
  332. * If this is the first one, rememeber what menu it's on because
  333. * all items are supposed to be in the same menu.
  334. */
  335. if (fFirst) {
  336. pMenu = pMenuItemIsOn;
  337. hMenu = PtoHq(pMenu);
  338. fFirst = FALSE;
  339. }
  340. /*
  341. * If this item is on a different menu, don't touch it
  342. */
  343. if (pMenu != pMenuItemIsOn) {
  344. continue;
  345. }
  346. /*
  347. * Set the new check state. Avoid the trip to the kernel if possible
  348. */
  349. if (wIDCur == wIDCheck) {
  350. /*
  351. * Check it.
  352. */
  353. if (!TestMFT(pItem, MFT_RADIOCHECK) || !TestMFS(pItem, MFS_CHECKED)) {
  354. mii.fMask = MIIM_FTYPE | MIIM_STATE;
  355. mii.fType = (pItem->fType & MFT_MASK) | MFT_RADIOCHECK;
  356. mii.fState = (pItem->fState & MFS_MASK) | MFS_CHECKED;
  357. NtUserThunkedMenuItemInfo(hMenu, wIDCheck, fByPosition, FALSE, &mii, NULL);
  358. }
  359. fChecked = TRUE;
  360. } else {
  361. /*
  362. * Uncheck it
  363. * NOTE: don't remove MFT_RADIOCHECK type
  364. */
  365. if (TestMFS(pItem, MFS_CHECKED)) {
  366. mii.fMask = MIIM_STATE;
  367. mii.fState = (pItem->fState & MFS_MASK) & ~MFS_CHECKED;
  368. NtUserThunkedMenuItemInfo(hMenu, wIDCur, fByPosition, FALSE, &mii, NULL);
  369. }
  370. }
  371. } /* for */
  372. if (fFirst) {
  373. /*
  374. * No item was ever found.
  375. */
  376. RIPERR0(ERROR_MENU_ITEM_NOT_FOUND, RIP_VERBOSE, "CheckMenuRadioItem, no items found\n");
  377. }
  378. return(fChecked);
  379. }