4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994 Alexandre Julliard
6 * Copyright 1997 Morten Welinder
7 * Copyright 2005 Maxime Bellengé
8 * Copyright 2006 Phil Krylov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Note: the style MF_MOUSESELECT is used to mark popup items that
27 * have been selected, i.e. their popup menu is currently displayed.
28 * This is probably not the meaning this style has in MS-Windows.
30 * Note 2: where there is a difference, these menu API's are according
31 * the behavior of Windows 2k and Windows XP. Known differences with
32 * Windows 9x/ME are documented in the comments, in case an application
33 * is found to depend on the old behavior.
50 #include "user_private.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(menu
);
56 #define MENU_ITEM_TYPE(flags) \
57 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
59 /* macro to test that flags do not indicate bitmap, ownerdraw or separator */
60 #define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
61 #define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
63 #define MENUITEMINFO_TYPE_MASK \
64 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
65 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
66 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
67 #define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
68 #define STATE_MASK (~TYPE_MASK)
69 #define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
72 /**********************************************************************
75 * Parse a standard menu resource and add items to the menu.
76 * Return a pointer to the end of the resource.
78 * NOTE: flags is equivalent to the mtOption field
80 static LPCSTR
MENU_ParseResource( LPCSTR res
, HMENU hMenu
)
88 flags
= GET_WORD(res
);
89 end_flag
= flags
& MF_END
;
90 /* Remove MF_END because it has the same value as MF_HILITE */
93 if (!(flags
& MF_POPUP
))
99 res
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
100 if (flags
& MF_POPUP
)
102 HMENU hSubMenu
= CreatePopupMenu();
103 if (!hSubMenu
) return NULL
;
104 if (!(res
= MENU_ParseResource( res
, hSubMenu
))) return NULL
;
105 AppendMenuW( hMenu
, flags
, (UINT_PTR
)hSubMenu
, str
);
107 else /* Not a popup */
109 AppendMenuW( hMenu
, flags
, id
, *str
? str
: NULL
);
116 /**********************************************************************
117 * MENUEX_ParseResource
119 * Parse an extended menu resource and add items to the menu.
120 * Return a pointer to the end of the resource.
122 static LPCSTR
MENUEX_ParseResource( LPCSTR res
, HMENU hMenu
)
128 mii
.cbSize
= sizeof(mii
);
129 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
;
130 mii
.fType
= GET_DWORD(res
);
131 res
+= sizeof(DWORD
);
132 mii
.fState
= GET_DWORD(res
);
133 res
+= sizeof(DWORD
);
134 mii
.wID
= GET_DWORD(res
);
135 res
+= sizeof(DWORD
);
136 resinfo
= GET_WORD(res
); /* FIXME: for 16-bit apps this is a byte. */
138 /* Align the text on a word boundary. */
139 res
+= (~((UINT_PTR
)res
- 1)) & 1;
140 mii
.dwTypeData
= (LPWSTR
) res
;
141 res
+= (1 + lstrlenW(mii
.dwTypeData
)) * sizeof(WCHAR
);
142 /* Align the following fields on a dword boundary. */
143 res
+= (~((UINT_PTR
)res
- 1)) & 3;
145 TRACE("Menu item: [%08x,%08x,%04x,%04x,%s]\n",
146 mii
.fType
, mii
.fState
, mii
.wID
, resinfo
, debugstr_w(mii
.dwTypeData
));
148 if (resinfo
& 1) { /* Pop-up? */
149 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
150 res
+= sizeof(DWORD
);
151 mii
.hSubMenu
= CreatePopupMenu();
154 if (!(res
= MENUEX_ParseResource(res
, mii
.hSubMenu
))) {
155 NtUserDestroyMenu( mii
.hSubMenu
);
158 mii
.fMask
|= MIIM_SUBMENU
;
159 mii
.fType
|= MF_POPUP
;
161 else if(!*mii
.dwTypeData
&& !(mii
.fType
& MF_SEPARATOR
))
163 WARN("Converting NULL menu item %04x, type %04x to SEPARATOR\n",
165 mii
.fType
|= MF_SEPARATOR
;
167 InsertMenuItemW(hMenu
, -1, MF_BYPOSITION
, &mii
);
168 } while (!(resinfo
& MF_END
));
173 /**********************************************************************
174 * TrackPopupMenu (USER32.@)
176 * Like the win32 API, the function return the command ID only if the
177 * flag TPM_RETURNCMD is on.
180 BOOL WINAPI
TrackPopupMenu( HMENU hMenu
, UINT wFlags
, INT x
, INT y
,
181 INT nReserved
, HWND hWnd
, const RECT
*lpRect
)
183 return NtUserTrackPopupMenuEx( hMenu
, wFlags
, x
, y
, hWnd
, NULL
);
186 /***********************************************************************
189 * NOTE: Windows has totally different (and undocumented) popup wndproc.
191 LRESULT WINAPI
PopupMenuWndProc( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
197 case WM_MOUSEACTIVATE
:
203 return NtUserMessageCall( hwnd
, message
, wParam
, lParam
,
204 NULL
, NtUserPopupMenuWndProc
, FALSE
);
207 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
213 /*******************************************************************
214 * ChangeMenuA (USER32.@)
216 BOOL WINAPI
ChangeMenuA( HMENU hMenu
, UINT pos
, LPCSTR data
,
217 UINT id
, UINT flags
)
219 TRACE("menu=%p pos=%d data=%p id=%08x flags=%08x\n", hMenu
, pos
, data
, id
, flags
);
220 if (flags
& MF_APPEND
) return AppendMenuA( hMenu
, flags
& ~MF_APPEND
,
222 if (flags
& MF_DELETE
) return NtUserDeleteMenu( hMenu
, pos
, flags
& ~MF_DELETE
);
223 if (flags
& MF_CHANGE
) return ModifyMenuA(hMenu
, pos
, flags
& ~MF_CHANGE
,
225 if (flags
& MF_REMOVE
) return NtUserRemoveMenu( hMenu
,
226 flags
& MF_BYPOSITION
? pos
: id
,
227 flags
& ~MF_REMOVE
);
228 /* Default: MF_INSERT */
229 return InsertMenuA( hMenu
, pos
, flags
, id
, data
);
233 /*******************************************************************
234 * ChangeMenuW (USER32.@)
236 BOOL WINAPI
ChangeMenuW( HMENU hMenu
, UINT pos
, LPCWSTR data
,
237 UINT id
, UINT flags
)
239 TRACE("menu=%p pos=%d data=%p id=%08x flags=%08x\n", hMenu
, pos
, data
, id
, flags
);
240 if (flags
& MF_APPEND
) return AppendMenuW( hMenu
, flags
& ~MF_APPEND
,
242 if (flags
& MF_DELETE
) return NtUserDeleteMenu( hMenu
, pos
, flags
& ~MF_DELETE
);
243 if (flags
& MF_CHANGE
) return ModifyMenuW(hMenu
, pos
, flags
& ~MF_CHANGE
,
245 if (flags
& MF_REMOVE
) return NtUserRemoveMenu( hMenu
,
246 flags
& MF_BYPOSITION
? pos
: id
,
247 flags
& ~MF_REMOVE
);
248 /* Default: MF_INSERT */
249 return InsertMenuW( hMenu
, pos
, flags
, id
, data
);
253 /*******************************************************************
254 * GetMenuStringA (USER32.@)
256 INT WINAPI
GetMenuStringA( HMENU menu
, UINT item
, char *str
, INT count
, UINT flags
)
261 TRACE( "menu=%p item=%04x ptr=%p len=%d flags=%04x\n", menu
, item
, str
, count
, flags
);
263 info
.cbSize
= sizeof(info
);
264 info
.fMask
= MIIM_STRING
;
265 info
.dwTypeData
= str
;
267 ret
= NtUserThunkedMenuItemInfo( menu
, item
, flags
, NtUserGetMenuItemInfoA
,
268 (MENUITEMINFOW
*)&info
, NULL
);
269 if (ret
) ret
= info
.cch
;
270 TRACE( "returning %s %d\n", debugstr_a( str
), ret
);
275 /*******************************************************************
276 * GetMenuStringW (USER32.@)
278 INT WINAPI
GetMenuStringW( HMENU menu
, UINT item
, WCHAR
*str
, INT count
, UINT flags
)
283 TRACE( "menu=%p item=%04x ptr=%p len=%d flags=%04x\n", menu
, item
, str
, count
, flags
);
285 info
.cbSize
= sizeof(info
);
286 info
.fMask
= MIIM_STRING
;
287 info
.dwTypeData
= str
;
289 ret
= NtUserThunkedMenuItemInfo( menu
, item
, flags
, NtUserGetMenuItemInfoW
, &info
, NULL
);
290 if (ret
) ret
= info
.cch
;
291 TRACE( "returning %s %d\n", debugstr_w( str
), ret
);
296 /**********************************************************************
297 * GetMenuState (USER32.@)
299 UINT WINAPI
GetMenuState( HMENU menu
, UINT item
, UINT flags
)
301 return NtUserThunkedMenuItemInfo( menu
, item
, flags
, NtUserGetMenuState
, NULL
, NULL
);
305 /**********************************************************************
306 * GetMenuItemCount (USER32.@)
308 INT WINAPI
GetMenuItemCount( HMENU menu
)
310 return NtUserGetMenuItemCount( menu
);
314 /**********************************************************************
315 * GetMenuItemID (USER32.@)
317 UINT WINAPI
GetMenuItemID( HMENU menu
, INT pos
)
319 return NtUserThunkedMenuItemInfo( menu
, pos
, MF_BYPOSITION
, NtUserGetMenuItemID
, NULL
, NULL
);
323 /**********************************************************************
326 * Uses flags, id and text ptr, passed by InsertMenu() and
327 * ModifyMenu() to setup a MenuItemInfo structure.
329 static void MENU_mnu2mnuii( UINT flags
, UINT_PTR id
, LPCWSTR str
,
330 LPMENUITEMINFOW pmii
)
332 ZeroMemory( pmii
, sizeof( MENUITEMINFOW
));
333 pmii
->cbSize
= sizeof( MENUITEMINFOW
);
334 pmii
->fMask
= MIIM_STATE
| MIIM_ID
| MIIM_FTYPE
;
335 /* setting bitmap clears text and vice versa */
336 if( IS_STRING_ITEM(flags
)) {
337 pmii
->fMask
|= MIIM_STRING
| MIIM_BITMAP
;
339 flags
|= MF_SEPARATOR
;
340 /* Item beginning with a backspace is a help item */
341 /* FIXME: wrong place, this is only true in win16 */
342 else if( *str
== '\b') {
346 pmii
->dwTypeData
= (LPWSTR
)str
;
347 } else if( flags
& MFT_BITMAP
){
348 pmii
->fMask
|= MIIM_BITMAP
| MIIM_STRING
;
349 pmii
->hbmpItem
= (HBITMAP
)str
;
351 if( flags
& MF_OWNERDRAW
){
352 pmii
->fMask
|= MIIM_DATA
;
353 pmii
->dwItemData
= (ULONG_PTR
) str
;
355 if ((flags
& MF_POPUP
) && IsMenu( UlongToHandle( id
)))
357 pmii
->fMask
|= MIIM_SUBMENU
;
358 pmii
->hSubMenu
= (HMENU
)id
;
360 if( flags
& MF_SEPARATOR
) flags
|= MF_GRAYED
| MF_DISABLED
;
361 pmii
->fState
= flags
& MENUITEMINFO_STATE_MASK
& ~MFS_DEFAULT
;
362 pmii
->fType
= flags
& MENUITEMINFO_TYPE_MASK
;
363 pmii
->wID
= (UINT
)id
;
367 /*******************************************************************
368 * InsertMenuW (USER32.@)
370 BOOL WINAPI
InsertMenuW( HMENU hMenu
, UINT pos
, UINT flags
,
371 UINT_PTR id
, LPCWSTR str
)
375 if (IS_STRING_ITEM(flags
) && str
)
376 TRACE("hMenu %p, pos %d, flags %08x, id %04Ix, str %s\n",
377 hMenu
, pos
, flags
, id
, debugstr_w(str
) );
378 else TRACE("hMenu %p, pos %d, flags %08x, id %04Ix, str %p (not a string)\n",
379 hMenu
, pos
, flags
, id
, str
);
381 MENU_mnu2mnuii( flags
, id
, str
, &mii
);
382 mii
.fMask
|= MIIM_CHECKMARKS
;
383 return NtUserThunkedMenuItemInfo( hMenu
, pos
, flags
, NtUserInsertMenuItem
, &mii
, NULL
);
387 /*******************************************************************
388 * InsertMenuA (USER32.@)
390 BOOL WINAPI
InsertMenuA( HMENU hMenu
, UINT pos
, UINT flags
,
391 UINT_PTR id
, LPCSTR str
)
395 if (IS_STRING_ITEM(flags
) && str
)
397 INT len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
398 LPWSTR newstr
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
401 MultiByteToWideChar( CP_ACP
, 0, str
, -1, newstr
, len
);
402 ret
= InsertMenuW( hMenu
, pos
, flags
, id
, newstr
);
403 HeapFree( GetProcessHeap(), 0, newstr
);
407 else return InsertMenuW( hMenu
, pos
, flags
, id
, (LPCWSTR
)str
);
411 /*******************************************************************
412 * AppendMenuA (USER32.@)
414 BOOL WINAPI
AppendMenuA( HMENU hMenu
, UINT flags
,
415 UINT_PTR id
, LPCSTR data
)
417 return InsertMenuA( hMenu
, -1, flags
| MF_BYPOSITION
, id
, data
);
421 /*******************************************************************
422 * AppendMenuW (USER32.@)
424 BOOL WINAPI
AppendMenuW( HMENU hMenu
, UINT flags
,
425 UINT_PTR id
, LPCWSTR data
)
427 return InsertMenuW( hMenu
, -1, flags
| MF_BYPOSITION
, id
, data
);
431 /*******************************************************************
432 * ModifyMenuW (USER32.@)
434 BOOL WINAPI
ModifyMenuW( HMENU hMenu
, UINT pos
, UINT flags
,
435 UINT_PTR id
, LPCWSTR str
)
439 if (IS_STRING_ITEM(flags
))
440 TRACE("%p %d %04x %04Ix %s\n", hMenu
, pos
, flags
, id
, debugstr_w(str
) );
442 TRACE("%p %d %04x %04Ix %p\n", hMenu
, pos
, flags
, id
, str
);
444 MENU_mnu2mnuii( flags
, id
, str
, &mii
);
445 return NtUserThunkedMenuItemInfo( hMenu
, pos
, flags
, NtUserSetMenuItemInfo
, &mii
, NULL
);
449 /*******************************************************************
450 * ModifyMenuA (USER32.@)
452 BOOL WINAPI
ModifyMenuA( HMENU hMenu
, UINT pos
, UINT flags
,
453 UINT_PTR id
, LPCSTR str
)
457 if (IS_STRING_ITEM(flags
) && str
)
459 INT len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
460 LPWSTR newstr
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
463 MultiByteToWideChar( CP_ACP
, 0, str
, -1, newstr
, len
);
464 ret
= ModifyMenuW( hMenu
, pos
, flags
, id
, newstr
);
465 HeapFree( GetProcessHeap(), 0, newstr
);
469 else return ModifyMenuW( hMenu
, pos
, flags
, id
, (LPCWSTR
)str
);
473 /**********************************************************************
474 * CreatePopupMenu (USER32.@)
476 HMENU WINAPI
CreatePopupMenu(void)
478 return NtUserCreateMenu( TRUE
);
482 /**********************************************************************
483 * GetMenuCheckMarkDimensions (USER.417)
484 * GetMenuCheckMarkDimensions (USER32.@)
486 DWORD WINAPI
GetMenuCheckMarkDimensions(void)
488 return MAKELONG( GetSystemMetrics(SM_CXMENUCHECK
), GetSystemMetrics(SM_CYMENUCHECK
) );
492 /**********************************************************************
493 * SetMenuItemBitmaps (USER32.@)
495 BOOL WINAPI
SetMenuItemBitmaps( HMENU menu
, UINT pos
, UINT flags
, HBITMAP uncheck
, HBITMAP check
)
499 info
.cbSize
= sizeof(info
);
500 info
.fMask
= MIIM_STATE
;
501 if (!NtUserThunkedMenuItemInfo( menu
, pos
, flags
, NtUserGetMenuItemInfoW
, &info
, NULL
))
504 info
.fMask
= MIIM_STATE
| MIIM_CHECKMARKS
;
505 info
.hbmpChecked
= check
;
506 info
.hbmpUnchecked
= uncheck
;
507 if (check
|| uncheck
) info
.fState
|= MF_USECHECKBITMAPS
;
508 else info
.fState
&= ~MF_USECHECKBITMAPS
;
509 return NtUserThunkedMenuItemInfo( menu
, pos
, flags
, NtUserSetMenuItemInfo
, &info
, NULL
);
513 /**********************************************************************
514 * CreateMenu (USER32.@)
516 HMENU WINAPI
CreateMenu(void)
518 return NtUserCreateMenu( FALSE
);
522 /**********************************************************************
525 HMENU WINAPI
GetMenu( HWND hWnd
)
527 HMENU retvalue
= (HMENU
)GetWindowLongPtrW( hWnd
, GWLP_ID
);
528 TRACE("for %p returning %p\n", hWnd
, retvalue
);
533 /**********************************************************************
534 * GetSubMenu (USER32.@)
536 HMENU WINAPI
GetSubMenu( HMENU menu
, INT pos
)
538 UINT ret
= NtUserThunkedMenuItemInfo( menu
, pos
, MF_BYPOSITION
, NtUserGetSubMenu
, NULL
, NULL
);
539 return UlongToHandle( ret
);
543 /**********************************************************************
544 * DrawMenuBar (USER32.@)
546 BOOL WINAPI
DrawMenuBar( HWND hwnd
)
548 return NtUserDrawMenuBar( hwnd
);
552 /*****************************************************************
553 * LoadMenuA (USER32.@)
555 HMENU WINAPI
LoadMenuA( HINSTANCE instance
, LPCSTR name
)
557 HRSRC hrsrc
= FindResourceA( instance
, name
, (LPSTR
)RT_MENU
);
558 if (!hrsrc
) return 0;
559 return LoadMenuIndirectA( LoadResource( instance
, hrsrc
));
563 /*****************************************************************
564 * LoadMenuW (USER32.@)
566 HMENU WINAPI
LoadMenuW( HINSTANCE instance
, LPCWSTR name
)
568 HRSRC hrsrc
= FindResourceW( instance
, name
, (LPWSTR
)RT_MENU
);
569 if (!hrsrc
) return 0;
570 return LoadMenuIndirectW( LoadResource( instance
, hrsrc
));
574 /**********************************************************************
575 * LoadMenuIndirectW (USER32.@)
577 HMENU WINAPI
LoadMenuIndirectW( LPCVOID
template )
580 WORD version
, offset
;
583 version
= GET_WORD(p
);
585 TRACE("%p, ver %d\n", template, version
);
588 case 0: /* standard format is version of 0 */
589 offset
= GET_WORD(p
);
590 p
+= sizeof(WORD
) + offset
;
591 if (!(hMenu
= CreateMenu())) return 0;
592 if (!MENU_ParseResource( p
, hMenu
))
594 NtUserDestroyMenu( hMenu
);
598 case 1: /* extended format is version of 1 */
599 offset
= GET_WORD(p
);
600 p
+= sizeof(WORD
) + offset
;
601 if (!(hMenu
= CreateMenu())) return 0;
602 if (!MENUEX_ParseResource( p
, hMenu
))
604 NtUserDestroyMenu( hMenu
);
609 ERR("version %d not supported.\n", version
);
615 /**********************************************************************
616 * LoadMenuIndirectA (USER32.@)
618 HMENU WINAPI
LoadMenuIndirectA( LPCVOID
template )
620 return LoadMenuIndirectW( template );
624 /**********************************************************************
627 BOOL WINAPI
IsMenu( HMENU menu
)
631 info
.cbSize
= sizeof(info
);
633 if (GetMenuInfo( menu
, &info
)) return TRUE
;
635 SetLastError(ERROR_INVALID_MENU_HANDLE
);
640 /**********************************************************************
641 * GetMenuItemInfoA (USER32.@)
643 BOOL WINAPI
GetMenuItemInfoA( HMENU hmenu
, UINT item
, BOOL bypos
,
644 LPMENUITEMINFOA lpmii
)
648 if( lpmii
->cbSize
!= sizeof( mii
) &&
649 lpmii
->cbSize
!= sizeof( mii
) - sizeof ( mii
.hbmpItem
)) {
650 SetLastError( ERROR_INVALID_PARAMETER
);
653 memcpy( &mii
, lpmii
, lpmii
->cbSize
);
654 mii
.cbSize
= sizeof( mii
);
655 ret
= NtUserThunkedMenuItemInfo( hmenu
, item
, bypos
? MF_BYPOSITION
: 0,
656 NtUserGetMenuItemInfoA
, (MENUITEMINFOW
*)&mii
, NULL
);
657 mii
.cbSize
= lpmii
->cbSize
;
658 memcpy( lpmii
, &mii
, mii
.cbSize
);
662 /**********************************************************************
663 * GetMenuItemInfoW (USER32.@)
665 BOOL WINAPI
GetMenuItemInfoW( HMENU hmenu
, UINT item
, BOOL bypos
,
666 LPMENUITEMINFOW lpmii
)
670 if( lpmii
->cbSize
!= sizeof( mii
) &&
671 lpmii
->cbSize
!= sizeof( mii
) - sizeof ( mii
.hbmpItem
)) {
672 SetLastError( ERROR_INVALID_PARAMETER
);
675 memcpy( &mii
, lpmii
, lpmii
->cbSize
);
676 mii
.cbSize
= sizeof( mii
);
677 ret
= NtUserThunkedMenuItemInfo( hmenu
, item
, bypos
? MF_BYPOSITION
: 0,
678 NtUserGetMenuItemInfoW
, &mii
, NULL
);
679 mii
.cbSize
= lpmii
->cbSize
;
680 memcpy( lpmii
, &mii
, mii
.cbSize
);
685 /**********************************************************************
686 * MENU_NormalizeMenuItemInfoStruct
688 * Helper for SetMenuItemInfo and InsertMenuItemInfo:
689 * check, copy and extend the MENUITEMINFO struct from the version that the application
690 * supplied to the version used by wine source. */
691 static BOOL
MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW
*pmii_in
,
692 MENUITEMINFOW
*pmii_out
)
694 /* do we recognize the size? */
695 if( !pmii_in
|| (pmii_in
->cbSize
!= sizeof( MENUITEMINFOW
) &&
696 pmii_in
->cbSize
!= sizeof( MENUITEMINFOW
) - sizeof( pmii_in
->hbmpItem
)) ) {
697 SetLastError( ERROR_INVALID_PARAMETER
);
700 /* copy the fields that we have */
701 memcpy( pmii_out
, pmii_in
, pmii_in
->cbSize
);
702 /* if the hbmpItem member is missing then extend */
703 if( pmii_in
->cbSize
!= sizeof( MENUITEMINFOW
)) {
704 pmii_out
->cbSize
= sizeof( MENUITEMINFOW
);
705 pmii_out
->hbmpItem
= NULL
;
707 /* test for invalid bit combinations */
708 if( (pmii_out
->fMask
& MIIM_TYPE
&&
709 pmii_out
->fMask
& (MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
)) ||
710 (pmii_out
->fMask
& MIIM_FTYPE
&& pmii_out
->fType
& MFT_BITMAP
)) {
711 WARN("invalid combination of fMask bits used\n");
712 /* this does not happen on Win9x/ME */
713 SetLastError( ERROR_INVALID_PARAMETER
);
716 /* convert old style (MIIM_TYPE) to the new */
717 if( pmii_out
->fMask
& MIIM_TYPE
){
718 pmii_out
->fMask
|= MIIM_FTYPE
;
719 if( IS_STRING_ITEM(pmii_out
->fType
)){
720 pmii_out
->fMask
|= MIIM_STRING
;
721 } else if( (pmii_out
->fType
) & MFT_BITMAP
){
722 pmii_out
->fMask
|= MIIM_BITMAP
;
723 pmii_out
->hbmpItem
= UlongToHandle(LOWORD(pmii_out
->dwTypeData
));
729 /**********************************************************************
730 * SetMenuItemInfoA (USER32.@)
732 BOOL WINAPI
SetMenuItemInfoA(HMENU hmenu
, UINT item
, BOOL bypos
,
733 const MENUITEMINFOA
*lpmii
)
739 TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu
, item
, bypos
, lpmii
);
741 if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW
*)lpmii
, &mii
)) return FALSE
;
743 if ((mii
.fMask
& MIIM_STRING
) && mii
.dwTypeData
)
745 const char *str
= (const char *)mii
.dwTypeData
;
746 UINT len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
747 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
748 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
749 mii
.dwTypeData
= strW
;
752 ret
= NtUserThunkedMenuItemInfo( hmenu
, item
, bypos
? MF_BYPOSITION
: 0,
753 NtUserSetMenuItemInfo
, &mii
, NULL
);
755 HeapFree( GetProcessHeap(), 0, strW
);
759 /**********************************************************************
760 * SetMenuItemInfoW (USER32.@)
762 BOOL WINAPI
SetMenuItemInfoW(HMENU hmenu
, UINT item
, BOOL bypos
,
763 const MENUITEMINFOW
*lpmii
)
767 TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu
, item
, bypos
, lpmii
);
769 if (!MENU_NormalizeMenuItemInfoStruct( lpmii
, &mii
)) return FALSE
;
771 return NtUserThunkedMenuItemInfo( hmenu
, item
, bypos
? MF_BYPOSITION
: 0,
772 NtUserSetMenuItemInfo
, &mii
, NULL
);
775 /**********************************************************************
776 * GetMenuDefaultItem (USER32.@)
778 UINT WINAPI
GetMenuDefaultItem( HMENU menu
, UINT bypos
, UINT flags
)
780 return NtUserThunkedMenuItemInfo( menu
, bypos
, flags
, NtUserGetMenuDefaultItem
, NULL
, NULL
);
784 /**********************************************************************
785 * InsertMenuItemA (USER32.@)
787 BOOL WINAPI
InsertMenuItemA(HMENU hMenu
, UINT uItem
, BOOL bypos
,
788 const MENUITEMINFOA
*lpmii
)
794 TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu
, uItem
, bypos
, lpmii
);
796 if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW
*)lpmii
, &mii
)) return FALSE
;
798 if ((mii
.fMask
& MIIM_STRING
) && mii
.dwTypeData
)
800 const char *str
= (const char *)mii
.dwTypeData
;
801 UINT len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
802 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
803 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
804 mii
.dwTypeData
= strW
;
807 ret
= NtUserThunkedMenuItemInfo( hMenu
, uItem
, bypos
? MF_BYPOSITION
: 0,
808 NtUserInsertMenuItem
, &mii
, NULL
);
810 HeapFree( GetProcessHeap(), 0, strW
);
815 /**********************************************************************
816 * InsertMenuItemW (USER32.@)
818 BOOL WINAPI
InsertMenuItemW(HMENU hMenu
, UINT uItem
, BOOL bypos
,
819 const MENUITEMINFOW
*lpmii
)
823 TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu
, uItem
, bypos
, lpmii
);
825 if (!MENU_NormalizeMenuItemInfoStruct( lpmii
, &mii
)) return FALSE
;
827 return NtUserThunkedMenuItemInfo( hMenu
, uItem
, bypos
? MF_BYPOSITION
: 0,
828 NtUserInsertMenuItem
, &mii
, NULL
);
831 /**********************************************************************
832 * CheckMenuRadioItem (USER32.@)
834 BOOL WINAPI
CheckMenuRadioItem( HMENU menu
, UINT first
, UINT last
, UINT check
, UINT flags
)
836 MENUITEMINFOW info
; /* abuse to pass last and check */
839 return NtUserThunkedMenuItemInfo( menu
, first
, flags
, NtUserCheckMenuRadioItem
, &info
, NULL
);
843 /**********************************************************************
844 * SetMenuInfo (USER32.@)
846 BOOL WINAPI
SetMenuInfo( HMENU menu
, const MENUINFO
*info
)
848 TRACE( "(%p %p)\n", menu
, info
);
850 if (!info
|| info
->cbSize
!= sizeof(*info
))
852 SetLastError( ERROR_INVALID_PARAMETER
);
856 return NtUserThunkedMenuInfo( menu
, info
);
859 /**********************************************************************
860 * GetMenuInfo (USER32.@)
862 BOOL WINAPI
GetMenuInfo( HMENU menu
, MENUINFO
*info
)
864 return NtUserGetMenuInfo( menu
, info
);
868 /**********************************************************************
869 * GetMenuContextHelpId (USER32.@)
871 DWORD WINAPI
GetMenuContextHelpId( HMENU menu
)
874 TRACE( "(%p)\n", menu
);
875 info
.cbSize
= sizeof(info
);
876 info
.fMask
= MIM_HELPID
;
877 return GetMenuInfo( menu
, &info
) ? info
.dwContextHelpID
: 0;
880 /**********************************************************************
881 * MenuItemFromPoint (USER32.@)
883 INT WINAPI
MenuItemFromPoint( HWND hwnd
, HMENU menu
, POINT pt
)
885 return NtUserMenuItemFromPoint( hwnd
, menu
, pt
.x
, pt
.y
);
889 /**********************************************************************
890 * CalcMenuBar (USER32.@)
892 DWORD WINAPI
CalcMenuBar(HWND hwnd
, DWORD left
, DWORD right
, DWORD top
, RECT
*rect
)
894 FIXME("(%p, %ld, %ld, %ld, %p): stub\n", hwnd
, left
, right
, top
, rect
);
899 /**********************************************************************
900 * TranslateAcceleratorA (USER32.@)
901 * TranslateAccelerator (USER32.@)
903 INT WINAPI
TranslateAcceleratorA( HWND hWnd
, HACCEL hAccel
, LPMSG msg
)
905 switch (msg
->message
)
909 return NtUserTranslateAccelerator( hWnd
, hAccel
, msg
);
915 char ch
= LOWORD(msg
->wParam
);
917 MultiByteToWideChar(CP_ACP
, 0, &ch
, 1, &wch
, 1);
918 msgW
.wParam
= MAKEWPARAM(wch
, HIWORD(msg
->wParam
));
919 return NtUserTranslateAccelerator( hWnd
, hAccel
, &msgW
);