3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: menu.c,v 1.46 2004/02/01 20:45:02 weiden Exp $
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/menu.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 09-05-2001 CSH Created
29 /* INCLUDES ******************************************************************/
39 #include <user32/callback.h>
40 #include "user32/regcontrol.h"
41 #include "../controls/controls.h"
43 /* TYPES *********************************************************************/
45 #define MENU_TYPE_MASK ((MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
47 #define MENU_ITEM_TYPE(flags) \
48 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
50 #define MENU_BAR_ITEMS_SPACE (12)
51 #define SEPARATOR_HEIGHT (5)
52 #define MENU_TAB_SPACE (8)
55 #define MF_END (0x0080)
59 #define MIIM_STRING (0x00000040)
62 #define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
63 #define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
64 #define POPUPMENU_CLASS_ATOMA MAKEINTATOMA(32768) /* PopupMenu */
65 #define POPUPMENU_CLASS_ATOMW MAKEINTATOMW(32768) /* PopupMenu */
67 static LRESULT WINAPI
PopupMenuWndProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
);
69 /*********************************************************************
70 * PopupMenu class descriptor
72 const struct builtin_class_descr POPUPMENU_builtin_class
=
74 POPUPMENU_CLASS_ATOMW
, /* name */
75 CS_GLOBALCLASS
| CS_SAVEBITS
| CS_DBLCLKS
, /* style */
76 (WNDPROC
) PopupMenuWndProcW
, /* FIXME - procW */
77 (WNDPROC
) NULL
, /* FIXME - procA */
78 sizeof(MENUINFO
*), /* extra */
79 (LPCWSTR
) IDC_ARROW
, /* cursor */
80 (HBRUSH
)(COLOR_MENU
+ 1) /* brush */
84 /* INTERNAL FUNCTIONS ********************************************************/
86 /* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
87 * Of course I didnt copy the ASM code because we want this to be portable
88 * and it needs to go away.
92 #define GET_WORD(ptr) (*(WORD *)(ptr))
95 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
98 HFONT hMenuFont
= NULL
;
99 HFONT hMenuFontBold
= NULL
;
101 static LRESULT WINAPI
PopupMenuWndProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
106 return DefWindowProcW(hwnd
, message
, wParam
, lParam
);
111 /**********************************************************************
112 * MENUEX_ParseResource
114 * Parse an extended menu resource and add items to the menu.
115 * Return a pointer to the end of the resource.
117 * FIXME - should we be passing an LPCSTR to a predominantly UNICODE function?
119 static LPCSTR
MENUEX_ParseResource( LPCSTR res
, HMENU hMenu
)
127 mii
.cbSize
= sizeof(mii
);
128 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
;
129 mii
.fType
= GET_DWORD(res
);
130 res
+= sizeof(DWORD
);
131 mii
.fState
= GET_DWORD(res
);
132 res
+= sizeof(DWORD
);
133 mii
.wID
= GET_DWORD(res
);
134 res
+= sizeof(DWORD
);
135 resinfo
= GET_WORD(res
);
137 /* Align the text on a word boundary. */
138 res
+= (~((int)res
- 1)) & 1;
139 mii
.dwTypeData
= (LPWSTR
) res
;
140 res
+= (1 + wcslen(mii
.dwTypeData
)) * sizeof(WCHAR
);
141 /* Align the following fields on a dword boundary. */
142 res
+= (~((int)res
- 1)) & 3;
144 if (resinfo
& 1) /* Pop-up? */
146 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
147 res
+= sizeof(DWORD
);
148 mii
.hSubMenu
= CreatePopupMenu();
151 if (!(res
= MENUEX_ParseResource(res
, mii
.hSubMenu
)))
153 DestroyMenu(mii
.hSubMenu
);
156 mii
.fMask
|= MIIM_SUBMENU
;
157 mii
.fType
|= MF_POPUP
;
159 else if(!*mii
.dwTypeData
&& !(mii
.fType
& MF_SEPARATOR
))
161 DbgPrint("WARN: Converting NULL menu item %04x, type %04x to SEPARATOR\n",
163 mii
.fType
|= MF_SEPARATOR
;
165 InsertMenuItemW(hMenu
, -1, MF_BYPOSITION
, &mii
);
167 while (!(resinfo
& MF_END
));
172 /**********************************************************************
175 * Parse a standard menu resource and add items to the menu.
176 * Return a pointer to the end of the resource.
178 * NOTE: flags is equivalent to the mtOption field
180 static LPCSTR
MENU_ParseResource( LPCSTR res
, HMENU hMenu
, BOOL unicode
)
189 flags
= GET_WORD(res
);
191 /* remove MF_END flag before passing it to AppendMenu()! */
192 end
= (flags
& MF_END
);
193 if(end
) flags
^= MF_END
;
196 if(!(flags
& MF_POPUP
))
203 res
+= strlen(str
) + 1;
205 res
+= (wcslen((LPCWSTR
)str
) + 1) * sizeof(WCHAR
);
206 if (flags
& MF_POPUP
)
208 hSubMenu
= CreatePopupMenu();
209 if(!hSubMenu
) return NULL
;
210 if(!(res
= MENU_ParseResource(res
, hSubMenu
, unicode
)))
213 AppendMenuA(hMenu
, flags
, (UINT
)hSubMenu
, str
);
215 AppendMenuW(hMenu
, flags
, (UINT
)hSubMenu
, (LPCWSTR
)str
);
217 else /* Not a popup */
220 AppendMenuA(hMenu
, flags
, id
, *str
? str
: NULL
);
222 AppendMenuW(hMenu
, flags
, id
,
223 *(LPCWSTR
)str
? (LPCWSTR
)str
: NULL
);
232 User32LoadSysMenuTemplateForKernel(PVOID Arguments
, ULONG ArgumentLength
)
236 hUser32
= GetModuleHandleW(L
"USER32");
237 Result
= (LRESULT
)LoadMenuW(hUser32
, L
"SYSMENU");
238 return(ZwCallbackReturn(&Result
, sizeof(LRESULT
), STATUS_SUCCESS
));
245 NONCLIENTMETRICSW ncm
;
247 /* get the menu font */
248 if(!hMenuFont
|| !hMenuFontBold
)
250 ncm
.cbSize
= sizeof(ncm
);
251 if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(ncm
), &ncm
, 0))
253 DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
257 hMenuFont
= CreateFontIndirectW(&ncm
.lfMenuFont
);
258 if(hMenuFont
== NULL
)
260 DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
264 ncm
.lfMenuFont
.lfWeight
= max(ncm
.lfMenuFont
.lfWeight
+ 300, 1000);
265 hMenuFontBold
= CreateFontIndirectW(&ncm
.lfMenuFont
);
266 if(hMenuFontBold
== NULL
)
268 DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
278 MeasureMenuItem(HWND hWnd
, HMENU mnu
, HDC hDC
, MENUITEMINFOW
*mii
, RECT
*mir
, LPWSTR str
)
281 MEASUREITEMSTRUCT mis
;
284 if(mii
->fType
& MFT_OWNERDRAW
)
286 /* send WM_MEASUREITEM message to window */
287 mis
.CtlType
= ODT_MENU
;
289 mis
.itemID
= mii
->wID
;
292 mis
.itemData
= mii
->dwItemData
;
293 res
= (BOOL
)SendMessageW(hWnd
, WM_MEASUREITEM
, 0, (LPARAM
)&mis
);
296 mir
->right
= mir
->left
+ mis
.itemWidth
;
297 mir
->bottom
= mir
->top
+ mis
.itemHeight
;
301 /* FIXME calculate size internally assuming the menu item is empty */
302 mir
->right
= mir
->left
+ 1;
303 mir
->bottom
= mir
->top
+ 1;
309 GetTextExtentPoint32W(hDC
, str
, mii
->cch
, &sz
);
310 /* FIXME calculate the size of the menu item */
311 mir
->right
= mir
->left
+ sz
.cx
+ 6;
312 mir
->bottom
= mir
->top
+ max(sz
.cy
, GetSystemMetrics(SM_CYMENU
));
318 DrawMenuItem(HWND hWnd
, HMENU mnu
, HDC hDC
, MENUITEMINFOW
*mii
, RECT
*mir
, LPWSTR str
)
323 if(mii
->fType
& MFT_OWNERDRAW
)
325 /* send WM_DRAWITEM message to window */
326 dis
.CtlType
= ODT_MENU
;
328 dis
.itemID
= mii
->wID
;
329 dis
.itemAction
= ODA_DRAWENTIRE
; /* FIXME */
330 dis
.itemState
= 0; /* FIXME */
331 dis
.hwndItem
= (HWND
)mnu
;
333 RtlCopyMemory(&dis
.rcItem
, mir
, sizeof(RECT
));
334 dis
.itemData
= mii
->dwItemData
;
335 res
= (BOOL
)SendMessageW(hWnd
, WM_DRAWITEM
, 0, (LPARAM
)&dis
);
340 /* FIXME draw the menu item */
341 SetTextColor(hDC
, COLOR_MENUTEXT
);
342 SetBkMode(hDC
, TRANSPARENT
);
343 DrawTextW(hDC
, str
, mii
->cch
, mir
, DT_SINGLELINE
| DT_VCENTER
| DT_CENTER
);
350 MenuDrawMenuBar(HDC hDC
, LPRECT Rect
, HWND hWnd
, BOOL Draw
)
356 DWORD BufSize
, Items
, Items2
, hItems
;
359 SETMENUITEMRECT smir
;
360 RECT
*omir
, *mir
= NULL
;
363 mnu
= GetMenu(hWnd
); /* Fixme - pass menu handle as parameter */
364 /* get menu item list size */
365 BufSize
= NtUserBuildMenuItemList(mnu
, (VOID
*)1, 0, 0);
368 hHeap
= GetProcessHeap();
369 hBuf
= HeapAlloc(hHeap
, 0, BufSize
);
373 /* copy menu items into buffer */
374 Items
= Items2
= NtUserBuildMenuItemList(mnu
, Buf
, BufSize
, 0);
378 bottom
= line
= Rect
->top
;
379 smir
.fByPosition
= TRUE
;
381 /* calculate menu item rectangles */
387 mii
= (LPMENUITEMINFOW
)Buf
;
388 Buf
+= sizeof(MENUITEMINFOW
);
394 Buf
+= (mii
->cch
+ 1) * sizeof(WCHAR
);
400 mir
->left
= omir
->right
+ 1;
401 mir
->top
= omir
->top
;
402 mir
->right
+= mir
->left
;
403 mir
->bottom
+= mir
->top
;
407 mir
->left
= Rect
->left
;
408 mir
->top
= Rect
->top
;
410 if((mii
->fType
& MFT_RIGHTJUSTIFY
) && !milist
)
412 milist
= mih
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, Items
* sizeof(MENUITEMINFOW
*));
416 MeasureMenuItem(hWnd
, mnu
, hDC
, mii
, mir
, str
);
418 if((mir
->right
> Rect
->right
) || (mii
->fType
& (MFT_MENUBREAK
| MFT_MENUBARBREAK
)))
420 mir
->right
-= (mir
->left
- Rect
->left
);
421 mir
->left
= Rect
->left
;
424 line
= mir
->bottom
- mir
->top
;
430 NtUserSetMenuItemRect(mnu
, &smir
);
438 bottom
= max(bottom
, mir
->bottom
);
439 line
= max(line
, mir
->bottom
- mir
->top
);
442 /* align help menus to the right */
448 smir
.uItem
= Items2
- 1;
455 mii
= (MENUITEMINFOW
*)(*(--mih
));
456 mir
= (LPRECT
)(mii
+ 1);
458 if(omii
&& ((mir
->right
>= x
) || (omii
->fType
& (MFT_MENUBREAK
| MFT_MENUBARBREAK
))))
463 wd
= (mir
->right
- mir
->left
);
465 mir
->left
= mir
->right
- wd
;
470 NtUserSetMenuItemRect(mnu
, &smir
);
477 HeapFree(GetProcessHeap(), 0, milist
);
479 bottom
= max(bottom
, Rect
->top
+ GetSystemMetrics(SM_CYMENU
));
480 if(bottom
- Rect
->top
> 0)
482 NtUserSetMenuBarHeight(mnu
, bottom
- Rect
->top
);
487 bottom
= Rect
->bottom
;
488 FillRect(hDC
, Rect
, GetSysColorBrush(COLOR_MENU
));
490 /* draw menu items */
493 mii
= (LPMENUITEMINFOW
)Buf
;
494 Buf
+= sizeof(MENUITEMINFOW
);
500 Buf
+= (mii
->cch
+ 1) * sizeof(WCHAR
);
504 /* DbgPrint("Draw menu item %ws at (%d, %d, %d, %d)\n", str, mir->left, mir->top, mir->right, mir->bottom); */
505 DrawMenuItem(hWnd
, mnu
, hDC
, mii
, mir
, str
);
510 HeapFree(hHeap
, 0, hBuf
);
513 return max(bottom
- Rect
->top
, GetSystemMetrics(SM_CYMENU
));
518 MenuTrackMouseMenuBar(HWND hWnd
, ULONG Ht
, POINT Pt
)
520 int Item
= NtUserMenuItemFromPoint(hWnd
, GetMenu(hWnd
), Pt
.x
, Pt
.y
);
530 MenuTrackKbdMenuBar(HWND hWnd
, ULONG wParam
, ULONG Key
)
534 /* FUNCTIONS *****************************************************************/
537 MenuIsStringItem(ULONG TypeData)
539 return((TypeData & MENU_TYPE_MASK) == MF_STRING);
547 AppendMenuA(HMENU hMenu
,
552 return(InsertMenuA(hMenu
, -1, uFlags
| MF_BYPOSITION
, uIDNewItem
,
561 AppendMenuW(HMENU hMenu
,
566 return(InsertMenuW(hMenu
, -1, uFlags
| MF_BYPOSITION
, uIDNewItem
,
575 CheckMenuItem(HMENU hmenu
,
579 return NtUserCheckMenuItem(hmenu
, uIDCheckItem
, uCheck
);
587 CheckMenuRadioItem(HMENU hmenu
,
604 return NtUserCreateMenu(FALSE
);
612 CreatePopupMenu(VOID
)
614 return NtUserCreateMenu(TRUE
);
622 DeleteMenu(HMENU hMenu
,
626 return NtUserDeleteMenu(hMenu
, uPosition
, uFlags
);
634 DestroyMenu(HMENU hMenu
)
636 return NtUserDestroyMenu(hMenu
);
644 DrawMenuBar(HWND hWnd
)
647 /* FIXME - return NtUserCallHwndLock(hWnd, 0x55); */
656 EnableMenuItem(HMENU hMenu
,
660 return NtUserEnableMenuItem(hMenu
, uIDEnableItem
, uEnable
);
670 guii
.cbSize
= sizeof(GUITHREADINFO
);
671 if(GetGUIThreadInfo(GetCurrentThreadId(), &guii
) && guii
.hwndMenuOwner
)
673 PostMessageW(guii
.hwndMenuOwner
, WM_CANCELMODE
, 0, 0);
685 return NtUserGetMenu(hWnd
);
693 GetMenuBarInfo(HWND hwnd
,
698 return (BOOL
)NtUserGetMenuBarInfo(hwnd
, idObject
, idItem
, pmbi
);
706 GetMenuCheckMarkDimensions(VOID
)
708 return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK
),
709 GetSystemMetrics(SM_CYMENUCHECK
)));
717 GetMenuDefaultItem(HMENU hMenu
,
721 return NtUserGetMenuDefaultItem(hMenu
, fByPos
, gmdiFlags
);
729 GetMenuInfo(HMENU hmenu
,
735 if(!lpcmi
|| (lpcmi
->cbSize
!= sizeof(MENUINFO
)))
738 RtlZeroMemory(&mi
, sizeof(MENUINFO
));
739 mi
.cbSize
= sizeof(MENUINFO
);
740 mi
.fMask
= lpcmi
->fMask
;
742 res
= NtUserMenuInfo(hmenu
, &mi
, FALSE
);
744 memcpy(lpcmi
, &mi
, sizeof(MENUINFO
));
753 GetMenuItemCount(HMENU hMenu
)
755 return NtUserBuildMenuItemList(hMenu
, NULL
, 0, 0);
763 GetMenuItemID(HMENU hMenu
,
768 mii
.cbSize
= sizeof(MENUITEMINFOW
);
769 mii
.fMask
= MIIM_ID
| MIIM_SUBMENU
;
771 if(!NtUserMenuItemInfo(hMenu
, nPos
, MF_BYPOSITION
, &mii
, FALSE
))
776 if(mii
.hSubMenu
) return -1;
777 if(mii
.wID
== 0) return -1;
791 LPMENUITEMINFOA lpmii
)
807 LPMENUITEMINFOW lpmii
)
818 GetMenuItemRect(HWND hWnd
,
839 mii
.cbSize
= sizeof(MENUITEMINFOW
);
840 mii
.fMask
= MIIM_STATE
| MIIM_TYPE
| MIIM_SUBMENU
;
843 if(NtUserMenuItemInfo(hMenu
, uId
, uFlags
, &mii
, FALSE
))
848 nSubItems
= (UINT
)NtUserBuildMenuItemList(mii
.hSubMenu
, NULL
, 0, 0);
850 /* FIXME - ported from wine, does that work (0xff)? */
851 if(GetLastError() != ERROR_INVALID_MENU_HANDLE
)
852 return (nSubItems
<< 8) | ((mii
.fState
| mii
.fType
) & 0xff);
854 return (UINT
)-1; /* Invalid submenu */
857 /* FIXME - ported from wine, does that work? */
858 return (mii
.fType
| mii
.fState
);
909 mi
.cbSize
= sizeof(mi
);
910 mi
.fMask
= MIIM_SUBMENU
;
911 if(NtUserMenuItemInfo(hMenu
, (UINT
)nPos
, MF_BYPOSITION
, &mi
, FALSE
))
930 return NtUserHiliteMenuItem(hwnd
, hmenu
, uItemHilite
, uHilite
);
947 mii
.cbSize
= sizeof(MENUITEMINFOA
);
948 mii
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
;
950 mii
.fState
= MFS_ENABLED
;
952 if(uFlags
& MF_BITMAP
)
954 mii
.fType
|= MFT_BITMAP
;
956 else if(uFlags
& MF_OWNERDRAW
)
958 mii
.fType
|= MFT_OWNERDRAW
;
961 if(uFlags
& MF_RIGHTJUSTIFY
)
963 mii
.fType
|= MFT_RIGHTJUSTIFY
;
965 if(uFlags
& MF_MENUBREAK
)
967 mii
.fType
|= MFT_MENUBREAK
;
969 if(uFlags
& MF_MENUBARBREAK
)
971 mii
.fType
|= MFT_MENUBARBREAK
;
973 if(uFlags
& MF_DISABLED
)
975 mii
.fState
|= MFS_DISABLED
;
977 if(uFlags
& MF_GRAYED
)
979 mii
.fState
|= MFS_GRAYED
;
982 mii
.dwTypeData
= (LPSTR
)lpNewItem
;
983 if(uFlags
& MF_POPUP
)
985 mii
.fMask
|= MIIM_SUBMENU
;
986 mii
.hSubMenu
= (HMENU
)uIDNewItem
;
990 mii
.fMask
|= MIIM_ID
;
991 mii
.wID
= (UINT
)uIDNewItem
;
993 return InsertMenuItemA(hMenu
, uPosition
, (BOOL
)!(MF_BYPOSITION
& uFlags
), &mii
);
1006 LPCMENUITEMINFOA lpmii
)
1009 UNICODE_STRING MenuText
;
1011 BOOL CleanHeap
= FALSE
;
1014 if((lpmii
->cbSize
== sizeof(MENUITEMINFOA
)) ||
1015 (lpmii
->cbSize
== sizeof(MENUITEMINFOA
) - sizeof(HBITMAP
)))
1017 RtlMoveMemory ( &mi
, lpmii
, lpmii
->cbSize
);
1019 /* copy the text string */
1020 if((mi
.fMask
& (MIIM_TYPE
| MIIM_STRING
)) &&
1021 (MENU_ITEM_TYPE(mi
.fType
) == MF_STRING
) && mi
.dwTypeData
)
1023 Status
= HEAP_strdupAtoW ( &mi
.dwTypeData
, (LPCSTR
)mi
.dwTypeData
, &mi
.cch
);
1024 if (!NT_SUCCESS (Status
))
1026 SetLastError (RtlNtStatusToDosError(Status
));
1029 RtlInitUnicodeString(&MenuText
, (PWSTR
)mi
.dwTypeData
);
1030 mi
.dwTypeData
= (LPWSTR
)&MenuText
;
1034 res
= NtUserInsertMenuItem(hMenu
, uItem
, fByPosition
, &mi
);
1036 if ( CleanHeap
) HEAP_free ( mi
.dwTypeData
);
1051 LPCMENUITEMINFOW lpmii
)
1054 UNICODE_STRING MenuText
;
1056 BOOL CleanHeap
= FALSE
;
1057 HANDLE hHeap
= RtlGetProcessHeap();
1058 mi
.hbmpItem
= (HBITMAP
)0;
1060 // while we could just pass 'lpmii' to win32k, we make a copy so that
1061 // if a bad user passes bad data, we crash his process instead of the
1064 if((lpmii
->cbSize
== sizeof(MENUITEMINFOW
)) ||
1065 (lpmii
->cbSize
== sizeof(MENUITEMINFOW
) - sizeof(HBITMAP
)))
1067 memcpy(&mi
, lpmii
, lpmii
->cbSize
);
1069 /* copy the text string */
1070 if((mi
.fMask
& (MIIM_TYPE
| MIIM_STRING
)) &&
1071 (MENU_ITEM_TYPE(mi
.fType
) == MF_STRING
) && mi
.dwTypeData
)
1075 if(!RtlCreateUnicodeString(&MenuText
, (PWSTR
)lpmii
->dwTypeData
))
1077 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY
));
1080 mi
.dwTypeData
= (LPWSTR
)&MenuText
;
1081 mi
.cch
= MenuText
.Length
/ sizeof(WCHAR
);
1086 res
= NtUserInsertMenuItem(hMenu
, uItem
, fByPosition
, &mi
);
1088 if(CleanHeap
) RtlFreeHeap (hHeap
, 0, mi
.dwTypeData
);
1103 UINT_PTR uIDNewItem
,
1107 mii
.cbSize
= sizeof(MENUITEMINFOW
);
1108 mii
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
;
1110 mii
.fState
= MFS_ENABLED
;
1112 if(uFlags
& MF_BITMAP
)
1114 mii
.fType
|= MFT_BITMAP
;
1116 else if(uFlags
& MF_OWNERDRAW
)
1118 mii
.fType
|= MFT_OWNERDRAW
;
1121 if(uFlags
& MF_RIGHTJUSTIFY
)
1123 mii
.fType
|= MFT_RIGHTJUSTIFY
;
1125 if(uFlags
& MF_MENUBREAK
)
1127 mii
.fType
|= MFT_MENUBREAK
;
1129 if(uFlags
& MF_MENUBARBREAK
)
1131 mii
.fType
|= MFT_MENUBARBREAK
;
1133 if(uFlags
& MF_DISABLED
)
1135 mii
.fState
|= MFS_DISABLED
;
1137 if(uFlags
& MF_GRAYED
)
1139 mii
.fState
|= MFS_GRAYED
;
1142 mii
.dwTypeData
= (LPWSTR
)lpNewItem
;
1143 if(uFlags
& MF_POPUP
)
1145 mii
.fMask
|= MIIM_SUBMENU
;
1146 mii
.hSubMenu
= (HMENU
)uIDNewItem
;
1150 mii
.fMask
|= MIIM_ID
;
1151 mii
.wID
= (UINT
)uIDNewItem
;
1153 return InsertMenuItemW(hMenu
, uPosition
, (BOOL
)!(MF_BYPOSITION
& uFlags
), &mii
);
1166 SetLastError(ERROR_SUCCESS
);
1167 ret
= NtUserBuildMenuItemList(hMenu
, NULL
, 0, 0);
1168 return ((ret
== (DWORD
)-1) || (GetLastError() == ERROR_INVALID_MENU_HANDLE
));
1176 LoadMenuA(HINSTANCE hInstance
,
1179 HANDLE Resource
= FindResourceA(hInstance
, lpMenuName
, MAKEINTRESOURCEA(4));
1180 if (Resource
== NULL
)
1184 return(LoadMenuIndirectA((PVOID
)LoadResource(hInstance
, Resource
)));
1192 LoadMenuIndirectA(CONST MENUTEMPLATE
*lpMenuTemplate
)
1194 return(LoadMenuIndirectW(lpMenuTemplate
));
1202 LoadMenuIndirectW(CONST MENUTEMPLATE
*lpMenuTemplate
)
1205 WORD version
, offset
;
1206 LPCSTR p
= (LPCSTR
)lpMenuTemplate
;
1208 version
= GET_WORD(p
);
1213 case 0: /* standard format is version of 0 */
1214 offset
= GET_WORD(p
);
1215 p
+= sizeof(WORD
) + offset
;
1216 if (!(hMenu
= CreateMenu())) return 0;
1217 if (!MENU_ParseResource(p
, hMenu
, TRUE
))
1223 case 1: /* extended format is version of 1 */
1224 offset
= GET_WORD(p
);
1225 p
+= sizeof(WORD
) + offset
;
1226 if (!(hMenu
= CreateMenu())) return 0;
1227 if (!MENUEX_ParseResource(p
, hMenu
))
1229 DestroyMenu( hMenu
);
1234 DbgPrint("LoadMenuIndirectW(): version %d not supported.\n", version
);
1244 LoadMenuW(HINSTANCE hInstance
,
1247 HANDLE Resource
= FindResourceW(hInstance
, lpMenuName
, RT_MENU
);
1248 if (Resource
== NULL
)
1252 return(LoadMenuIndirectW((PVOID
)LoadResource(hInstance
, Resource
)));
1266 return NtUserMenuItemFromPoint(hWnd
, hMenu
, ptScreen
.x
, ptScreen
.y
);
1279 UINT_PTR uIDNewItem
,
1296 UINT_PTR uIDNewItem
,
1314 return NtUserRemoveMenu(hMenu
, uPosition
, uFlags
);
1325 return NtUserSetMenu(hWnd
, hMenu
, TRUE
);
1339 return NtUserSetMenuDefaultItem(hMenu
, uItem
, fByPos
);
1354 if(lpcmi
->cbSize
!= sizeof(MENUINFO
))
1357 memcpy(&mi
, lpcmi
, sizeof(MENUINFO
));
1358 return NtUserMenuInfo(hmenu
, &mi
, TRUE
);
1371 HBITMAP hBitmapUnchecked
,
1372 HBITMAP hBitmapChecked
)
1388 LPMENUITEMINFOA lpmii
)
1404 LPMENUITEMINFOW lpmii
)
1423 CONST RECT
*prcRect
)
1429 tpm
.cbSize
= sizeof(TPMPARAMS
);
1430 tpm
.rcExclude
= *prcRect
;
1433 return (BOOL
)NtUserTrackPopupMenuEx(hMenu
, uFlags
, x
, y
, hWnd
,
1434 (prcRect
? &tpm
: NULL
));
1451 return (BOOL
)NtUserTrackPopupMenuEx(hmenu
, fuFlags
, x
, y
, hwnd
, lptpm
);
1460 SetMenuContextHelpId(HMENU hmenu
,
1461 DWORD dwContextHelpId
)
1463 return NtUserSetMenuContextHelpId(hmenu
, dwContextHelpId
);
1472 GetMenuContextHelpId(HMENU hmenu
)
1475 mi
.cbSize
= sizeof(MENUINFO
);
1476 mi
.fMask
= MIM_HELPID
;
1478 if(NtUserMenuInfo(hmenu
, &mi
, FALSE
))
1480 return mi
.dwContextHelpID
;
1542 LPCWSTR lpszNewItem
,