blob: 708905c054b89db0fb7228c2c56956ede0a61ece [file] [log] [blame]
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001/*
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00002 * Menu functions
3 *
4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994 Alexandre Julliard
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00006 * Copyright 1997 Morten Welinder
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00007 */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00008
9/*
10 * Note: the style MF_MOUSESELECT is used to mark popup items that
11 * have been selected, i.e. their popup menu is currently displayed.
12 * This is probably not the meaning this style has in MS-Windows.
13 */
Alexandre Julliard401710d1993-09-04 10:09:32 +000014
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000015#include <assert.h>
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000016#include <ctype.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017#include <stdlib.h>
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000018#include <string.h>
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000019
Jeremy Whited3e22d92000-02-10 19:03:02 +000020#include "windef.h"
Alexandre Julliard24a62ab2000-11-28 22:40:56 +000021#include "winnls.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000022#include "wingdi.h"
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000023#include "wine/winbase16.h"
Michael Veksler3fbb8dc1999-02-21 18:23:26 +000024#include "wine/winuser16.h"
Alexandre Julliard24a62ab2000-11-28 22:40:56 +000025#include "wine/unicode.h"
Andreas Mohra6d83eb2000-12-27 04:02:46 +000026#include "wine/port.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000027#include "win.h"
Alexandre Julliard91222da2000-12-10 23:01:33 +000028#include "controls.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000029#include "nonclient.h"
Alexandre Julliard1f579291994-05-25 16:25:21 +000030#include "user.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000031#include "message.h"
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000032
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000033#include "debugtools.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000034
Dmitry Timoshkovef559322000-10-26 21:47:20 +000035DEFAULT_DEBUG_CHANNEL(menu);
36DECLARE_DEBUG_CHANNEL(accel);
Alexandre Julliardd37eb361997-07-20 16:23:21 +000037
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000038/* internal popup menu window messages */
39
40#define MM_SETMENUHANDLE (WM_USER + 0)
41#define MM_GETMENUHANDLE (WM_USER + 1)
42
Alexandre Julliard2d93d001996-05-21 15:01:41 +000043/* Menu item structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000044typedef struct {
45 /* ----------- MENUITEMINFO Stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000046 UINT fType; /* Item type. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000047 UINT fState; /* Item state. */
48 UINT wID; /* Item id. */
49 HMENU hSubMenu; /* Pop-up menu. */
Juergen Schmied78513941999-04-18 14:40:32 +000050 HBITMAP hCheckBit; /* Bitmap when checked. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000051 HBITMAP hUnCheckBit; /* Bitmap when unchecked. */
Aric Stewartc946b1c2000-10-24 21:28:19 +000052 LPWSTR text; /* Item text or bitmap handle. */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000053 DWORD dwItemData; /* Application defined. */
Juergen Schmied78513941999-04-18 14:40:32 +000054 DWORD dwTypeData; /* depends on fMask */
55 HBITMAP hbmpItem; /* bitmap in win98 style menus */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000056 /* ----------- Wine stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000057 RECT rect; /* Item area (relative to menu window) */
58 UINT xTab; /* X position of text after Tab */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000059} MENUITEM;
60
61/* Popup menu structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000062typedef struct {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000063 WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
64 WORD wMagic; /* Magic number */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000065 WORD Width; /* Width of the whole menu */
66 WORD Height; /* Height of the whole menu */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +000067 UINT nItems; /* Number of items in the menu */
Juergen Schmied78513941999-04-18 14:40:32 +000068 HWND hWnd; /* Window containing the menu */
69 MENUITEM *items; /* Array of menu items */
70 UINT FocusedItem; /* Currently focused item */
Juergen Schmied466a6521999-05-02 11:21:08 +000071 HWND hwndOwner; /* window receiving the messages for ownerdraw */
Pascal Lessard2eb0a301999-09-03 16:38:52 +000072 BOOL bTimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
Juergen Schmied78513941999-04-18 14:40:32 +000073 /* ------------ MENUINFO members ------ */
74 DWORD dwStyle; /* Extended mennu style */
75 UINT cyMax; /* max hight of the whole menu, 0 is screen hight */
76 HBRUSH hbrBack; /* brush for menu background */
77 DWORD dwContextHelpID;
78 DWORD dwMenuData; /* application defined value */
Pascal Lessardd814bb61999-07-31 13:02:02 +000079 HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000080} POPUPMENU, *LPPOPUPMENU;
81
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000082/* internal flags for menu tracking */
83
84#define TF_ENDMENU 0x0001
85#define TF_SUSPENDPOPUP 0x0002
86#define TF_SKIPREMOVE 0x0004
87
88typedef struct
89{
Alexandre Julliarda3960291999-02-26 11:11:13 +000090 UINT trackFlags;
91 HMENU hCurrentMenu; /* current submenu (can be equal to hTopMenu)*/
92 HMENU hTopMenu; /* initial menu */
93 HWND hOwnerWnd; /* where notifications are sent */
94 POINT pt;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000095} MTRACKER;
96
Alexandre Julliard2d93d001996-05-21 15:01:41 +000097#define MENU_MAGIC 0x554d /* 'MU' */
98
Alexandre Julliard1e37a181996-08-18 16:21:52 +000099#define ITEM_PREV -1
100#define ITEM_NEXT 1
101
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000102 /* Internal MENU_TrackMenu() flags */
103#define TPM_INTERNAL 0xF0000000
104#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
105#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
Francois Boisvert85dd9fc1999-02-17 12:50:11 +0000106#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
Alexandre Julliardf7207251994-07-23 07:57:48 +0000107
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000108 /* popup menu shade thickness */
109#define POPUP_XSHADE 4
110#define POPUP_YSHADE 4
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000111
Alexandre Julliardf7207251994-07-23 07:57:48 +0000112 /* Space between 2 menu bar items */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000113#define MENU_BAR_ITEMS_SPACE 12
Alexandre Julliardf7207251994-07-23 07:57:48 +0000114
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000115 /* Minimum width of a tab character */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000116#define MENU_TAB_SPACE 8
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000117
Alexandre Julliardf7207251994-07-23 07:57:48 +0000118 /* Height of a separator item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000119#define SEPARATOR_HEIGHT 5
Alexandre Julliardf7207251994-07-23 07:57:48 +0000120
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000121 /* (other menu->FocusedItem values give the position of the focused item) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000122#define NO_SELECTED_ITEM 0xffff
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000123
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000124#define MENU_ITEM_TYPE(flags) \
125 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
126
127#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
Juergen Schmied78513941999-04-18 14:40:32 +0000128#define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
François Gouget75b278e2001-01-06 01:45:51 +0000129#define IS_MAGIC_ITEM(text) (LOWORD((int)text)<12)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000130
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000131#define IS_SYSTEM_MENU(menu) \
132 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
Juergen Schmied78513941999-04-18 14:40:32 +0000133
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000134#define IS_SYSTEM_POPUP(menu) \
135 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
136
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000137#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
138 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
139 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
140 MF_POPUP | MF_SYSMENU | MF_HELP)
141#define STATE_MASK (~TYPE_MASK)
142
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000143 /* Dimension of the menu bitmaps */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000144static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000145
Alexandre Julliarda3960291999-02-26 11:11:13 +0000146static HBITMAP hStdMnArrow = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000147
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000148/* Minimze/restore/close buttons to be inserted in menubar */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000149static HBITMAP hBmpMinimize = 0;
150static HBITMAP hBmpMinimizeD = 0;
151static HBITMAP hBmpMaximize = 0;
152static HBITMAP hBmpMaximizeD = 0;
153static HBITMAP hBmpClose = 0;
154static HBITMAP hBmpCloseD = 0;
Francois Boisvert308c6af1999-02-18 10:37:17 +0000155
Francois Boisvert8b391741999-02-09 14:09:55 +0000156
Juergen Schmied78513941999-04-18 14:40:32 +0000157static HBRUSH hShadeBrush = 0;
158static HFONT hMenuFont = 0;
Juergen Schmied466a6521999-05-02 11:21:08 +0000159static HFONT hMenuFontBold = 0;
Juergen Schmied78513941999-04-18 14:40:32 +0000160
Alexandre Julliarda3960291999-02-26 11:11:13 +0000161static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000162
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000163/* Use global popup window because there's no way 2 menus can
164 * be tracked at the same time. */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000165static HWND top_popup;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000166
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000167 /* Flag set by EndMenu() to force an exit from menu tracking */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000168static BOOL fEndMenu = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000169
Alexandre Julliard91222da2000-12-10 23:01:33 +0000170static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
171
172
173/*********************************************************************
174 * menu class descriptor
175 */
176const struct builtin_class_descr MENU_builtin_class =
177{
178 POPUPMENU_CLASS_ATOM, /* name */
179 CS_GLOBALCLASS | CS_SAVEBITS, /* style */
180 NULL, /* procA (winproc is Unicode only) */
181 PopupMenuWndProc, /* procW */
182 sizeof(HMENU), /* extra */
183 IDC_ARROWA, /* cursor */
184 COLOR_MENU+1 /* brush */
185};
186
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000187
188/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000189 * debug_print_menuitem
190 *
191 * Print a menuitem in readable form.
192 */
193
Alexandre Julliard03468f71998-02-15 19:40:49 +0000194#define debug_print_menuitem(pre, mp, post) \
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000195 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000196
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000197#define MENUOUT(text) \
Alexandre Julliard15de6151999-08-04 12:22:42 +0000198 DPRINTF("%s%s", (count++ ? "," : ""), (text))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000199
200#define MENUFLAG(bit,text) \
201 do { \
202 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
203 } while (0)
204
Alexandre Julliard03468f71998-02-15 19:40:49 +0000205static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
206 const char *postfix)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000207{
Alexandre Julliard15de6151999-08-04 12:22:42 +0000208 TRACE("%s ", prefix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000209 if (mp) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000210 UINT flags = mp->fType;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000211 int typ = MENU_ITEM_TYPE(flags);
Alexandre Julliard15de6151999-08-04 12:22:42 +0000212 DPRINTF( "{ ID=0x%x", mp->wID);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000213 if (flags & MF_POPUP)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000214 DPRINTF( ", Sub=0x%x", mp->hSubMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000215 if (flags) {
216 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000217 DPRINTF( ", Typ=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000218 if (typ == MFT_STRING)
219 /* Nothing */ ;
220 else if (typ == MFT_SEPARATOR)
221 MENUOUT("sep");
222 else if (typ == MFT_OWNERDRAW)
223 MENUOUT("own");
224 else if (typ == MFT_BITMAP)
225 MENUOUT("bit");
226 else
227 MENUOUT("???");
228 flags -= typ;
229
230 MENUFLAG(MF_POPUP, "pop");
231 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
232 MENUFLAG(MFT_MENUBREAK, "brk");
233 MENUFLAG(MFT_RADIOCHECK, "radio");
234 MENUFLAG(MFT_RIGHTORDER, "rorder");
235 MENUFLAG(MF_SYSMENU, "sys");
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000236 MENUFLAG(MFT_RIGHTJUSTIFY, "right"); /* same as MF_HELP */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000237
238 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000239 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000240 }
241 flags = mp->fState;
242 if (flags) {
243 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000244 DPRINTF( ", State=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000245 MENUFLAG(MFS_GRAYED, "grey");
Juergen Schmied466a6521999-05-02 11:21:08 +0000246 MENUFLAG(MFS_DEFAULT, "default");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000247 MENUFLAG(MFS_DISABLED, "dis");
248 MENUFLAG(MFS_CHECKED, "check");
249 MENUFLAG(MFS_HILITE, "hi");
250 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
251 MENUFLAG(MF_MOUSESELECT, "mouse");
252 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000253 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000254 }
255 if (mp->hCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000256 DPRINTF( ", Chk=0x%x", mp->hCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000257 if (mp->hUnCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000258 DPRINTF( ", Unc=0x%x", mp->hUnCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000259
260 if (typ == MFT_STRING) {
261 if (mp->text)
François Gougetb99367e2001-02-14 21:42:10 +0000262 DPRINTF( ", Text=%s", debugstr_w(mp->text));
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000263 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000264 DPRINTF( ", Text=Null");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000265 } else if (mp->text == NULL)
266 /* Nothing */ ;
267 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000268 DPRINTF( ", Text=%p", mp->text);
Juergen Schmied7abca951999-04-11 17:02:30 +0000269 if (mp->dwItemData)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000270 DPRINTF( ", ItemData=0x%08lx", mp->dwItemData);
271 DPRINTF( " }");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000272 } else {
Alexandre Julliard15de6151999-08-04 12:22:42 +0000273 DPRINTF( "NULL");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000274 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000275
Alexandre Julliard15de6151999-08-04 12:22:42 +0000276 DPRINTF(" %s\n", postfix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000277}
278
279#undef MENUOUT
280#undef MENUFLAG
281
Gerard Patel3e629742000-01-17 22:22:16 +0000282
283/***********************************************************************
284 * MENU_GetMenu
285 *
286 * Validate the given menu handle and returns the menu structure pointer.
287 */
Alexandre Julliardde424282001-08-10 22:51:42 +0000288static POPUPMENU *MENU_GetMenu(HMENU hMenu)
Gerard Patel3e629742000-01-17 22:22:16 +0000289{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000290 POPUPMENU *menu = USER_HEAP_LIN_ADDR(hMenu);
291 if (!menu || menu->wMagic != MENU_MAGIC)
Gerard Patel3e629742000-01-17 22:22:16 +0000292 {
Gerard Patelc6369b02000-05-14 22:52:52 +0000293 WARN("invalid menu handle=%x, ptr=%p, magic=%x\n", hMenu, menu, menu? menu->wMagic:0);
Gerard Patel3e629742000-01-17 22:22:16 +0000294 menu = NULL;
295 }
296 return menu;
297}
298
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000299/***********************************************************************
Alexandre Julliardde424282001-08-10 22:51:42 +0000300 * get_win_sys_menu
301 *
302 * Get the system menu of a window
303 */
304static HMENU get_win_sys_menu( HWND hwnd )
305{
306 HMENU ret = 0;
307 WND *win = WIN_FindWndPtr( hwnd );
308 if (win)
309 {
310 ret = win->hSysMenu;
311 WIN_ReleaseWndPtr( win );
312 }
313 return ret;
314}
315
316/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000317 * MENU_CopySysPopup
318 *
319 * Return the default system menu.
320 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000321static HMENU MENU_CopySysPopup(void)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000322{
Bertho Stultiensd1895a71999-04-25 18:31:35 +0000323 HMENU hMenu = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000324
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000325 if( hMenu ) {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000326 POPUPMENU* menu = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000327 menu->wFlags |= MF_SYSMENU | MF_POPUP;
Juergen Schmied49251861999-05-13 18:42:03 +0000328 SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000329 }
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000330 else
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000331 ERR("Unable to load default system menu\n" );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000332
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000333 TRACE("returning %x.\n", hMenu );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000334
335 return hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000336}
337
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000338
339/**********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000340 * MENU_GetSysMenu
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000341 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000342 * Create a copy of the system menu. System menu in Windows is
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000343 * a special menu bar with the single entry - system menu popup.
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000344 * This popup is presented to the outside world as a "system menu".
345 * However, the real system menu handle is sometimes seen in the
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000346 * WM_MENUSELECT parameters (and Word 6 likes it this way).
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000347 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000348HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000349{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000350 HMENU hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000351
Alexandre Julliarda3960291999-02-26 11:11:13 +0000352 if ((hMenu = CreateMenu()))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000353 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000354 POPUPMENU *menu = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000355 menu->wFlags = MF_SYSMENU;
356 menu->hWnd = hWnd;
357
Alexandre Julliarda3960291999-02-26 11:11:13 +0000358 if (hPopupMenu == (HMENU)(-1))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000359 hPopupMenu = MENU_CopySysPopup();
360 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
361
362 if (hPopupMenu)
363 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000364 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000365
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000366 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
367 menu->items[0].fState = 0;
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000368 if ((menu = MENU_GetMenu(hPopupMenu))) menu->wFlags |= MF_SYSMENU;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000369
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000370 TRACE("GetSysMenu hMenu=%04x (%04x)\n", hMenu, hPopupMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000371 return hMenu;
372 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000373 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000374 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000375 ERR("failed to load system menu!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000376 return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000377}
378
379
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000380/***********************************************************************
381 * MENU_Init
382 *
383 * Menus initialisation.
384 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000385BOOL MENU_Init()
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000386{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000387 HBITMAP hBitmap;
Juergen Schmied78513941999-04-18 14:40:32 +0000388 NONCLIENTMETRICSA ncm;
389
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000390 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
391 0x55, 0, 0xAA, 0,
392 0x55, 0, 0xAA, 0,
393 0x55, 0, 0xAA, 0 };
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000394
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000395 /* Load menu bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000396 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
Francois Boisvert8b391741999-02-09 14:09:55 +0000397 /* Load system buttons bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000398 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
399 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
400 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
401 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
402 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
403 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000404
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000405 if (hStdMnArrow)
Juergen Schmied78513941999-04-18 14:40:32 +0000406 {
407 BITMAP bm;
408 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
409 arrow_bitmap_width = bm.bmWidth;
410 arrow_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000411 } else
Juergen Schmied78513941999-04-18 14:40:32 +0000412 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000413
Juergen Schmied78513941999-04-18 14:40:32 +0000414 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
415 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000416
Juergen Schmied78513941999-04-18 14:40:32 +0000417 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
418 return FALSE;
419
420 DeleteObject( hBitmap );
421 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
422 return FALSE;
423
424 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
425 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
426 return FALSE;
427
428 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
429 return FALSE;
430
Juergen Schmied466a6521999-05-02 11:21:08 +0000431 ncm.lfMenuFont.lfWeight += 300;
432 if ( ncm.lfMenuFont.lfWeight > 1000)
433 ncm.lfMenuFont.lfWeight = 1000;
434
435 if (!(hMenuFontBold = CreateFontIndirectA( &ncm.lfMenuFont )))
436 return FALSE;
437
Juergen Schmied78513941999-04-18 14:40:32 +0000438 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000439}
440
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000441/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000442 * MENU_InitSysMenuPopup
443 *
444 * Grey the appropriate items in System menu.
445 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000446static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000447{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000448 BOOL gray;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000449
450 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000451 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000452 gray = ((style & WS_MAXIMIZE) != 0);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000453 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000454 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000455 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000456 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000457 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000458 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000459 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000460 gray = (clsStyle & CS_NOCLOSE) != 0;
Pascal Lessardd814bb61999-07-31 13:02:02 +0000461
462 /* The menu item must keep its state if it's disabled */
463 if(gray)
464 EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000465}
466
467
Alexandre Julliard641ee761997-08-04 16:34:36 +0000468/******************************************************************************
469 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000470 * UINT MENU_GetStartOfNextColumn(
471 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000472 *
473 *****************************************************************************/
474
Alexandre Julliarda3960291999-02-26 11:11:13 +0000475static UINT MENU_GetStartOfNextColumn(
476 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000477{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000478 POPUPMENU *menu = MENU_GetMenu(hMenu);
479 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000480
481 if(!menu)
482 return NO_SELECTED_ITEM;
483
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000484 i = menu->FocusedItem + 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000485 if( i == NO_SELECTED_ITEM )
486 return i;
487
488 for( ; i < menu->nItems; ++i ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000489 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000490 return i;
491 }
492
493 return NO_SELECTED_ITEM;
494}
495
496
497/******************************************************************************
498 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000499 * UINT MENU_GetStartOfPrevColumn(
500 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000501 *
502 *****************************************************************************/
503
Alexandre Julliarda3960291999-02-26 11:11:13 +0000504static UINT MENU_GetStartOfPrevColumn(
505 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000506{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000507 POPUPMENU *menu = MENU_GetMenu(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000508 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000509
510 if( !menu )
511 return NO_SELECTED_ITEM;
512
513 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
514 return NO_SELECTED_ITEM;
515
516 /* Find the start of the column */
517
518 for(i = menu->FocusedItem; i != 0 &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000519 !(menu->items[i].fType & MF_MENUBARBREAK);
Alexandre Julliard641ee761997-08-04 16:34:36 +0000520 --i); /* empty */
521
522 if(i == 0)
523 return NO_SELECTED_ITEM;
524
525 for(--i; i != 0; --i) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000526 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000527 break;
528 }
529
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000530 TRACE("ret %d.\n", i );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000531
532 return i;
533}
534
535
536
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000537/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000538 * MENU_FindItem
539 *
540 * Find a menu item. Return a pointer on the item, and modifies *hmenu
541 * in case the item was in a sub-menu.
542 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000543static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000544{
545 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000546 UINT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000547
Gerard Patel3e629742000-01-17 22:22:16 +0000548 if (((*hmenu)==0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000549 if (wFlags & MF_BYPOSITION)
550 {
551 if (*nPos >= menu->nItems) return NULL;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000552 return &menu->items[*nPos];
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000553 }
554 else
555 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000556 MENUITEM *item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000557 for (i = 0; i < menu->nItems; i++, item++)
558 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000559 if (item->wID == *nPos)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000560 {
561 *nPos = i;
562 return item;
563 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000564 else if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000565 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000566 HMENU hsubmenu = item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000567 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
568 if (subitem)
569 {
570 *hmenu = hsubmenu;
571 return subitem;
572 }
573 }
574 }
575 }
576 return NULL;
577}
578
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000579/***********************************************************************
Rein Klazes80c924f1999-12-12 19:40:46 +0000580 * MENU_FindSubMenu
581 *
582 * Find a Sub menu. Return the position of the submenu, and modifies
583 * *hmenu in case it is found in another sub-menu.
584 * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
585 */
586UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
587{
588 POPUPMENU *menu;
589 UINT i;
590 MENUITEM *item;
591 if (((*hmenu)==0xffff) ||
Gerard Patel3e629742000-01-17 22:22:16 +0000592 (!(menu = MENU_GetMenu(*hmenu))))
Rein Klazes80c924f1999-12-12 19:40:46 +0000593 return NO_SELECTED_ITEM;
594 item = menu->items;
595 for (i = 0; i < menu->nItems; i++, item++) {
596 if(!(item->fType & MF_POPUP)) continue;
597 if (item->hSubMenu == hSubTarget) {
598 return i;
599 }
600 else {
601 HMENU hsubmenu = item->hSubMenu;
602 UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget );
603 if (pos != NO_SELECTED_ITEM) {
604 *hmenu = hsubmenu;
605 return pos;
606 }
607 }
608 }
609 return NO_SELECTED_ITEM;
610}
611
612/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000613 * MENU_FreeItemData
614 */
615static void MENU_FreeItemData( MENUITEM* item )
616{
617 /* delete text */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000618 if (IS_STRING_ITEM(item->fType) && item->text)
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000619 HeapFree( GetProcessHeap(), 0, item->text );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000620}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000621
622/***********************************************************************
623 * MENU_FindItemByCoords
624 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000625 * Find the item at the specified coordinates (screen coords). Does
626 * not work for child windows and therefore should not be called for
627 * an arbitrary system menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000628 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000629static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000630 POINT pt, UINT *pos )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000631{
632 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000633 UINT i;
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000634 RECT wrect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000635
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000636 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
637 pt.x -= wrect.left;pt.y -= wrect.top;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000638 item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000639 for (i = 0; i < menu->nItems; i++, item++)
640 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000641 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
642 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000643 {
644 if (pos) *pos = i;
645 return item;
646 }
647 }
648 return NULL;
649}
650
651
652/***********************************************************************
653 * MENU_FindItemByKey
654 *
655 * Find the menu item selected by a key press.
656 * Return item id, -1 if none, -2 if we should close the menu.
657 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000658static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
659 UINT key, BOOL forceMenuChar )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000660{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000661 TRACE("\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000662
Alexandre Julliardde424282001-08-10 22:51:42 +0000663 if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(hwndOwner), 0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000664
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000665 if (hmenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000666 {
Gerard Patel3e629742000-01-17 22:22:16 +0000667 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000668 MENUITEM *item = menu->items;
669 LONG menuchar;
670
671 if( !forceMenuChar )
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000672 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000673 UINT i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000674
675 key = toupper(key);
676 for (i = 0; i < menu->nItems; i++, item++)
677 {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000678 if (item->text && (IS_STRING_ITEM(item->fType)))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000679 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000680 WCHAR *p = item->text - 2;
Norman Stevensa83d0651998-10-12 07:25:35 +0000681 do
682 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000683 p = strchrW (p + 2, '&');
Norman Stevensa83d0651998-10-12 07:25:35 +0000684 }
685 while (p != NULL && p [1] == '&');
686 if (p && (toupper(p[1]) == key)) return i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000687 }
688 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000689 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000690 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000691 MAKEWPARAM( key, menu->wFlags ), hmenu );
692 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000693 if (HIWORD(menuchar) == 1) return (UINT)(-2);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000694 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000695 return (UINT)(-1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000696}
Francois Boisvert8b391741999-02-09 14:09:55 +0000697/***********************************************************************
698 * MENU_LoadMagicItem
699 *
700 * Load the bitmap associated with the magic menu item and its style
701 */
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000702
Juergen Schmied78513941999-04-18 14:40:32 +0000703static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
Francois Boisvert8b391741999-02-09 14:09:55 +0000704{
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000705 /*
706 * Magic menu item id's section
707 * These magic id's are used by windows to insert "standard" mdi
708 * buttons (minimize,restore,close) on menu. Under windows,
709 * these magic id's make sure the right things appear when those
710 * bitmap buttons are pressed/selected/released.
711 */
Francois Boisvert8b391741999-02-09 14:09:55 +0000712
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000713 switch(id & 0xffff)
Juergen Schmied78513941999-04-18 14:40:32 +0000714 { case HBMMENU_SYSTEM:
715 return (dwItemData) ?
716 (HBITMAP)dwItemData :
717 (hilite ? hBmpMinimizeD : hBmpMinimize);
718 case HBMMENU_MBAR_RESTORE:
719 return (hilite ? hBmpMaximizeD: hBmpMaximize);
720 case HBMMENU_MBAR_MINIMIZE:
721 return (hilite ? hBmpMinimizeD : hBmpMinimize);
722 case HBMMENU_MBAR_CLOSE:
723 return (hilite ? hBmpCloseD : hBmpClose);
724 case HBMMENU_CALLBACK:
725 case HBMMENU_MBAR_CLOSE_D:
726 case HBMMENU_MBAR_MINIMIZE_D:
727 case HBMMENU_POPUP_CLOSE:
728 case HBMMENU_POPUP_RESTORE:
729 case HBMMENU_POPUP_MAXIMIZE:
730 case HBMMENU_POPUP_MINIMIZE:
731 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000732 FIXME("Magic 0x%08x not implemented\n", id);
Juergen Schmied78513941999-04-18 14:40:32 +0000733 return 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000734 }
735
736}
Alexandre Julliardf7207251994-07-23 07:57:48 +0000737
738/***********************************************************************
739 * MENU_CalcItemSize
740 *
741 * Calculate the size of the menu item and store it in lpitem->rect.
742 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000743static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
744 INT orgX, INT orgY, BOOL menuBar )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000745{
Aric Stewartc946b1c2000-10-24 21:28:19 +0000746 WCHAR *p;
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +0000747 UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000748
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000749 TRACE("dc=0x%04x owner=0x%04x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000750 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
751 (menuBar ? " (MenuBar)" : ""));
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000752
Alexandre Julliarda3960291999-02-26 11:11:13 +0000753 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000754
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000755 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000756 {
Ken Thomases130f0d82000-05-10 21:38:37 +0000757 /*
758 ** Experimentation under Windows reveals that an owner-drawn
759 ** menu is expected to return the size of the content part of
760 ** the menu item, not including the checkmark nor the submenu
761 ** arrow. Windows adds those values itself and returns the
762 ** enlarged rectangle on subsequent WM_DRAWITEM messages.
763 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000764 MEASUREITEMSTRUCT mis;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000765 mis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000766 mis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000767 mis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000768 mis.itemData = (DWORD)lpitem->dwItemData;
769 mis.itemHeight = 0;
770 mis.itemWidth = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000771 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000772 lpitem->rect.right += mis.itemWidth;
Aric Stewart70cc1692000-05-10 21:54:07 +0000773
774 if (menuBar)
775 {
776 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
777
778
779 /* under at least win95 you seem to be given a standard
780 height for the menu and the height value is ignored */
781
782 if (TWEAK_WineLook == WIN31_LOOK)
783 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU);
784 else
785 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU)-1;
786 }
787 else
788 lpitem->rect.bottom += mis.itemHeight;
789
790 TRACE("id=%04x size=%dx%d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000791 lpitem->wID, mis.itemWidth, mis.itemHeight);
Ken Thomases130f0d82000-05-10 21:38:37 +0000792 /* Fall through to get check/arrow width calculation. */
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000793 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000794
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000795 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000796 {
797 lpitem->rect.bottom += SEPARATOR_HEIGHT;
798 return;
799 }
800
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000801 if (!menuBar)
802 {
803 lpitem->rect.right += 2 * check_bitmap_width;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000804 if (lpitem->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000805 lpitem->rect.right += arrow_bitmap_width;
806 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000807
Ken Thomases130f0d82000-05-10 21:38:37 +0000808 if (lpitem->fType & MF_OWNERDRAW)
809 return;
810
Juergen Schmied78513941999-04-18 14:40:32 +0000811 if (IS_BITMAP_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +0000812 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000813 BITMAP bm;
Juergen Schmied78513941999-04-18 14:40:32 +0000814 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000815
Patrik Stridvall1bb94031999-05-08 15:47:44 +0000816 /* Check if there is a magic menu item associated with this item */
François Gouget75b278e2001-01-06 01:45:51 +0000817 if (IS_MAGIC_ITEM(lpitem->text))
Juergen Schmied78513941999-04-18 14:40:32 +0000818 {
819 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
820 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +0000821 }
822 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000823 resBmp = (HBITMAP)lpitem->text;
Francois Boisvert8b391741999-02-09 14:09:55 +0000824
Alexandre Julliarda3960291999-02-26 11:11:13 +0000825 if (GetObjectA(resBmp, sizeof(bm), &bm ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000826 {
827 lpitem->rect.right += bm.bmWidth;
828 lpitem->rect.bottom += bm.bmHeight;
Francois Gouget75f9e642000-11-06 05:25:29 +0000829 if (TWEAK_WineLook == WIN98_LOOK) {
830 /* Leave space for the sunken border */
831 lpitem->rect.right += 2;
832 lpitem->rect.bottom += 2;
833 }
Francois Boisvert8b391741999-02-09 14:09:55 +0000834
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000835 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000836 }
837
Juergen Schmied78513941999-04-18 14:40:32 +0000838
Gerard Patel2482ef32001-03-19 19:16:21 +0000839 /* it must be a text item - unless it's the system menu */
840 if (!(lpitem->fType & MF_SYSMENU) && IS_STRING_ITEM( lpitem->fType ))
Juergen Schmied78513941999-04-18 14:40:32 +0000841 { SIZE size;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000842
Aric Stewartc946b1c2000-10-24 21:28:19 +0000843 GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000844
845 lpitem->rect.right += size.cx;
846 if (TWEAK_WineLook == WIN31_LOOK)
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000847 lpitem->rect.bottom += max( size.cy, GetSystemMetrics(SM_CYMENU) );
Juergen Schmied78513941999-04-18 14:40:32 +0000848 else
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000849 lpitem->rect.bottom += max(size.cy, GetSystemMetrics(SM_CYMENU)-1);
Juergen Schmied78513941999-04-18 14:40:32 +0000850 lpitem->xTab = 0;
851
852 if (menuBar)
853 {
854 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
855 }
Aric Stewartc946b1c2000-10-24 21:28:19 +0000856 else if ((p = strchrW( lpitem->text, '\t' )) != NULL)
Juergen Schmied78513941999-04-18 14:40:32 +0000857 {
858 /* Item contains a tab (only meaningful in popup menus) */
Aric Stewartc946b1c2000-10-24 21:28:19 +0000859 GetTextExtentPoint32W(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000860 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
861 lpitem->rect.right += MENU_TAB_SPACE;
862 }
863 else
864 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000865 if (strchrW( lpitem->text, '\b' ))
Juergen Schmied78513941999-04-18 14:40:32 +0000866 lpitem->rect.right += MENU_TAB_SPACE;
867 lpitem->xTab = lpitem->rect.right - check_bitmap_width
868 - arrow_bitmap_width;
869 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000870 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000871 TRACE("(%d,%d)-(%d,%d)\n", lpitem->rect.left, lpitem->rect.top, lpitem->rect.right, lpitem->rect.bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000872}
873
874
875/***********************************************************************
876 * MENU_PopupMenuCalcSize
877 *
878 * Calculate the size of a popup menu.
879 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000880static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000881{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000882 MENUITEM *lpitem;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000883 HDC hdc;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000884 int start, i;
885 int orgX, orgY, maxX, maxTab, maxTabWidth;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000886
Alexandre Julliardf7207251994-07-23 07:57:48 +0000887 lppop->Width = lppop->Height = 0;
888 if (lppop->nItems == 0) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000889 hdc = GetDC( 0 );
Juergen Schmied78513941999-04-18 14:40:32 +0000890
891 SelectObject( hdc, hMenuFont);
892
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000893 start = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000894 maxX = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CXBORDER) : 2+1 ;
Juergen Schmied466a6521999-05-02 11:21:08 +0000895
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000896 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000897 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000898 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000899 orgX = maxX;
Marcus Meissnerddca3151999-05-22 11:33:23 +0000900 orgY = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CYBORDER) : 2;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000901
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000902 maxTab = maxTabWidth = 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000903
904 /* Parse items until column break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000905 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000906 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000907 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000908 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000909
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000910 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
Pascal Lessard47274231999-02-13 12:21:46 +0000911
Juergen Schmied466a6521999-05-02 11:21:08 +0000912 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000913 maxX = max( maxX, lpitem->rect.right );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000914 orgY = lpitem->rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000915 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000916 {
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000917 maxTab = max( maxTab, lpitem->xTab );
918 maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000919 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000920 }
921
922 /* Finish the column (set all items to the largest width found) */
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000923 maxX = max( maxX, maxTab + maxTabWidth );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000924 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000925 {
926 lpitem->rect.right = maxX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000927 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Juergen Schmied466a6521999-05-02 11:21:08 +0000928 lpitem->xTab = maxTab;
929
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000930 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000931 lppop->Height = max( lppop->Height, orgY );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000932 }
933
934 lppop->Width = maxX;
Juergen Schmied466a6521999-05-02 11:21:08 +0000935
936 /* space for 3d border */
937 if(TWEAK_WineLook > WIN31_LOOK)
938 {
939 lppop->Height += 2;
940 lppop->Width += 2;
941 }
942
Alexandre Julliarda3960291999-02-26 11:11:13 +0000943 ReleaseDC( 0, hdc );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000944}
945
946
947/***********************************************************************
948 * MENU_MenuBarCalcSize
949 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000950 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000951 * height is off by 1 pixel which causes lengthy window relocations when
952 * active document window is maximized/restored.
953 *
Alexandre Julliardf7207251994-07-23 07:57:48 +0000954 * Calculate the size of the menu bar.
955 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000956static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
957 LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000958{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000959 MENUITEM *lpitem;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000960 int start, i, orgX, orgY, maxY, helpPos;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000961
962 if ((lprect == NULL) || (lppop == NULL)) return;
963 if (lppop->nItems == 0) return;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000964 TRACE("left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000965 lprect->left, lprect->top, lprect->right, lprect->bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000966 lppop->Width = lprect->right - lprect->left;
967 lppop->Height = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000968 maxY = lprect->top+1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000969 start = 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000970 helpPos = -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000971 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000972 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000973 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000974 orgX = lprect->left;
975 orgY = maxY;
976
977 /* Parse items until line break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000978 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000979 {
Francois Gouget58182402001-01-04 20:56:43 +0000980 if ((helpPos == -1) && (lpitem->fType & MF_RIGHTJUSTIFY)) helpPos = i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000981 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000982 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000983
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000984 TRACE("calling MENU_CalcItemSize org=(%d, %d)\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000985 orgX, orgY );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000986 debug_print_menuitem (" item: ", lpitem, "");
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000987 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
Pascal Lessard47274231999-02-13 12:21:46 +0000988
Alexandre Julliardf7207251994-07-23 07:57:48 +0000989 if (lpitem->rect.right > lprect->right)
990 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000991 if (i != start) break;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000992 else lpitem->rect.right = lprect->right;
993 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000994 maxY = max( maxY, lpitem->rect.bottom );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000995 orgX = lpitem->rect.right;
996 }
997
998 /* Finish the line (set all items to the largest height found) */
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000999 while (start < i) lppop->items[start++].rect.bottom = maxY;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001000 }
1001
1002 lprect->bottom = maxY;
1003 lppop->Height = lprect->bottom - lprect->top;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001004
Francois Gouget58182402001-01-04 20:56:43 +00001005 /* Flush right all items between the MF_RIGHTJUSTIFY and */
1006 /* the last item (if several lines, only move the last line) */
1007 lpitem = &lppop->items[lppop->nItems-1];
1008 orgY = lpitem->rect.top;
1009 orgX = lprect->right;
1010 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--) {
1011 if ( (helpPos==-1) || (helpPos>i) )
1012 break; /* done */
1013 if (lpitem->rect.top != orgY) break; /* Other line */
1014 if (lpitem->rect.right >= orgX) break; /* Too far right already */
1015 lpitem->rect.left += orgX - lpitem->rect.right;
1016 lpitem->rect.right = orgX;
1017 orgX = lpitem->rect.left;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001018 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001019}
1020
Alexandre Julliardf7207251994-07-23 07:57:48 +00001021/***********************************************************************
1022 * MENU_DrawMenuItem
1023 *
1024 * Draw a single menu item.
1025 */
Juergen Schmied78513941999-04-18 14:40:32 +00001026static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001027 UINT height, BOOL menuBar, UINT odaction )
Alexandre Julliardf7207251994-07-23 07:57:48 +00001028{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001029 RECT rect;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001030
Alexandre Julliard03468f71998-02-15 19:40:49 +00001031 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001032
1033 if (lpitem->fType & MF_SYSMENU)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001034 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001035 if( !IsIconic(hwnd) ) {
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001036 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001037 NC_DrawSysButton95( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001038 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001039 (MF_HILITE | MF_MOUSESELECT) );
1040 else
1041 NC_DrawSysButton( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001042 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001043 (MF_HILITE | MF_MOUSESELECT) );
1044 }
1045
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001046 return;
1047 }
1048
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001049 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001050 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001051 /*
1052 ** Experimentation under Windows reveals that an owner-drawn
1053 ** menu is given the rectangle which includes the space it requested
1054 ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
1055 ** and a popup-menu arrow. This is the value of lpitem->rect.
1056 ** Windows will leave all drawing to the application except for
1057 ** the popup-menu arrow. Windows always draws that itself, after
1058 ** the menu owner has finished drawing.
1059 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001060 DRAWITEMSTRUCT dis;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001061
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001062 dis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +00001063 dis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001064 dis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +00001065 dis.itemData = (DWORD)lpitem->dwItemData;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001066 dis.itemState = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001067 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
1068 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
1069 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001070 dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
Juergen Schmied78513941999-04-18 14:40:32 +00001071 dis.hwndItem = hmenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001072 dis.hDC = hdc;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001073 dis.rcItem = lpitem->rect;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001074 TRACE("Ownerdraw: owner=%04x itemID=%d, itemState=%d, itemAction=%d, "
Juergen Schmied78513941999-04-18 14:40:32 +00001075 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n", hwndOwner,
1076 dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
1077 dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
1078 dis.rcItem.bottom);
1079 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
Ken Thomases130f0d82000-05-10 21:38:37 +00001080 /* Fall through to draw popup-menu arrow */
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001081 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001082
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001083 TRACE("rect={%d,%d,%d,%d}\n", lpitem->rect.left, lpitem->rect.top,
Juergen Schmied78513941999-04-18 14:40:32 +00001084 lpitem->rect.right,lpitem->rect.bottom);
1085
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001086 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
Juergen Schmied78513941999-04-18 14:40:32 +00001087
Alexandre Julliardf7207251994-07-23 07:57:48 +00001088 rect = lpitem->rect;
1089
Ken Thomases130f0d82000-05-10 21:38:37 +00001090 if (!(lpitem->fType & MF_OWNERDRAW))
1091 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001092 if (lpitem->fState & MF_HILITE)
1093 {
1094 if(TWEAK_WineLook == WIN98_LOOK)
1095 {
1096 if(menuBar)
1097 DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
1098 else
1099 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1100 }
1101 else /* Not Win98 Look */
1102 {
1103 if(!IS_BITMAP_ITEM(lpitem->fType))
1104 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1105 }
1106 }
Ken Thomases130f0d82000-05-10 21:38:37 +00001107 else
1108 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
1109 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001110
Alexandre Julliarda3960291999-02-26 11:11:13 +00001111 SetBkMode( hdc, TRANSPARENT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001112
Ken Thomases130f0d82000-05-10 21:38:37 +00001113 if (!(lpitem->fType & MF_OWNERDRAW))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001114 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001115 /* vertical separator */
1116 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
1117 {
1118 if (TWEAK_WineLook > WIN31_LOOK)
1119 {
1120 RECT rc = rect;
1121 rc.top = 3;
1122 rc.bottom = height - 3;
1123 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
1124 }
1125 else
1126 {
1127 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001128 MoveToEx( hdc, rect.left, 0, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001129 LineTo( hdc, rect.left, height );
1130 }
1131 }
Juergen Schmied78513941999-04-18 14:40:32 +00001132
Ken Thomases130f0d82000-05-10 21:38:37 +00001133 /* horizontal separator */
1134 if (lpitem->fType & MF_SEPARATOR)
1135 {
1136 if (TWEAK_WineLook > WIN31_LOOK)
1137 {
1138 RECT rc = rect;
1139 rc.left++;
1140 rc.right--;
1141 rc.top += SEPARATOR_HEIGHT / 2;
1142 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
1143 }
1144 else
1145 {
1146 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001147 MoveToEx( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001148 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
1149 }
1150 return;
1151 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001152 }
1153
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001154 /* Setup colors */
1155
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001156 if (lpitem->fState & MF_HILITE)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001157 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001158 if(TWEAK_WineLook == WIN98_LOOK)
1159 {
François Gouget75b278e2001-01-06 01:45:51 +00001160 if(menuBar) {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001161 SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
François Gouget75b278e2001-01-06 01:45:51 +00001162 SetBkColor(hdc, GetSysColor(COLOR_MENU));
1163 } else {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001164 if(lpitem->fState & MF_GRAYED)
1165 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
1166 else
1167 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
François Gouget75b278e2001-01-06 01:45:51 +00001168 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001169 }
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001170 }
1171 else /* Not Win98 Look */
1172 {
1173 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1174 if(!IS_BITMAP_ITEM(lpitem->fType))
1175 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001176 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001177 }
1178 else
1179 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001180 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001181 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001182 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001183 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
1184 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001185 }
1186
Juergen Schmied78513941999-04-18 14:40:32 +00001187 /* helper lines for debugging */
1188/* FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
1189 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001190 MoveToEx( hdc, rect.left, (rect.top + rect.bottom)/2, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00001191 LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
1192*/
1193
Alexandre Julliardf7207251994-07-23 07:57:48 +00001194 if (!menuBar)
1195 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001196 INT y = rect.top + rect.bottom;
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00001197 UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
1198 UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001199
Ken Thomases130f0d82000-05-10 21:38:37 +00001200 if (!(lpitem->fType & MF_OWNERDRAW))
1201 {
1202 /* Draw the check mark
1203 *
1204 * FIXME:
1205 * Custom checkmark bitmaps are monochrome but not always 1bpp.
1206 */
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00001207 HBITMAP bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
1208 if (bm) /* we have a custom bitmap */
1209 {
1210 HDC hdcMem = CreateCompatibleDC( hdc );
1211 SelectObject( hdcMem, bm );
1212 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1213 check_bitmap_width, check_bitmap_height,
1214 hdcMem, 0, 0, SRCCOPY );
1215 DeleteDC( hdcMem );
1216 }
1217 else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
1218 {
1219 RECT r;
1220 HBITMAP bm = CreateBitmap( check_bitmap_width, check_bitmap_height, 1, 1, NULL );
1221 HDC hdcMem = CreateCompatibleDC( hdc );
1222 SelectObject( hdcMem, bm );
1223 SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height );
1224 DrawFrameControl( hdcMem, &r, DFC_MENU,
1225 (lpitem->fType & MFT_RADIOCHECK) ?
1226 DFCS_MENUBULLET : DFCS_MENUCHECK );
1227 BitBlt( hdc, rect.left, (y - r.bottom) / 2, r.right, r.bottom,
1228 hdcMem, 0, 0, SRCCOPY );
1229 DeleteDC( hdcMem );
1230 DeleteObject( bm );
1231 }
Ken Thomases130f0d82000-05-10 21:38:37 +00001232 }
Juergen Schmied78513941999-04-18 14:40:32 +00001233
Alexandre Julliardf7207251994-07-23 07:57:48 +00001234 /* Draw the popup-menu arrow */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001235 if (lpitem->fType & MF_POPUP)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001236 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001237 HDC hdcMem = CreateCompatibleDC( hdc );
Ken Thomases130f0d82000-05-10 21:38:37 +00001238 HBITMAP hOrigBitmap;
Huw D M Davies2d617be1998-12-08 09:14:09 +00001239
Ken Thomases130f0d82000-05-10 21:38:37 +00001240 hOrigBitmap = SelectObject( hdcMem, hStdMnArrow );
Juergen Schmied78513941999-04-18 14:40:32 +00001241 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001242 (y - arrow_bitmap_height) / 2,
1243 arrow_bitmap_width, arrow_bitmap_height,
1244 hdcMem, 0, 0, SRCCOPY );
Ken Thomases130f0d82000-05-10 21:38:37 +00001245 SelectObject( hdcMem, hOrigBitmap );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001246 DeleteDC( hdcMem );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001247 }
1248
1249 rect.left += check_bitmap_width;
1250 rect.right -= arrow_bitmap_width;
1251 }
1252
Ken Thomases130f0d82000-05-10 21:38:37 +00001253 /* Done for owner-drawn */
1254 if (lpitem->fType & MF_OWNERDRAW)
1255 return;
1256
Juergen Schmied78513941999-04-18 14:40:32 +00001257 /* Draw the item text or bitmap */
1258 if (IS_BITMAP_ITEM(lpitem->fType))
François Gouget75b278e2001-01-06 01:45:51 +00001259 {
1260 int left,top,w,h;
1261 DWORD rop;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001262
Alexandre Julliarda3960291999-02-26 11:11:13 +00001263 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +00001264
Alexandre Julliarda3960291999-02-26 11:11:13 +00001265 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001266
Patrik Stridvall1bb94031999-05-08 15:47:44 +00001267 /*
1268 * Check if there is a magic menu item associated with this item
1269 * and load the appropriate bitmap
1270 */
François Gouget75b278e2001-01-06 01:45:51 +00001271 if (IS_MAGIC_ITEM(lpitem->text))
Juergen Schmied78513941999-04-18 14:40:32 +00001272 {
1273 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
1274 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +00001275 }
1276 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001277 resBmp = (HBITMAP)lpitem->text;
Juergen Schmied78513941999-04-18 14:40:32 +00001278
1279 if (resBmp)
1280 {
1281 BITMAP bm;
1282 GetObjectA( resBmp, sizeof(bm), &bm );
1283
1284 SelectObject(hdcMem,resBmp );
1285
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001286 /* handle fontsize > bitmap_height */
François Gouget75b278e2001-01-06 01:45:51 +00001287 h=rect.bottom - rect.top;
1288 top = (h>bm.bmHeight) ?
1289 rect.top+(h-bm.bmHeight)/2 : rect.top;
1290 w=rect.right - rect.left;
1291 left=rect.left;
1292 if (TWEAK_WineLook == WIN95_LOOK) {
1293 rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(lpitem->text)) ? NOTSRCCOPY : SRCCOPY;
1294 if ((lpitem->fState & MF_HILITE) && IS_BITMAP_ITEM(lpitem->fType))
1295 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1296 } else {
1297 left++;
1298 w-=2;
1299 rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(lpitem->text) && (!menuBar)) ? MERGEPAINT : SRCCOPY;
1300 }
1301 BitBlt( hdc, left, top, w,
1302 h, hdcMem, 0, 0,
1303 rop);
Juergen Schmied78513941999-04-18 14:40:32 +00001304 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001305 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001306
Alexandre Julliardf7207251994-07-23 07:57:48 +00001307 return;
Francois Boisvert8b391741999-02-09 14:09:55 +00001308
Alexandre Julliardf7207251994-07-23 07:57:48 +00001309 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001310 /* No bitmap - process text if present */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001311 else if (IS_STRING_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001312 {
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001313 register int i;
Juergen Schmied466a6521999-05-02 11:21:08 +00001314 HFONT hfontOld = 0;
1315
Juergen Schmied78513941999-04-18 14:40:32 +00001316 UINT uFormat = (menuBar) ?
1317 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
1318 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001319
Juergen Schmied466a6521999-05-02 11:21:08 +00001320 if ( lpitem->fState & MFS_DEFAULT )
1321 {
1322 hfontOld = SelectObject( hdc, hMenuFontBold);
1323 }
1324
Alexandre Julliardf7207251994-07-23 07:57:48 +00001325 if (menuBar)
1326 {
1327 rect.left += MENU_BAR_ITEMS_SPACE / 2;
1328 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001329 i = strlenW( lpitem->text );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001330 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001331 else
Alexandre Julliardf7207251994-07-23 07:57:48 +00001332 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001333 for (i = 0; lpitem->text[i]; i++)
Juergen Schmied466a6521999-05-02 11:21:08 +00001334 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
1335 break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001336 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001337
Juergen Schmied466a6521999-05-02 11:21:08 +00001338 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
Juergen Schmied78513941999-04-18 14:40:32 +00001339 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001340 if (!(lpitem->fState & MF_HILITE) )
Juergen Schmied78513941999-04-18 14:40:32 +00001341 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001342 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001343 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001344 DrawTextW( hdc, lpitem->text, i, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001345 --rect.left; --rect.top; --rect.right; --rect.bottom;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001346 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001347 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001348 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001349
Aric Stewartc946b1c2000-10-24 21:28:19 +00001350 DrawTextW( hdc, lpitem->text, i, &rect, uFormat);
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001351
Juergen Schmied466a6521999-05-02 11:21:08 +00001352 /* paint the shortcut text */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001353 if (lpitem->text[i]) /* There's a tab or flush-right char */
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001354 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001355 if (lpitem->text[i] == '\t')
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001356 {
1357 rect.left = lpitem->xTab;
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001358 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001359 }
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001360 else
1361 {
1362 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
1363 }
1364
Juergen Schmied466a6521999-05-02 11:21:08 +00001365 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
1366 {
1367 if (!(lpitem->fState & MF_HILITE) )
1368 {
1369 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
1370 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001371 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001372 --rect.left; --rect.top; --rect.right; --rect.bottom;
1373 }
1374 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
1375 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00001376 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001377 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001378
1379 if (hfontOld)
1380 SelectObject (hdc, hfontOld);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001381 }
1382}
1383
1384
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001385/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001386 * MENU_DrawPopupMenu
1387 *
1388 * Paint a popup menu.
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001389 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001390static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001391{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001392 HBRUSH hPrevBrush = 0;
1393 RECT rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001394
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001395 TRACE("wnd=0x%04x dc=0x%04x menu=0x%04x\n", hwnd, hdc, hmenu);
Juergen Schmied78513941999-04-18 14:40:32 +00001396
Alexandre Julliarda3960291999-02-26 11:11:13 +00001397 GetClientRect( hwnd, &rect );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001398
Alex Korobka44a1b591999-04-01 12:03:52 +00001399 if(TWEAK_WineLook == WIN31_LOOK)
1400 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001401 rect.bottom -= POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
1402 rect.right -= POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001403 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001404
Juergen Schmied78513941999-04-18 14:40:32 +00001405 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
1406 && (SelectObject( hdc, hMenuFont)))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001407 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001408 HPEN hPrevPen;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001409
Alexandre Julliarda3960291999-02-26 11:11:13 +00001410 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001411
Alexandre Julliarda3960291999-02-26 11:11:13 +00001412 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001413 if( hPrevPen )
1414 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001415 INT ropPrev, i;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001416 POPUPMENU *menu;
1417
1418 /* draw 3-d shade */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001419 if(TWEAK_WineLook == WIN31_LOOK) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001420 SelectObject( hdc, hShadeBrush );
1421 SetBkMode( hdc, TRANSPARENT );
1422 ropPrev = SetROP2( hdc, R2_MASKPEN );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001423
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001424 i = rect.right; /* why SetBrushOrg() doesn't? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001425 PatBlt( hdc, i & 0xfffffffe,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001426 rect.top + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER),
1427 i%2 + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001428 rect.bottom - rect.top, 0x00a000c9 );
1429 i = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001430 PatBlt( hdc, rect.left + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001431 i & 0xfffffffe,rect.right - rect.left,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001432 i%2 + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER), 0x00a000c9 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433 SelectObject( hdc, hPrevPen );
1434 SelectObject( hdc, hPrevBrush );
1435 SetROP2( hdc, ropPrev );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001436 }
1437 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001438 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001439
1440 /* draw menu items */
1441
Gerard Patel3e629742000-01-17 22:22:16 +00001442 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001443 if (menu && menu->nItems)
1444 {
1445 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001446 UINT u;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001447
1448 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
Juergen Schmied78513941999-04-18 14:40:32 +00001449 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
1450 menu->Height, FALSE, ODA_DRAWENTIRE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001451
1452 }
Juergen Schmied78513941999-04-18 14:40:32 +00001453 } else
1454 {
1455 SelectObject( hdc, hPrevBrush );
1456 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001457 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001458}
1459
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001460/***********************************************************************
1461 * MENU_DrawMenuBar
1462 *
1463 * Paint a menu bar. Returns the height of the menu bar.
Juergen Schmied78513941999-04-18 14:40:32 +00001464 * called from [windows/nonclient.c]
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001465 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001466UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
1467 BOOL suppress_draw)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001468{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001469 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001470 UINT i,retvalue;
Juergen Schmied78513941999-04-18 14:40:32 +00001471 HFONT hfontOld = 0;
Alexandre Julliardde424282001-08-10 22:51:42 +00001472 HMENU hMenu = GetMenu(hwnd);
Juergen Schmied78513941999-04-18 14:40:32 +00001473
Alexandre Julliardde424282001-08-10 22:51:42 +00001474 lppop = MENU_GetMenu( hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001475 if (lppop == NULL || lprect == NULL)
1476 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001477 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001478 goto END;
1479 }
Juergen Schmied78513941999-04-18 14:40:32 +00001480
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001481 TRACE("(%04x, %p, %p)\n", hDC, lprect, lppop);
Juergen Schmied78513941999-04-18 14:40:32 +00001482
1483 hfontOld = SelectObject( hDC, hMenuFont);
1484
1485 if (lppop->Height == 0)
1486 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
1487
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001488 lprect->bottom = lprect->top + lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001489
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001490 if (suppress_draw)
1491 {
1492 retvalue = lppop->Height;
1493 goto END;
1494 }
Juergen Schmied78513941999-04-18 14:40:32 +00001495
Alexandre Julliarda3960291999-02-26 11:11:13 +00001496 FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001497
Juergen Schmied78513941999-04-18 14:40:32 +00001498 if (TWEAK_WineLook == WIN31_LOOK)
1499 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001500 SelectObject( hDC, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001501 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001502 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001503 }
Juergen Schmied78513941999-04-18 14:40:32 +00001504 else
1505 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001506 SelectObject( hDC, GetSysColorPen(COLOR_3DFACE));
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001507 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001508 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001509 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001510
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001511 if (lppop->nItems == 0)
1512 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001513 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001514 goto END;
1515 }
Juergen Schmied78513941999-04-18 14:40:32 +00001516
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001517 for (i = 0; i < lppop->nItems; i++)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001518 {
Alexandre Julliardde424282001-08-10 22:51:42 +00001519 MENU_DrawMenuItem( hwnd, hMenu, hwnd,
1520 hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001521 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001522 retvalue = lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001523
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001524END:
Alexandre Julliardde424282001-08-10 22:51:42 +00001525 if (hfontOld) SelectObject (hDC, hfontOld);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001526 return retvalue;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001527}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001528
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001529
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001530/***********************************************************************
1531 * MENU_ShowPopup
1532 *
1533 * Display a popup menu.
1534 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001535static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
1536 INT x, INT y, INT xanchor, INT yanchor )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001537{
Alexandre Julliardde424282001-08-10 22:51:42 +00001538 POPUPMENU *menu;
1539 UINT width, height;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001540
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001541 TRACE("owner=0x%04x hmenu=0x%04x id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
Juergen Schmied78513941999-04-18 14:40:32 +00001542 hwndOwner, hmenu, id, x, y, xanchor, yanchor);
1543
Gerard Patel3e629742000-01-17 22:22:16 +00001544 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001545 if (menu->FocusedItem != NO_SELECTED_ITEM)
1546 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001547 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001548 menu->FocusedItem = NO_SELECTED_ITEM;
1549 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001550
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001551 /* store the owner for DrawItem */
Juergen Schmied78513941999-04-18 14:40:32 +00001552 menu->hwndOwner = hwndOwner;
1553
Alexandre Julliardde424282001-08-10 22:51:42 +00001554
1555 MENU_PopupMenuCalcSize( menu, hwndOwner );
1556
1557 /* adjust popup menu pos so that it fits within the desktop */
1558
1559 width = menu->Width + GetSystemMetrics(SM_CXBORDER);
1560 height = menu->Height + GetSystemMetrics(SM_CYBORDER);
1561
1562 if( x + width > GetSystemMetrics(SM_CXSCREEN ))
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001563 {
Alexandre Julliardde424282001-08-10 22:51:42 +00001564 if( xanchor )
1565 x -= width - xanchor;
1566 if( x + width > GetSystemMetrics(SM_CXSCREEN))
1567 x = GetSystemMetrics(SM_CXSCREEN) - width;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001568 }
Alexandre Julliardde424282001-08-10 22:51:42 +00001569 if( x < 0 ) x = 0;
1570
1571 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
1572 {
1573 if( yanchor )
1574 y -= height + yanchor;
1575 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
1576 y = GetSystemMetrics(SM_CYSCREEN) - height;
1577 }
1578 if( y < 0 ) y = 0;
1579
1580 if( TWEAK_WineLook == WIN31_LOOK )
1581 {
1582 width += POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER); /* add space for shading */
1583 height += POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
1584 }
1585
1586 /* NOTE: In Windows, top menu popup is not owned. */
1587 menu->hWnd = CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
1588 WS_POPUP, x, y, width, height,
1589 hwndOwner, 0, GetWindowLongA(hwndOwner,GWL_HINSTANCE),
1590 (LPVOID)hmenu );
1591 if( !menu->hWnd ) return FALSE;
1592 if (!top_popup) top_popup = menu->hWnd;
1593
1594 /* Display the window */
1595
1596 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
1597 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1598 UpdateWindow( menu->hWnd );
1599 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001600}
1601
1602
1603/***********************************************************************
1604 * MENU_SelectItem
1605 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001606static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
Rein Klazes80c924f1999-12-12 19:40:46 +00001607 BOOL sendMenuSelect, HMENU topmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001608{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001609 LPPOPUPMENU lppop;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001610 HDC hdc;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001611
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001612 TRACE("owner=0x%04x menu=0x%04x index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
Juergen Schmied78513941999-04-18 14:40:32 +00001613
Gerard Patel3e629742000-01-17 22:22:16 +00001614 lppop = MENU_GetMenu( hmenu );
Gerard Patel8f79fdc2001-05-14 19:20:13 +00001615 if ((!lppop) || (!lppop->nItems) || (!lppop->hWnd)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001616
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001617 if (lppop->FocusedItem == wIndex) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001618 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
1619 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001620
Juergen Schmied78513941999-04-18 14:40:32 +00001621 SelectObject( hdc, hMenuFont);
1622
Alexandre Julliardf7207251994-07-23 07:57:48 +00001623 /* Clear previous highlighted item */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001624 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001625 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001626 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Juergen Schmied78513941999-04-18 14:40:32 +00001627 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001628 lppop->Height, !(lppop->wFlags & MF_POPUP),
1629 ODA_SELECT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001630 }
1631
1632 /* Highlight new item (if any) */
1633 lppop->FocusedItem = wIndex;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001634 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001635 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001636 if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
1637 lppop->items[wIndex].fState |= MF_HILITE;
1638 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
1639 &lppop->items[wIndex], lppop->Height,
1640 !(lppop->wFlags & MF_POPUP), ODA_SELECT );
1641 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001642 if (sendMenuSelect)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001643 {
1644 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
Juergen Schmied78513941999-04-18 14:40:32 +00001645 SendMessageA( hwndOwner, WM_MENUSELECT,
Rein Klazes80c924f1999-12-12 19:40:46 +00001646 MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
1647 ip->fType | ip->fState | MF_MOUSESELECT |
1648 (lppop->wFlags & MF_SYSMENU)), hmenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001649 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001650 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001651 else if (sendMenuSelect) {
Rein Klazes80c924f1999-12-12 19:40:46 +00001652 if(topmenu){
1653 int pos;
1654 if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001655 POPUPMENU *ptm = MENU_GetMenu( topmenu );
Rein Klazes80c924f1999-12-12 19:40:46 +00001656 MENUITEM *ip = &ptm->items[pos];
1657 SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
1658 ip->fType | ip->fState | MF_MOUSESELECT |
1659 (ptm->wFlags & MF_SYSMENU)), topmenu);
1660 }
1661 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001662 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001663 ReleaseDC( lppop->hWnd, hdc );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001664}
1665
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001666
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001667/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001668 * MENU_MoveSelection
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001669 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001670 * Moves currently selected item according to the offset parameter.
1671 * If there is no selection then it should select the last item if
1672 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001673 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001674static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001675{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001676 INT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001677 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001678
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001679 TRACE("hwnd=0x%04x hmenu=0x%04x off=0x%04x\n", hwndOwner, hmenu, offset);
Juergen Schmied466a6521999-05-02 11:21:08 +00001680
Gerard Patel3e629742000-01-17 22:22:16 +00001681 menu = MENU_GetMenu( hmenu );
1682 if ((!menu) || (!menu->items)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001683
1684 if ( menu->FocusedItem != NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001685 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001686 if( menu->nItems == 1 ) return; else
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001687 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
1688 ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001689 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001690 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001691 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001692 return;
1693 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001694 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001695
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001696 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
1697 i >= 0 && i < menu->nItems ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001698 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001699 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001700 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001701 return;
1702 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001703}
1704
1705
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001706/**********************************************************************
1707 * MENU_SetItemData
1708 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001709 * Set an item flags, id and text ptr. Called by InsertMenu() and
1710 * ModifyMenu().
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001711 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001712static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
Aric Stewartc946b1c2000-10-24 21:28:19 +00001713 LPCWSTR str )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001714{
Aric Stewartc946b1c2000-10-24 21:28:19 +00001715 LPWSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001716
Alexandre Julliard03468f71998-02-15 19:40:49 +00001717 debug_print_menuitem("MENU_SetItemData from: ", item, "");
Gerard Patel2482ef32001-03-19 19:16:21 +00001718 TRACE("flags=%x str=%p\n", flags, str);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001719
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001720 if (IS_STRING_ITEM(flags))
1721 {
Dmitry Timoshkov9316fa32001-02-14 00:23:45 +00001722 if (!str)
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001723 {
1724 flags |= MF_SEPARATOR;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001725 item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001726 }
1727 else
1728 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00001729 LPWSTR text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001730 /* Item beginning with a backspace is a help item */
1731 if (*str == '\b')
1732 {
1733 flags |= MF_HELP;
1734 str++;
1735 }
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00001736 if (!(text = HeapAlloc( GetProcessHeap(), 0, (strlenW(str)+1) * sizeof(WCHAR) )))
1737 return FALSE;
1738 strcpyW( text, str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001739 item->text = text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001740 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001741 }
Juergen Schmied78513941999-04-18 14:40:32 +00001742 else if (IS_BITMAP_ITEM(flags))
Aric Stewartc946b1c2000-10-24 21:28:19 +00001743 item->text = (LPWSTR)(HBITMAP)LOWORD(str);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001744 else item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001745
Alexandre Julliarda845b881998-06-01 10:44:35 +00001746 if (flags & MF_OWNERDRAW)
1747 item->dwItemData = (DWORD)str;
1748 else
1749 item->dwItemData = 0;
1750
Alexandre Julliard02e90081998-01-04 17:49:09 +00001751 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001752 DestroyMenu( item->hSubMenu ); /* ModifyMenu() spec */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001753
1754 if (flags & MF_POPUP)
1755 {
Gerard Patel3e629742000-01-17 22:22:16 +00001756 POPUPMENU *menu = MENU_GetMenu((UINT16)id);
1757 if (menu) menu->wFlags |= MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001758 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001759 {
1760 item->wID = 0;
1761 item->hSubMenu = 0;
1762 item->fType = 0;
1763 item->fState = 0;
1764 return FALSE;
1765 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001766 }
1767
1768 item->wID = id;
1769 if (flags & MF_POPUP)
1770 item->hSubMenu = id;
1771
1772 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
1773 flags |= MF_POPUP; /* keep popup */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001774
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001775 item->fType = flags & TYPE_MASK;
1776 item->fState = (flags & STATE_MASK) &
1777 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001778
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001779
1780 /* Don't call SetRectEmpty here! */
1781
1782
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001783 if (prevText) HeapFree( GetProcessHeap(), 0, prevText );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001784
Alexandre Julliard03468f71998-02-15 19:40:49 +00001785 debug_print_menuitem("MENU_SetItemData to : ", item, "");
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001786 return TRUE;
1787}
1788
1789
1790/**********************************************************************
1791 * MENU_InsertItem
1792 *
1793 * Insert a new item into a menu.
1794 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001795static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001796{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001797 MENUITEM *newItems;
1798 POPUPMENU *menu;
1799
Gerard Patel3e629742000-01-17 22:22:16 +00001800 if (!(menu = MENU_GetMenu(hMenu)))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001801 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001802
1803 /* Find where to insert new item */
1804
Gerard Patelc6369b02000-05-14 22:52:52 +00001805 if (flags & MF_BYPOSITION) {
1806 if (pos > menu->nItems)
1807 pos = menu->nItems;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00001808 } else {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001809 if (!MENU_FindItem( &hMenu, &pos, flags ))
Gerard Patelc6369b02000-05-14 22:52:52 +00001810 pos = menu->nItems;
1811 else {
1812 if (!(menu = MENU_GetMenu( hMenu )))
1813 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001814 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001815 }
1816
1817 /* Create new items array */
1818
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001819 newItems = HeapAlloc( GetProcessHeap(), 0, sizeof(MENUITEM) * (menu->nItems+1) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001820 if (!newItems)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001821 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001822 WARN("allocation failed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001823 return NULL;
1824 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001825 if (menu->nItems > 0)
1826 {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001827 /* Copy the old array into the new one */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001828 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
1829 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001830 (menu->nItems-pos)*sizeof(MENUITEM) );
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001831 HeapFree( GetProcessHeap(), 0, menu->items );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001832 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001833 menu->items = newItems;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001834 menu->nItems++;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001835 memset( &newItems[pos], 0, sizeof(*newItems) );
Gerard Patel6df06941999-09-28 13:05:54 +00001836 menu->Height = 0; /* force size recalculate */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001837 return &newItems[pos];
1838}
1839
1840
1841/**********************************************************************
1842 * MENU_ParseResource
1843 *
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001844 * Parse a standard menu resource and add items to the menu.
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001845 * Return a pointer to the end of the resource.
1846 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001847static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001848{
1849 WORD flags, id = 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001850 LPCSTR str;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001851
1852 do
1853 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001854 flags = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001855 res += sizeof(WORD);
1856 if (!(flags & MF_POPUP))
1857 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001858 id = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001859 res += sizeof(WORD);
1860 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001861 if (!IS_STRING_ITEM(flags))
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001862 ERR("not a string item %04x\n", flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001863 str = res;
1864 if (!unicode) res += strlen(str) + 1;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001865 else res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001866 if (flags & MF_POPUP)
1867 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001868 HMENU hSubMenu = CreatePopupMenu();
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001869 if (!hSubMenu) return NULL;
1870 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
1871 return NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001872 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
1873 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001874 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001875 else /* Not a popup */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001876 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001877 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1878 else AppendMenuW( hMenu, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001879 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001880 }
1881 } while (!(flags & MF_END));
1882 return res;
1883}
1884
1885
Alexandre Julliard641ee761997-08-04 16:34:36 +00001886/**********************************************************************
1887 * MENUEX_ParseResource
1888 *
1889 * Parse an extended menu resource and add items to the menu.
1890 * Return a pointer to the end of the resource.
1891 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001892static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
Alexandre Julliard641ee761997-08-04 16:34:36 +00001893{
Alexandre Julliard641ee761997-08-04 16:34:36 +00001894 WORD resinfo;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001895 do {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001896 MENUITEMINFOW mii;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001897
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001898 mii.cbSize = sizeof(mii);
1899 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
1900 mii.fType = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001901 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001902 mii.fState = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001903 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001904 mii.wID = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001905 res += sizeof(DWORD);
1906 resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */
1907 res += sizeof(WORD);
1908 /* Align the text on a word boundary. */
1909 res += (~((int)res - 1)) & 1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001910 mii.dwTypeData = (LPWSTR) res;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001911 res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001912 /* Align the following fields on a dword boundary. */
1913 res += (~((int)res - 1)) & 3;
1914
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001915 TRACE("Menu item: [%08x,%08x,%04x,%04x,%s]\n",
1916 mii.fType, mii.fState, mii.wID, resinfo, debugstr_w(mii.dwTypeData));
Alexandre Julliard641ee761997-08-04 16:34:36 +00001917
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001918 if (resinfo & 1) { /* Pop-up? */
Marcus Meissnerde43ef41999-02-28 19:56:59 +00001919 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
Alexandre Julliard641ee761997-08-04 16:34:36 +00001920 res += sizeof(DWORD);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001921 mii.hSubMenu = CreatePopupMenu();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001922 if (!mii.hSubMenu)
1923 return NULL;
1924 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001925 DestroyMenu(mii.hSubMenu);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001926 return NULL;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001927 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001928 mii.fMask |= MIIM_SUBMENU;
1929 mii.fType |= MF_POPUP;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001930 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001931 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001932 } while (!(resinfo & MF_END));
1933 return res;
1934}
1935
1936
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001937/***********************************************************************
1938 * MENU_GetSubPopup
1939 *
1940 * Return the handle of the selected sub-popup menu (if any).
1941 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001942static HMENU MENU_GetSubPopup( HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001943{
1944 POPUPMENU *menu;
1945 MENUITEM *item;
1946
Gerard Patel3e629742000-01-17 22:22:16 +00001947 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001948
Gerard Patel3e629742000-01-17 22:22:16 +00001949 if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001950
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001951 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001952 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
1953 return item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001954 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001955}
1956
1957
1958/***********************************************************************
1959 * MENU_HideSubPopups
1960 *
1961 * Hide the sub-popup menus of this menu.
1962 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001963static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
1964 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001965{
Gerard Patel3e629742000-01-17 22:22:16 +00001966 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001967
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001968 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, sendMenuSelect);
Juergen Schmied466a6521999-05-02 11:21:08 +00001969
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001970 if (menu && top_popup)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001971 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001972 HMENU hsubmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001973 POPUPMENU *submenu;
1974 MENUITEM *item;
1975
1976 if (menu->FocusedItem != NO_SELECTED_ITEM)
1977 {
1978 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001979 if (!(item->fType & MF_POPUP) ||
1980 !(item->fState & MF_MOUSESELECT)) return;
1981 item->fState &= ~MF_MOUSESELECT;
1982 hsubmenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001983 } else return;
1984
Gerard Patel3e629742000-01-17 22:22:16 +00001985 submenu = MENU_GetMenu( hsubmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001986 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00001987 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001988 DestroyWindow( submenu->hWnd );
1989 submenu->hWnd = 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001990 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001991}
1992
1993
1994/***********************************************************************
1995 * MENU_ShowSubPopup
1996 *
1997 * Display the sub-menu of the selected item of this menu.
1998 * Return the handle of the submenu, or hmenu if no submenu to display.
1999 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002000static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002001 BOOL selectFirst, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002002{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002003 RECT rect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002004 POPUPMENU *menu;
2005 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002006 HDC hdc;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002007
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002008 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, selectFirst);
Juergen Schmied466a6521999-05-02 11:21:08 +00002009
Gerard Patel3e629742000-01-17 22:22:16 +00002010 if (!(menu = MENU_GetMenu( hmenu ))) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002011
Alexandre Julliardde424282001-08-10 22:51:42 +00002012 if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002013
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002014 item = &menu->items[menu->FocusedItem];
Alexandre Julliardde424282001-08-10 22:51:42 +00002015 if (!(item->fType & MF_POPUP) || (item->fState & (MF_GRAYED | MF_DISABLED)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002016 return hmenu;
Alexandre Julliard02e90081998-01-04 17:49:09 +00002017
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002018 /* message must be sent before using item,
2019 because nearly everything may be changed by the application ! */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002020
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002021 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
2022 if (!(wFlags & TPM_NONOTIFY))
2023 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
Alexandre Julliard02e90081998-01-04 17:49:09 +00002024 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
2025
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002026 item = &menu->items[menu->FocusedItem];
2027 rect = item->rect;
2028
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002029 /* correct item if modified as a reaction to WM_INITMENUPOPUP message */
Alexandre Julliard02e90081998-01-04 17:49:09 +00002030 if (!(item->fState & MF_HILITE))
2031 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002032 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
2033 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Juergen Schmied78513941999-04-18 14:40:32 +00002034
2035 SelectObject( hdc, hMenuFont);
2036
Alexandre Julliard02e90081998-01-04 17:49:09 +00002037 item->fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00002038 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002039 ReleaseDC( menu->hWnd, hdc );
Alexandre Julliard02e90081998-01-04 17:49:09 +00002040 }
2041 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
2042 item->rect = rect;
2043
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002044 item->fState |= MF_MOUSESELECT;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002045
2046 if (IS_SYSTEM_MENU(menu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002047 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002048 MENU_InitSysMenuPopup(item->hSubMenu,
2049 GetWindowLongA( menu->hWnd, GWL_STYLE ),
2050 GetClassLongA( menu->hWnd, GCL_STYLE));
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002051
Alexandre Julliardde424282001-08-10 22:51:42 +00002052 NC_GetSysPopupPos( menu->hWnd, &rect );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002053 rect.top = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00002054 rect.right = GetSystemMetrics(SM_CXSIZE);
2055 rect.bottom = GetSystemMetrics(SM_CYSIZE);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002056 }
2057 else
2058 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002059 GetWindowRect( menu->hWnd, &rect );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002060 if (menu->wFlags & MF_POPUP)
2061 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002062 rect.left += item->rect.right - GetSystemMetrics(SM_CXBORDER);
2063 rect.top += item->rect.top;
Ken Thomases130f0d82000-05-10 21:38:37 +00002064 rect.right = item->rect.left - item->rect.right + GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002065 rect.bottom = item->rect.top - item->rect.bottom;
2066 }
2067 else
2068 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002069 rect.left += item->rect.left;
2070 rect.top += item->rect.bottom;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002071 rect.right = item->rect.right - item->rect.left;
2072 rect.bottom = item->rect.bottom - item->rect.top;
2073 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002074 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002075
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002076 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002077 rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002078 if (selectFirst)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002079 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002080 return item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002081}
2082
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002083
2084
2085/**********************************************************************
2086 * MENU_IsMenuActive
2087 */
2088BOOL MENU_IsMenuActive(void)
2089{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00002090 return (top_popup != 0);
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002091}
2092
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002093/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002094 * MENU_PtMenu
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002095 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002096 * Walks menu chain trying to find a menu pt maps to.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002097 */
Alexandre Julliard83f52d12000-09-26 22:20:14 +00002098static HMENU MENU_PtMenu( HMENU hMenu, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002099{
Gerard Patel3e629742000-01-17 22:22:16 +00002100 POPUPMENU *menu = MENU_GetMenu( hMenu );
Alexandre Julliardde424282001-08-10 22:51:42 +00002101 UINT item = menu->FocusedItem;
2102 HMENU ret;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002103
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002104 /* try subpopup first (if any) */
Alexandre Julliardde424282001-08-10 22:51:42 +00002105 ret = (item != NO_SELECTED_ITEM &&
2106 (menu->items[item].fType & MF_POPUP) &&
2107 (menu->items[item].fState & MF_MOUSESELECT))
2108 ? MENU_PtMenu(menu->items[item].hSubMenu, pt) : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002109
Alexandre Julliardde424282001-08-10 22:51:42 +00002110 if (!ret) /* check the current window (avoiding WM_HITTEST) */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002111 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002112 INT ht = NC_HandleNCHitTest( menu->hWnd, pt );
2113 if( menu->wFlags & MF_POPUP )
2114 {
2115 if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu;
2116 }
2117 else if (ht == HTSYSMENU)
2118 ret = get_win_sys_menu( menu->hWnd );
2119 else if (ht == HTMENU)
2120 ret = GetMenu( menu->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002121 }
Alexandre Julliardde424282001-08-10 22:51:42 +00002122 return ret;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002123}
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002124
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002125/***********************************************************************
2126 * MENU_ExecFocusedItem
2127 *
2128 * Execute a menu item (for instance when user pressed Enter).
Karl Lessard13409b31999-09-28 16:24:58 +00002129 * Return the wID of the executed item. Otherwise, -1 indicating
Andreas Mohr2e011a52000-06-01 23:28:25 +00002130 * that no menu item was executed;
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002131 * Have to receive the flags for the TrackPopupMenu options to avoid
2132 * sending unwanted message.
2133 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002134 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002135static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002136{
2137 MENUITEM *item;
Gerard Patel3e629742000-01-17 22:22:16 +00002138 POPUPMENU *menu = MENU_GetMenu( hMenu );
Juergen Schmied466a6521999-05-02 11:21:08 +00002139
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002140 TRACE("%p hmenu=0x%04x\n", pmt, hMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002141
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002142 if (!menu || !menu->nItems ||
Karl Lessard13409b31999-09-28 16:24:58 +00002143 (menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002144
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002145 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002146
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002147 TRACE("%08x %08x %08x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002148 hMenu, item->wID, item->hSubMenu);
2149
2150 if (!(item->fType & MF_POPUP))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002151 {
Francois Gouget93fd46a2000-10-23 00:37:49 +00002152 if (!(item->fState & (MF_GRAYED | MF_DISABLED)) && !(item->fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002153 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002154 /* If TPM_RETURNCMD is set you return the id, but
2155 do not send a message to the owner */
2156 if(!(wFlags & TPM_RETURNCMD))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002157 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002158 if( menu->wFlags & MF_SYSMENU )
2159 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
2160 MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
2161 else
2162 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002163 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002164 return item->wID;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002165 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002166 }
2167 else
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002168 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hMenu, TRUE, wFlags);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002169
Karl Lessard13409b31999-09-28 16:24:58 +00002170 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002171}
2172
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002173/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002174 * MENU_SwitchTracking
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002175 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002176 * Helper function for menu navigation routines.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002177 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002178static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002179{
Gerard Patel3e629742000-01-17 22:22:16 +00002180 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
2181 POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002182
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002183 TRACE("%p hmenu=0x%04x 0x%04x\n", pmt, hPtMenu, id);
Juergen Schmied466a6521999-05-02 11:21:08 +00002184
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002185 if( pmt->hTopMenu != hPtMenu &&
2186 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002187 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002188 /* both are top level menus (system and menu-bar) */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002189 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002190 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002191 pmt->hTopMenu = hPtMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002192 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002193 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002194 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002195}
2196
2197
2198/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002199 * MENU_ButtonDown
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002200 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002201 * Return TRUE if we can go on with menu tracking.
2202 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002203static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002204{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002205 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002206
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002207 if (hPtMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002208 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002209 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002210 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002211 MENUITEM *item;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002212
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002213 if( IS_SYSTEM_MENU(ptmenu) )
2214 item = ptmenu->items;
2215 else
2216 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002217
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002218 if( item )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002219 {
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002220 if( ptmenu->FocusedItem != id )
2221 MENU_SwitchTracking( pmt, hPtMenu, id );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002222
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002223 /* If the popup menu is not already "popped" */
2224 if(!(item->fState & MF_MOUSESELECT ))
Pascal Lessard07c447f1999-09-19 12:03:25 +00002225 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002226 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002227
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002228 /* In win31, a newly popped menu always remains opened for the next buttonup */
Pascal Lessard07c447f1999-09-19 12:03:25 +00002229 if(TWEAK_WineLook == WIN31_LOOK)
2230 ptmenu->bTimeToHide = FALSE;
2231 }
2232
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002233 return TRUE;
2234 }
Pascal Lessard445c9101999-09-20 18:27:14 +00002235 /* Else the click was on the menu bar, finish the tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002236 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002237 return FALSE;
2238}
2239
2240/***********************************************************************
2241 * MENU_ButtonUp
2242 *
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002243 * Return the value of MENU_ExecFocusedItem if
2244 * the selected item was not a popup. Else open the popup.
Karl Lessard13409b31999-09-28 16:24:58 +00002245 * A -1 return value indicates that we go on with menu tracking.
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002246 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002247 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002248static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002249{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002250 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002251
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002252 if (hPtMenu)
2253 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002254 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002255 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002256 MENUITEM *item;
2257
2258 if( IS_SYSTEM_MENU(ptmenu) )
2259 item = ptmenu->items;
2260 else
2261 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2262
Alexandre Julliard491502b1997-11-01 19:08:16 +00002263 if( item && (ptmenu->FocusedItem == id ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002264 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002265 if( !(item->fType & MF_POPUP) )
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002266 return MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002267
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002268 /* If we are dealing with the top-level menu */
2269 /* and this is a click on an already "popped" item: */
2270 /* Stop the menu tracking and close the opened submenus */
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002271 if((pmt->hTopMenu == hPtMenu) && (ptmenu->bTimeToHide == TRUE))
Karl Lessard13409b31999-09-28 16:24:58 +00002272 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002273 }
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002274 ptmenu->bTimeToHide = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002275 }
Karl Lessard13409b31999-09-28 16:24:58 +00002276 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002277}
2278
2279
2280/***********************************************************************
2281 * MENU_MouseMove
2282 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002283 * Return TRUE if we can go on with menu tracking.
2284 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002285static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002286{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002287 UINT id = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002288 POPUPMENU *ptmenu = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002289
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002290 if( hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002291 {
Gerard Patel3e629742000-01-17 22:22:16 +00002292 ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002293 if( IS_SYSTEM_MENU(ptmenu) )
2294 id = 0;
2295 else
2296 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2297 }
2298
2299 if( id == NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002300 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002301 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002302 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
2303
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002304 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002305 else if( ptmenu->FocusedItem != id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002306 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002307 MENU_SwitchTracking( pmt, hPtMenu, id );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002308 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002309 }
2310 return TRUE;
2311}
2312
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002313
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002314/***********************************************************************
2315 * MENU_DoNextMenu
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002316 *
2317 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002318 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002319static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002320{
Gerard Patel3e629742000-01-17 22:22:16 +00002321 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002322
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002323 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
2324 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
2325 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002326 HMENU hNewMenu;
2327 HWND hNewWnd;
2328 UINT id = 0;
Juergen Schmied78513941999-04-18 14:40:32 +00002329 LRESULT l = SendMessageA( pmt->hOwnerWnd, WM_NEXTMENU, vk,
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00002330 (IS_SYSTEM_MENU(menu)) ? GetSubMenu(pmt->hTopMenu,0) : pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002331
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002332 TRACE("%04x [%04x] -> %04x [%04x]\n",
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002333 (UINT16)pmt->hCurrentMenu, (UINT16)pmt->hOwnerWnd, LOWORD(l), HIWORD(l) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002334
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002335 if( l == 0 )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002336 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002337 DWORD style = GetWindowLongA( pmt->hOwnerWnd, GWL_STYLE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002338 hNewWnd = pmt->hOwnerWnd;
2339 if( IS_SYSTEM_MENU(menu) )
2340 {
2341 /* switch to the menu bar */
2342
Alexandre Julliardde424282001-08-10 22:51:42 +00002343 if(style & WS_CHILD || !(hNewMenu = GetMenu(hNewWnd))) return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002344
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002345 if( vk == VK_LEFT )
2346 {
Gerard Patel3e629742000-01-17 22:22:16 +00002347 menu = MENU_GetMenu( hNewMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002348 id = menu->nItems - 1;
2349 }
2350 }
Alexandre Julliardde424282001-08-10 22:51:42 +00002351 else if (style & WS_SYSMENU )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002352 {
2353 /* switch to the system menu */
Alexandre Julliardde424282001-08-10 22:51:42 +00002354 hNewMenu = get_win_sys_menu( hNewWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002355 }
Alexandre Julliardde424282001-08-10 22:51:42 +00002356 else return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002357 }
2358 else /* application returned a new menu to switch to */
2359 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002360 hNewMenu = LOWORD(l);
2361 hNewWnd = HIWORD(l);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002362
Alexandre Julliarda3960291999-02-26 11:11:13 +00002363 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002364 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002365 DWORD style = GetWindowLongA( hNewWnd, GWL_STYLE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002366
Alexandre Julliardde424282001-08-10 22:51:42 +00002367 if (style & WS_SYSMENU &&
2368 GetSubMenu(get_win_sys_menu(hNewWnd), 0) == hNewMenu )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002369 {
2370 /* get the real system menu */
Alexandre Julliardde424282001-08-10 22:51:42 +00002371 hNewMenu = get_win_sys_menu(hNewWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002372 }
Alexandre Julliardde424282001-08-10 22:51:42 +00002373 else if (style & WS_CHILD || GetMenu(hNewWnd) != hNewMenu )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002374 {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002375 /* FIXME: Not sure what to do here;
2376 * perhaps try to track hNewMenu as a popup? */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002377
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002378 TRACE(" -- got confused.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002379 return FALSE;
2380 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002381 }
2382 else return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002383 }
2384
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002385 if( hNewMenu != pmt->hTopMenu )
2386 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002387 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM,
2388 FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002389 if( pmt->hCurrentMenu != pmt->hTopMenu )
2390 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2391 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002392
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002393 if( hNewWnd != pmt->hOwnerWnd )
2394 {
2395 ReleaseCapture();
2396 pmt->hOwnerWnd = hNewWnd;
2397 EVENT_Capture( pmt->hOwnerWnd, HTMENU );
2398 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002399
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002400 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
Rein Klazes80c924f1999-12-12 19:40:46 +00002401 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002402
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002403 return TRUE;
2404 }
2405 return FALSE;
2406}
2407
2408/***********************************************************************
2409 * MENU_SuspendPopup
2410 *
2411 * The idea is not to show the popup if the next input message is
2412 * going to hide it anyway.
2413 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002414static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT16 uMsg )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002415{
Juergen Schmied78513941999-04-18 14:40:32 +00002416 MSG msg;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002417
2418 msg.hwnd = pmt->hOwnerWnd;
2419
Juergen Schmied78513941999-04-18 14:40:32 +00002420 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002421 pmt->trackFlags |= TF_SKIPREMOVE;
2422
2423 switch( uMsg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002424 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002425 case WM_KEYDOWN:
Juergen Schmied78513941999-04-18 14:40:32 +00002426 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002427 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
2428 {
Juergen Schmied78513941999-04-18 14:40:32 +00002429 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
2430 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002431 if( msg.message == WM_KEYDOWN &&
2432 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
2433 {
2434 pmt->trackFlags |= TF_SUSPENDPOPUP;
2435 return TRUE;
2436 }
2437 }
2438 break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002439 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002440
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002441 /* failures go through this */
2442 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
2443 return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002444}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002445
2446/***********************************************************************
Ulrich Czekalla18ce3882001-05-18 23:20:20 +00002447 * MENU_KeyEscape
2448 *
2449 * Handle a VK_ESCAPE key event in a menu.
2450 */
2451static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags)
2452{
2453 BOOL bEndMenu = TRUE;
2454
2455 if (pmt->hCurrentMenu != pmt->hTopMenu)
2456 {
2457 POPUPMENU *menu = MENU_GetMenu(pmt->hCurrentMenu);
2458
2459 if (menu->wFlags & MF_POPUP)
2460 {
2461 HMENU hmenutmp, hmenuprev;
2462
2463 hmenuprev = hmenutmp = pmt->hTopMenu;
2464
2465 /* close topmost popup */
2466 while (hmenutmp != pmt->hCurrentMenu)
2467 {
2468 hmenuprev = hmenutmp;
2469 hmenutmp = MENU_GetSubPopup( hmenuprev );
2470 }
2471
2472 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2473 pmt->hCurrentMenu = hmenuprev;
2474 bEndMenu = FALSE;
2475 }
2476 }
2477
2478 return bEndMenu;
2479}
2480
2481/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002482 * MENU_KeyLeft
2483 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002484 * Handle a VK_LEFT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002485 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002486static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002487{
2488 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002489 HMENU hmenutmp, hmenuprev;
2490 UINT prevcol;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002491
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002492 hmenuprev = hmenutmp = pmt->hTopMenu;
Gerard Patel3e629742000-01-17 22:22:16 +00002493 menu = MENU_GetMenu( hmenutmp );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002494
Alexandre Julliard641ee761997-08-04 16:34:36 +00002495 /* Try to move 1 column left (if possible) */
2496 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
2497 NO_SELECTED_ITEM ) {
2498
2499 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002500 prevcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002501 return;
2502 }
2503
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002504 /* close topmost popup */
2505 while (hmenutmp != pmt->hCurrentMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002506 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002507 hmenuprev = hmenutmp;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002508 hmenutmp = MENU_GetSubPopup( hmenuprev );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002509 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002510
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002511 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2512 pmt->hCurrentMenu = hmenuprev;
2513
2514 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002515 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002516 /* move menu bar selection if no more popups are left */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002517
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002518 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
2519 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002520
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002521 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002522 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002523 /* A sublevel menu was displayed - display the next one
2524 * unless there is another displacement coming up */
2525
2526 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002527 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2528 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002529 }
2530 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002531}
2532
2533
2534/***********************************************************************
2535 * MENU_KeyRight
2536 *
2537 * Handle a VK_RIGHT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002538 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002539static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002540{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002541 HMENU hmenutmp;
Gerard Patel3e629742000-01-17 22:22:16 +00002542 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002543 UINT nextcol;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002544
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002545 TRACE("MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
Alexandre Julliard641ee761997-08-04 16:34:36 +00002546 pmt->hCurrentMenu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00002547 debugstr_w((MENU_GetMenu(pmt->hCurrentMenu))->
2548 items[0].text),
2549 pmt->hTopMenu, debugstr_w(menu->items[0].text) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002550
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002551 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002552 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002553 /* If already displaying a popup, try to display sub-popup */
2554
2555 hmenutmp = pmt->hCurrentMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002556 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hmenutmp, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002557
2558 /* if subpopup was displayed then we are done */
2559 if (hmenutmp != pmt->hCurrentMenu) return;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002560 }
2561
Alexandre Julliard641ee761997-08-04 16:34:36 +00002562 /* Check to see if there's another column */
2563 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
2564 NO_SELECTED_ITEM ) {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002565 TRACE("Going to %d.\n", nextcol );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002566 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002567 nextcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002568 return;
2569 }
2570
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002571 if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002572 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002573 if( pmt->hCurrentMenu != pmt->hTopMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002574 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002575 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2576 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
2577 } else hmenutmp = 0;
2578
2579 /* try to move to the next item */
2580 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
2581 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
2582
2583 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
2584 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002585 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2586 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002587 }
2588}
2589
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002590/***********************************************************************
2591 * MENU_TrackMenu
2592 *
2593 * Menu tracking code.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002594 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002595static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
2596 HWND hwnd, const RECT *lprect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002597{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002598 MSG msg;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002599 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002600 BOOL fRemove;
Karl Lessard13409b31999-09-28 16:24:58 +00002601 INT executedMenuId = -1;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002602 MTRACKER mt;
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002603 BOOL enterIdleSent = FALSE;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002604
2605 mt.trackFlags = 0;
2606 mt.hCurrentMenu = hmenu;
2607 mt.hTopMenu = hmenu;
2608 mt.hOwnerWnd = hwnd;
2609 mt.pt.x = x;
2610 mt.pt.y = y;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002611
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002612 TRACE("hmenu=0x%04x flags=0x%08x (%d,%d) hwnd=0x%04x (%d,%d)-(%d,%d)\n",
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002613 hmenu, wFlags, x, y, hwnd, (lprect) ? lprect->left : 0, (lprect) ? lprect->top : 0,
2614 (lprect) ? lprect->right : 0, (lprect) ? lprect->bottom : 0);
Juergen Schmied78513941999-04-18 14:40:32 +00002615
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002616 fEndMenu = FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00002617 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002618
Pascal Lessardae6de762000-01-09 02:38:02 +00002619 if (wFlags & TPM_BUTTONDOWN)
2620 {
2621 /* Get the result in order to start the tracking or not */
2622 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2623 fEndMenu = !fRemove;
2624 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002625
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002626 EVENT_Capture( mt.hOwnerWnd, HTMENU );
2627
2628 while (!fEndMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002629 {
Gerard Patel3e629742000-01-17 22:22:16 +00002630 menu = MENU_GetMenu( mt.hCurrentMenu );
Marcus Meissner4a699392001-02-13 01:49:06 +00002631 if (!menu) /* sometimes happens if I do a window manager close */
2632 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002633
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002634 /* we have to keep the message in the queue until it's
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002635 * clear that menu loop is not over yet. */
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002636
Alexandre Julliardbfb4a232001-08-06 18:05:47 +00002637 for (;;)
2638 {
2639 if (PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ))
2640 {
2641 if (!CallMsgFilterA( &msg, MSGF_MENU )) break;
2642 /* remove the message from the queue */
2643 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
2644 }
2645 else
2646 {
2647 if (!enterIdleSent)
2648 {
2649 HWND win = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
2650 enterIdleSent = TRUE;
2651 SendMessageW( mt.hOwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM)win );
2652 }
2653 WaitMessage();
2654 }
2655 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002656
Rob Farnumb2007932000-05-23 23:34:17 +00002657 /* check if EndMenu() tried to cancel us, by posting this message */
2658 if(msg.message == WM_CANCELMODE)
2659 {
2660 /* we are now out of the loop */
2661 fEndMenu = TRUE;
2662
2663 /* remove the message from the queue */
2664 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
2665
2666 /* break out of internal loop, ala ESCAPE */
2667 break;
2668 }
2669
Alexandre Julliarda3960291999-02-26 11:11:13 +00002670 TranslateMessage( &msg );
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002671 mt.pt = msg.pt;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002672
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002673 if ( (msg.hwnd==menu->hWnd) || (msg.message!=WM_TIMER) )
2674 enterIdleSent=FALSE;
2675
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002676 fRemove = FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002677 if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002678 {
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002679 /*
2680 * use the mouse coordinates in lParam instead of those in the MSG
2681 * struct to properly handle synthetic messages. lParam coords are
2682 * relative to client area, so they must be converted; since they can
2683 * be negative, we must use SLOWORD/SHIWORD instead of LOWORD/HIWORD.
2684 */
2685 mt.pt.x = SLOWORD(msg.lParam);
2686 mt.pt.y = SHIWORD(msg.lParam);
2687 ClientToScreen(msg.hwnd,&mt.pt);
2688
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002689 /* Find a menu for this mouse event */
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002690 hmenu = MENU_PtMenu( mt.hTopMenu, mt.pt );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002691
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002692 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002693 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002694 /* no WM_NC... messages in captured state */
2695
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002696 case WM_RBUTTONDBLCLK:
2697 case WM_RBUTTONDOWN:
2698 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2699 /* fall through */
2700 case WM_LBUTTONDBLCLK:
2701 case WM_LBUTTONDOWN:
Karl Lessard4a0a7df1999-11-07 05:17:10 +00002702 /* If the message belongs to the menu, removes it from the queue */
2703 /* Else, end menu tracking */
2704 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2705 fEndMenu = !fRemove;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002706 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002707
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002708 case WM_RBUTTONUP:
2709 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2710 /* fall through */
2711 case WM_LBUTTONUP:
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002712 /* Check if a menu was selected by the mouse */
2713 if (hmenu)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002714 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002715 executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002716
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002717 /* End the loop if executedMenuId is an item ID */
Karl Lessard13409b31999-09-28 16:24:58 +00002718 /* or if the job was done (executedMenuId = 0). */
2719 fEndMenu = fRemove = (executedMenuId != -1);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002720 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002721 /* No menu was selected by the mouse */
2722 /* if the function was called by TrackPopupMenu, continue
2723 with the menu tracking. If not, stop it */
2724 else
2725 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
2726
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002727 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002728
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002729 case WM_MOUSEMOVE:
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002730 /* In win95 winelook, the selected menu item must be changed every time the
2731 mouse moves. In Win31 winelook, the mouse button has to be held down */
2732
2733 if ( (TWEAK_WineLook > WIN31_LOOK) ||
2734 ( (msg.wParam & MK_LBUTTON) ||
2735 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
2736
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002737 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002738
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002739 } /* switch(msg.message) - mouse */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002740 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002741 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002742 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002743 fRemove = TRUE; /* Keyboard messages are always removed */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002744 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002745 {
2746 case WM_KEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002747 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002748 {
2749 case VK_HOME:
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002750 case VK_END:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002751 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002752 NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002753 /* fall through */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002754 case VK_UP:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002755 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002756 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002757 break;
2758
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002759 case VK_DOWN: /* If on menu bar, pull-down the menu */
2760
Gerard Patel3e629742000-01-17 22:22:16 +00002761 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002762 if (!(menu->wFlags & MF_POPUP))
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002763 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002764 else /* otherwise try to move selection */
2765 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002766 break;
2767
2768 case VK_LEFT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002769 MENU_KeyLeft( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002770 break;
2771
2772 case VK_RIGHT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002773 MENU_KeyRight( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002774 break;
2775
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002776 case VK_ESCAPE:
Ulrich Czekalla18ce3882001-05-18 23:20:20 +00002777 fEndMenu = MENU_KeyEscape(&mt, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002778 break;
2779
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002780 case VK_F1:
2781 {
2782 HELPINFO hi;
2783 hi.cbSize = sizeof(HELPINFO);
2784 hi.iContextType = HELPINFO_MENUITEM;
2785 if (menu->FocusedItem == NO_SELECTED_ITEM)
2786 hi.iCtrlId = 0;
2787 else
2788 hi.iCtrlId = menu->items[menu->FocusedItem].wID;
2789 hi.hItemHandle = hmenu;
2790 hi.dwContextId = menu->dwContextHelpID;
2791 hi.MousePos = msg.pt;
2792 SendMessageA(hwnd, WM_HELP, 0, (LPARAM)&hi);
2793 break;
2794 }
2795
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002796 default:
2797 break;
2798 }
2799 break; /* WM_KEYDOWN */
2800
2801 case WM_SYSKEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002802 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002803 {
2804 case VK_MENU:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002805 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002806 break;
2807
2808 }
2809 break; /* WM_SYSKEYDOWN */
2810
2811 case WM_CHAR:
2812 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002813 UINT pos;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002814
Norman Stevensa83d0651998-10-12 07:25:35 +00002815 if (msg.wParam == '\r' || msg.wParam == ' ')
2816 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002817 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002818 fEndMenu = (executedMenuId != -1);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002819
Norman Stevensa83d0651998-10-12 07:25:35 +00002820 break;
2821 }
2822
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002823 /* Hack to avoid control chars. */
2824 /* We will find a better way real soon... */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002825 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002826
2827 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002828 LOWORD(msg.wParam), FALSE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002829 if (pos == (UINT)-2) fEndMenu = TRUE;
2830 else if (pos == (UINT)-1) MessageBeep(0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002831 else
2832 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002833 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos,
2834 TRUE, 0 );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002835 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002836 fEndMenu = (executedMenuId != -1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002837 }
2838 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002839 break;
2840 } /* switch(msg.message) - kbd */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002841 }
2842 else
2843 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002844 DispatchMessageA( &msg );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002845 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002846
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002847 if (!fEndMenu) fRemove = TRUE;
2848
2849 /* finally remove message from the queue */
2850
2851 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002852 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002853 else mt.trackFlags &= ~TF_SKIPREMOVE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002854 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002855
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002856 ReleaseCapture();
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002857
Guy Albertellif12b70a2000-05-11 00:06:11 +00002858 /* If dropdown is still painted and the close box is clicked on
2859 then the menu will be destroyed as part of the DispatchMessage above.
2860 This will then invalidate the menu handle in mt.hTopMenu. We should
2861 check for this first. */
2862 if( IsMenu( mt.hTopMenu ) )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002863 {
Guy Albertellif12b70a2000-05-11 00:06:11 +00002864 menu = MENU_GetMenu( mt.hTopMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002865
Guy Albertellif12b70a2000-05-11 00:06:11 +00002866 if( IsWindow( mt.hOwnerWnd ) )
2867 {
2868 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
2869
2870 if (menu && menu->wFlags & MF_POPUP)
2871 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00002872 DestroyWindow( menu->hWnd );
2873 menu->hWnd = 0;
Guy Albertellif12b70a2000-05-11 00:06:11 +00002874 }
2875 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
2876 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
2877 }
2878
2879 /* Reset the variable for hiding menu */
2880 if( menu ) menu->bTimeToHide = FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002881 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002882
Juergen Schmied371c4201999-10-13 12:27:44 +00002883 /* The return value is only used by TrackPopupMenu */
2884 return ((executedMenuId != -1) ? executedMenuId : 0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002885}
2886
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002887/***********************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002888 * MENU_InitTracking
2889 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002890static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002891{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002892 TRACE("hwnd=0x%04x hmenu=0x%04x\n", hWnd, hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00002893
Alexandre Julliarda3960291999-02-26 11:11:13 +00002894 HideCaret(0);
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002895
2896 /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
2897 if (!(wFlags & TPM_NONOTIFY))
2898 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
2899
Juergen Schmied78513941999-04-18 14:40:32 +00002900 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002901
2902 if (!(wFlags & TPM_NONOTIFY))
Gerard Patelcf2ff272001-03-14 17:24:59 +00002903 {
2904 POPUPMENU *menu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002905 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
Gerard Patelcf2ff272001-03-14 17:24:59 +00002906 if ((menu = MENU_GetMenu( hMenu )) && (!menu->Height))
2907 { /* app changed/recreated menu bar entries in WM_INITMENU
2908 Recalculate menu sizes else clicks will not work */
Gerard Patel326b2802001-07-17 00:43:22 +00002909 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
2910 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
2911
Gerard Patelcf2ff272001-03-14 17:24:59 +00002912 }
2913 }
Juergen Schmied78513941999-04-18 14:40:32 +00002914 return TRUE;
2915}
2916/***********************************************************************
2917 * MENU_ExitTracking
2918 */
2919static BOOL MENU_ExitTracking(HWND hWnd)
2920{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002921 TRACE("hwnd=0x%04x\n", hWnd);
Juergen Schmied78513941999-04-18 14:40:32 +00002922
2923 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
2924 ShowCaret(0);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002925 return TRUE;
2926}
2927
2928/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002929 * MENU_TrackMouseMenuBar
2930 *
2931 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
2932 */
Alexandre Julliardde424282001-08-10 22:51:42 +00002933void MENU_TrackMouseMenuBar( HWND hWnd, INT ht, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002934{
Alexandre Julliardde424282001-08-10 22:51:42 +00002935 HMENU hMenu = (ht == HTSYSMENU) ? get_win_sys_menu( hWnd ) : GetMenu( hWnd );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002936 UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002937
Alexandre Julliardde424282001-08-10 22:51:42 +00002938 TRACE("wnd=%x ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
Juergen Schmied78513941999-04-18 14:40:32 +00002939
Alexandre Julliarda3960291999-02-26 11:11:13 +00002940 if (IsMenu(hMenu))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002941 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002942 MENU_InitTracking( hWnd, hMenu, FALSE, wFlags );
2943 MENU_TrackMenu( hMenu, wFlags, pt.x, pt.y, hWnd, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00002944 MENU_ExitTracking(hWnd);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002945 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002946}
2947
2948
2949/***********************************************************************
2950 * MENU_TrackKbdMenuBar
2951 *
2952 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
2953 */
Alexandre Julliardde424282001-08-10 22:51:42 +00002954void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam, INT vkey)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002955{
Alexandre Julliardde424282001-08-10 22:51:42 +00002956 UINT uItem = NO_SELECTED_ITEM;
2957 HMENU hTrackMenu;
2958 UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002959
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002960 /* find window that has a menu */
Alexandre Julliardde424282001-08-10 22:51:42 +00002961
2962 while (GetWindowLongA( hwnd, GWL_STYLE ) & WS_CHILD)
2963 if (!(hwnd = GetParent( hwnd ))) return;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002964
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002965 /* check if we have to track a system menu */
Alexandre Julliardde424282001-08-10 22:51:42 +00002966
2967 hTrackMenu = GetMenu( hwnd );
2968 if (!hTrackMenu || IsIconic(hwnd) || vkey == VK_SPACE )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002969 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002970 if (!(GetWindowLongA( hwnd, GWL_STYLE ) & WS_SYSMENU)) return;
2971 hTrackMenu = get_win_sys_menu( hwnd );
2972 uItem = 0;
2973 wParam |= HTSYSMENU; /* prevent item lookup */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002974 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002975
Alexandre Julliardde424282001-08-10 22:51:42 +00002976 if (!IsMenu( hTrackMenu )) return;
2977
2978 MENU_InitTracking( hwnd, hTrackMenu, FALSE, wFlags );
2979
2980 if( vkey && vkey != VK_SPACE )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002981 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002982 uItem = MENU_FindItemByKey( hwnd, hTrackMenu, vkey, (wParam & HTSYSMENU) );
2983 if( uItem >= (UINT)(-2) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002984 {
Alexandre Julliardde424282001-08-10 22:51:42 +00002985 if( uItem == (UINT)(-1) ) MessageBeep(0);
2986 hTrackMenu = 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002987 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002988 }
Alexandre Julliardde424282001-08-10 22:51:42 +00002989
2990 if( hTrackMenu )
2991 {
2992 MENU_SelectItem( hwnd, hTrackMenu, uItem, TRUE, 0 );
2993
2994 if( uItem == NO_SELECTED_ITEM )
2995 MENU_MoveSelection( hwnd, hTrackMenu, ITEM_NEXT );
2996 else if( vkey )
2997 PostMessageA( hwnd, WM_KEYDOWN, VK_DOWN, 0L );
2998
2999 MENU_TrackMenu( hTrackMenu, wFlags, 0, 0, hwnd, NULL );
3000 }
3001 MENU_ExitTracking( hwnd );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003002}
3003
3004
3005/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003006 * TrackPopupMenu (USER.416)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003007 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003008BOOL16 WINAPI TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
3009 INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003010{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003011 RECT r;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003012 if (lpRect)
3013 CONV_RECT16TO32( lpRect, &r );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003014 return TrackPopupMenu( hMenu, wFlags, x, y, nReserved, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003015 lpRect ? &r : NULL );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003016}
3017
3018
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003019/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003020 * TrackPopupMenu (USER32.@)
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003021 *
3022 * Like the win32 API, the function return the command ID only if the
3023 * flag TPM_RETURNCMD is on.
3024 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003025 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003026BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
3027 INT nReserved, HWND hWnd, const RECT *lpRect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003028{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003029 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003030
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003031 MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
3032
3033 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
3034 if (!(wFlags & TPM_NONOTIFY))
3035 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
3036
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003037 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00003038 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
Juergen Schmied78513941999-04-18 14:40:32 +00003039 MENU_ExitTracking(hWnd);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003040
3041 if( (!(wFlags & TPM_RETURNCMD)) && (ret != FALSE) )
3042 ret = 1;
3043
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003044 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003045}
3046
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003047/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003048 * TrackPopupMenuEx (USER32.@)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003049 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003050BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
3051 HWND hWnd, LPTPMPARAMS lpTpm )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003052{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003053 FIXME("not fully implemented\n" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003054 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003055 lpTpm ? &lpTpm->rcExclude : NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003056}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003057
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003058/***********************************************************************
3059 * PopupMenuWndProc
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003060 *
3061 * NOTE: Windows has totally different (and undocumented) popup wndproc.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003062 */
Alexandre Julliard91222da2000-12-10 23:01:33 +00003063static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
3064{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003065 TRACE("hwnd=0x%04x msg=0x%04x wp=0x%04x lp=0x%08lx\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003066 hwnd, message, wParam, lParam);
3067
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003068 switch(message)
3069 {
3070 case WM_CREATE:
3071 {
Alexandre Julliard91222da2000-12-10 23:01:33 +00003072 CREATESTRUCTW *cs = (CREATESTRUCTW*)lParam;
3073 SetWindowLongW( hwnd, 0, (LONG)cs->lpCreateParams );
3074 return 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003075 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003076
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003077 case WM_MOUSEACTIVATE: /* We don't want to be activated */
Alexandre Julliard91222da2000-12-10 23:01:33 +00003078 return MA_NOACTIVATE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003079
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003080 case WM_PAINT:
3081 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003082 PAINTSTRUCT ps;
3083 BeginPaint( hwnd, &ps );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003084 MENU_DrawPopupMenu( hwnd, ps.hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +00003085 (HMENU)GetWindowLongA( hwnd, 0 ) );
3086 EndPaint( hwnd, &ps );
Alexandre Julliard91222da2000-12-10 23:01:33 +00003087 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003088 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003089 case WM_ERASEBKGND:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003090 return 1;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003091
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003092 case WM_DESTROY:
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003093 /* zero out global pointer in case resident popup window was destroyed. */
3094 if (hwnd == top_popup) top_popup = 0;
3095 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003096
3097 case WM_SHOWWINDOW:
3098
3099 if( wParam )
3100 {
Alexandre Julliard91222da2000-12-10 23:01:33 +00003101 if (!GetWindowLongW( hwnd, 0 )) ERR("no menu to display\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003102 }
3103 else
Alexandre Julliard91222da2000-12-10 23:01:33 +00003104 SetWindowLongW( hwnd, 0, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003105 break;
3106
3107 case MM_SETMENUHANDLE:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003108 SetWindowLongW( hwnd, 0, wParam );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003109 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003110
3111 case MM_GETMENUHANDLE:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003112 return GetWindowLongW( hwnd, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003113
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003114 default:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003115 return DefWindowProcW( hwnd, message, wParam, lParam );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003116 }
Alexandre Julliard91222da2000-12-10 23:01:33 +00003117 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003118}
3119
3120
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00003121/***********************************************************************
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003122 * MENU_GetMenuBarHeight
3123 *
3124 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
3125 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003126UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
3127 INT orgX, INT orgY )
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003128{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003129 HDC hdc;
3130 RECT rectBar;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003131 LPPOPUPMENU lppop;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003132
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003133 TRACE("HWND 0x%x, width %d, at (%d, %d).\n",
Alexandre Julliardde424282001-08-10 22:51:42 +00003134 hwnd, menubarWidth, orgX, orgY );
Juergen Schmied78513941999-04-18 14:40:32 +00003135
Alexandre Julliardde424282001-08-10 22:51:42 +00003136 if (!(lppop = MENU_GetMenu( GetMenu(hwnd) ))) return 0;
Juergen Schmied78513941999-04-18 14:40:32 +00003137
Alexandre Julliarda3960291999-02-26 11:11:13 +00003138 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
Juergen Schmied78513941999-04-18 14:40:32 +00003139 SelectObject( hdc, hMenuFont);
Marcus Meissnerddca3151999-05-22 11:33:23 +00003140 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
Juergen Schmied78513941999-04-18 14:40:32 +00003141 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003142 ReleaseDC( hwnd, hdc );
Alexandre Julliardde424282001-08-10 22:51:42 +00003143 return lppop->Height;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003144}
3145
3146
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003147/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003148 * ChangeMenu (USER.153)
Alexandre Julliard401710d1993-09-04 10:09:32 +00003149 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003150BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
3151 UINT16 id, UINT16 flags )
Alexandre Julliard401710d1993-09-04 10:09:32 +00003152{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003153 TRACE("menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003154 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003155 if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND,
3156 id, data );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003157
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003158 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
3159 /* for MF_DELETE. We should check the parameters for all others */
3160 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003161
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003162 if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
3163 if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
3164 id, data );
3165 if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003166 flags & MF_BYPOSITION ? pos : id,
3167 flags & ~MF_REMOVE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003168 /* Default: MF_INSERT */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003169 return InsertMenu16( hMenu, pos, flags, id, data );
3170}
3171
3172
3173/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003174 * ChangeMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003175 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003176BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
3177 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003178{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003179 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003180 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003181 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003182 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003183 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3184 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003185 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003186 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003187 flags & MF_BYPOSITION ? pos : id,
3188 flags & ~MF_REMOVE );
3189 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003190 return InsertMenuA( hMenu, pos, flags, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003191}
3192
3193
3194/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003195 * ChangeMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003196 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003197BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
3198 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003199{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003200 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003201 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003202 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003203 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003204 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3205 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003206 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003207 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003208 flags & MF_BYPOSITION ? pos : id,
3209 flags & ~MF_REMOVE );
3210 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003211 return InsertMenuW( hMenu, pos, flags, id, data );
Alexandre Julliard401710d1993-09-04 10:09:32 +00003212}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003213
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003214
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003215/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003216 * CheckMenuItem (USER.154)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003217 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003218BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003219{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003220 return (BOOL16)CheckMenuItem( hMenu, id, flags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003221}
3222
3223
3224/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003225 * CheckMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003226 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003227DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003228{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003229 MENUITEM *item;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003230 DWORD ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003231
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003232 TRACE("menu=%04x id=%04x flags=%04x\n", hMenu, id, flags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003233 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003234 ret = item->fState & MF_CHECKED;
3235 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
3236 else item->fState &= ~MF_CHECKED;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003237 return ret;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003238}
3239
3240
3241/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003242 * EnableMenuItem (USER.155)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003243 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003244UINT16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003245{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003246 return EnableMenuItem( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003247}
3248
3249
3250/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003251 * EnableMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003252 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003253UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003254{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003255 UINT oldflags;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003256 MENUITEM *item;
Pascal Lessardd814bb61999-07-31 13:02:02 +00003257 POPUPMENU *menu;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003258
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003259 TRACE("(%04x, %04X, %04X) !\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003260 hMenu, wItemID, wFlags);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003261
Pascal Lessardd814bb61999-07-31 13:02:02 +00003262 /* Get the Popupmenu to access the owner menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003263 if (!(menu = MENU_GetMenu(hMenu)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003264 return (UINT)-1;
3265
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003266 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003267 return (UINT)-1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003268
3269 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
3270 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003271
3272 /* In win95 if the close item in the system menu change update the close button */
3273 if (TWEAK_WineLook == WIN95_LOOK)
3274 if((item->wID == SC_CLOSE) && (oldflags != wFlags))
3275 {
3276 if (menu->hSysMenuOwner != 0)
3277 {
3278 POPUPMENU* parentMenu;
3279
3280 /* Get the parent menu to access*/
Gerard Patel3e629742000-01-17 22:22:16 +00003281 if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003282 return (UINT)-1;
3283
3284 /* Refresh the frame to reflect the change*/
3285 SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
Stephane Lussiera833f631999-08-21 14:46:06 +00003286 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003287 }
3288 }
3289
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003290 return oldflags;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003291}
3292
3293
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003294/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003295 * GetMenuString (USER.161)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003296 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003297INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
3298 LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003299{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003300 return GetMenuStringA( hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003301}
3302
3303
3304/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003305 * GetMenuStringA (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003306 */
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003307INT WINAPI GetMenuStringA(
3308 HMENU hMenu, /* [in] menuhandle */
3309 UINT wItemID, /* [in] menu item (dep. on wFlags) */
3310 LPSTR str, /* [out] outbuffer. If NULL, func returns entry length*/
3311 INT nMaxSiz, /* [in] length of buffer. if 0, func returns entry len*/
3312 UINT wFlags /* [in] MF_ flags */
3313) {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003314 MENUITEM *item;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003315
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003316 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003317 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003318 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003319 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003320 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003321 str[0] = '\0';
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00003322 if (!WideCharToMultiByte( CP_ACP, 0, item->text, -1, str, nMaxSiz, NULL, NULL ))
3323 str[nMaxSiz-1] = 0;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003324 TRACE("returning '%s'\n", str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003325 return strlen(str);
Alexandre Julliard1f579291994-05-25 16:25:21 +00003326}
3327
3328
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003329/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003330 * GetMenuStringW (USER32.@)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003331 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003332INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
3333 LPWSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003334{
3335 MENUITEM *item;
3336
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003337 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003338 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003339 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003340 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003341 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003342 str[0] = '\0';
Aric Stewartc946b1c2000-10-24 21:28:19 +00003343 lstrcpynW( str, item->text, nMaxSiz );
3344 return strlenW(str);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003345}
3346
3347
3348/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003349 * HiliteMenuItem (USER.162)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003350 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003351BOOL16 WINAPI HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
3352 UINT16 wHilite )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003353{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003354 return HiliteMenuItem( hWnd, hMenu, wItemID, wHilite );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003355}
3356
3357
3358/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003359 * HiliteMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003360 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003361BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
3362 UINT wHilite )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003363{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003364 LPPOPUPMENU menu;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003365 TRACE("(%04x, %04x, %04x, %04x);\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003366 hWnd, hMenu, wItemID, wHilite);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003367 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003368 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003369 if (menu->FocusedItem == wItemID) return TRUE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003370 MENU_HideSubPopups( hWnd, hMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00003371 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003372 return TRUE;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003373}
3374
3375
3376/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003377 * GetMenuState (USER.250)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003378 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003379UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003380{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003381 return GetMenuState( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003382}
3383
3384
3385/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003386 * GetMenuState (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003387 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003388UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003389{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003390 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003391 TRACE("(menu=%04x, id=%04x, flags=%04x);\n",
Alexandre Julliardaca05781994-10-17 18:12:41 +00003392 hMenu, wItemID, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003393 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
Alexandre Julliard03468f71998-02-15 19:40:49 +00003394 debug_print_menuitem (" item: ", item, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003395 if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003396 {
Gerard Patel3e629742000-01-17 22:22:16 +00003397 POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003398 if (!menu) return -1;
Alexandre Julliard829fe321998-07-26 14:27:39 +00003399 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003400 }
Alexandre Julliard889f7421997-04-15 17:19:52 +00003401 else
Alexandre Julliard491502b1997-11-01 19:08:16 +00003402 {
Alexandre Julliard829fe321998-07-26 14:27:39 +00003403 /* We used to (from way back then) mask the result to 0xff. */
3404 /* I don't know why and it seems wrong as the documented */
3405 /* return flag MF_SEPARATOR is outside that mask. */
3406 return (item->fType | item->fState);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003407 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003408}
3409
3410
3411/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003412 * GetMenuItemCount (USER.263)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003413 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003414INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003415{
Gerard Patel3e629742000-01-17 22:22:16 +00003416 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3417 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003418 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003419 hMenu, menu->nItems );
3420 return menu->nItems;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003421}
3422
3423
3424/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003425 * GetMenuItemCount (USER32.@)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003426 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003427INT WINAPI GetMenuItemCount( HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003428{
Gerard Patel3e629742000-01-17 22:22:16 +00003429 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3430 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003431 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003432 hMenu, menu->nItems );
3433 return menu->nItems;
3434}
3435
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003436/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003437 * GetMenuItemID (USER.264)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003438 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003439UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003440{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003441 return (UINT16) GetMenuItemID (hMenu, nPos);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003442}
3443
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003444/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003445 * GetMenuItemID (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003446 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003447UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003448{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003449 MENUITEM * lpmi;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003450
Mike McCormack34329cf2001-07-10 19:06:12 +00003451 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return -1;
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003452 if (lpmi->fType & MF_POPUP) return -1;
3453 return lpmi->wID;
3454
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003455}
3456
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003457/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003458 * InsertMenu (USER.410)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003459 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003460BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3461 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003462{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003463 UINT pos32 = (UINT)pos;
3464 if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003465 if (IS_STRING_ITEM(flags) && data)
Alexandre Julliard982a2232000-12-13 20:20:09 +00003466 return InsertMenuA( hMenu, pos32, flags, id, MapSL(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003467 return InsertMenuA( hMenu, pos32, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003468}
3469
3470
3471/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003472 * InsertMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003473 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003474BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
3475 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003476{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003477 MENUITEM *item;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003478
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003479 if (IS_STRING_ITEM(flags) && str)
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003480 TRACE("hMenu %04x, pos %d, flags %08x, "
Francois Gougete76218d2001-05-09 17:31:31 +00003481 "id %04x, str %s\n",
Aric Stewartc946b1c2000-10-24 21:28:19 +00003482 hMenu, pos, flags, id, debugstr_w(str) );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003483 else TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003484 "id %04x, str %08lx (not a string)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003485 hMenu, pos, flags, id, (DWORD)str );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003486
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003487 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003488
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003489 if (!(MENU_SetItemData( item, flags, id, str )))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003490 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003491 RemoveMenu( hMenu, pos, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003492 return FALSE;
3493 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003494
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003495 if (flags & MF_POPUP) /* Set the MF_POPUP flag on the popup-menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003496 (MENU_GetMenu((HMENU16)id))->wFlags |= MF_POPUP;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003497
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003498 item->hCheckBit = item->hUnCheckBit = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003499 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003500}
3501
3502
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003503/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003504 * InsertMenuA (USER32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003505 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003506BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
3507 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003508{
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00003509 BOOL ret = FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003510
3511 if (IS_STRING_ITEM(flags) && str)
3512 {
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00003513 INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
3514 LPWSTR newstr = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3515 if (newstr)
3516 {
3517 MultiByteToWideChar( CP_ACP, 0, str, -1, newstr, len );
3518 ret = InsertMenuW( hMenu, pos, flags, id, newstr );
3519 HeapFree( GetProcessHeap(), 0, newstr );
3520 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003521 return ret;
3522 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003523 else return InsertMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003524}
3525
3526
3527/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003528 * AppendMenu (USER.411)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003529 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003530BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003531{
3532 return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
3533}
3534
3535
3536/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003537 * AppendMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003538 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003539BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
3540 UINT id, LPCSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003541{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003542 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003543}
3544
3545
3546/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003547 * AppendMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003548 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003549BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
3550 UINT id, LPCWSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003551{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003552 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003553}
3554
3555
3556/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003557 * RemoveMenu (USER.412)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003558 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003559BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003560{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003561 return RemoveMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003562}
3563
3564
3565/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003566 * RemoveMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003567 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003568BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003569{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003570 LPPOPUPMENU menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003571 MENUITEM *item;
3572
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003573 TRACE("(menu=%04x pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003574 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003575 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003576
3577 /* Remove item */
3578
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003579 MENU_FreeItemData( item );
3580
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003581 if (--menu->nItems == 0)
3582 {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00003583 HeapFree( GetProcessHeap(), 0, menu->items );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003584 menu->items = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003585 }
3586 else
3587 {
3588 while(nPos < menu->nItems)
3589 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003590 *item = *(item+1);
3591 item++;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003592 nPos++;
3593 }
Alexandre Julliardda2892c2001-02-23 01:13:42 +00003594 menu->items = HeapReAlloc( GetProcessHeap(), 0, menu->items,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003595 menu->nItems * sizeof(MENUITEM) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003596 }
3597 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003598}
3599
3600
3601/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003602 * DeleteMenu (USER.413)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003603 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003604BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003605{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003606 return DeleteMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003607}
3608
3609
3610/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003611 * DeleteMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003613BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003614{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003615 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
3616 if (!item) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003617 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003618 /* nPos is now the position of the item */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003619 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003620 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003621}
3622
3623
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003624/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003625 * ModifyMenu (USER.414)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003626 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003627BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3628 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003629{
3630 if (IS_STRING_ITEM(flags))
Alexandre Julliard982a2232000-12-13 20:20:09 +00003631 return ModifyMenuA( hMenu, pos, flags, id, MapSL(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003632 return ModifyMenuA( hMenu, pos, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003633}
3634
3635
3636/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003637 * ModifyMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003638 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003639BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
3640 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003641{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003642 MENUITEM *item;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003643
3644 if (IS_STRING_ITEM(flags))
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003645 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003646 TRACE("%04x %d %04x %04x %s\n",
3647 hMenu, pos, flags, id, debugstr_w(str) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003648 if (!str) return FALSE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003649 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003650 else
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003651 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003652 TRACE("%04x %d %04x %04x %08lx\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003653 hMenu, pos, flags, id, (DWORD)str );
3654 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003655
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003656 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003657 return MENU_SetItemData( item, flags, id, str );
3658}
3659
3660
3661/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003662 * ModifyMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003663 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003664BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
3665 UINT id, LPCSTR str )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003666{
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00003667 BOOL ret = FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003668
3669 if (IS_STRING_ITEM(flags) && str)
3670 {
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00003671 INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
3672 LPWSTR newstr = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3673 if (newstr)
3674 {
3675 MultiByteToWideChar( CP_ACP, 0, str, -1, newstr, len );
3676 ret = ModifyMenuW( hMenu, pos, flags, id, newstr );
3677 HeapFree( GetProcessHeap(), 0, newstr );
3678 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003679 return ret;
3680 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003681 else return ModifyMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003682}
3683
3684
3685/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003686 * CreatePopupMenu (USER.415)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003687 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003688HMENU16 WINAPI CreatePopupMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003689{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003690 return CreatePopupMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003691}
3692
3693
3694/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003695 * CreatePopupMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003696 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003697HMENU WINAPI CreatePopupMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003698{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003699 HMENU hmenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003700 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003701
Alexandre Julliarda3960291999-02-26 11:11:13 +00003702 if (!(hmenu = CreateMenu())) return 0;
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003703 menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003704 menu->wFlags |= MF_POPUP;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003705 menu->bTimeToHide = FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003706 return hmenu;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003707}
3708
3709
3710/**********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003711 * GetMenuCheckMarkDimensions (USER.417)
3712 * GetMenuCheckMarkDimensions (USER32.@)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003713 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003714DWORD WINAPI GetMenuCheckMarkDimensions(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003715{
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00003716 return MAKELONG( GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK) );
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003717}
3718
3719
3720/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003721 * SetMenuItemBitmaps (USER.418)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003722 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003723BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
3724 HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003725{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003726 return SetMenuItemBitmaps( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003727}
3728
3729
3730/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003731 * SetMenuItemBitmaps (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003732 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003733BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
3734 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003735{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003736 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003737 TRACE("(%04x, %04x, %04x, %04x, %04x)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003738 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
3739 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003740
3741 if (!hNewCheck && !hNewUnCheck)
3742 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003743 item->fState &= ~MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003744 }
3745 else /* Install new bitmaps */
3746 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003747 item->hCheckBit = hNewCheck;
3748 item->hUnCheckBit = hNewUnCheck;
3749 item->fState |= MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003750 }
3751 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003752}
3753
3754
3755/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003756 * CreateMenu (USER.151)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003757 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003758HMENU16 WINAPI CreateMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003759{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003760 return CreateMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003761}
3762
3763
3764/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003765 * CreateMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003766 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003767HMENU WINAPI CreateMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003768{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003769 HMENU hMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003770 LPPOPUPMENU menu;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003771 if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003772 menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00003773
3774 ZeroMemory(menu, sizeof(POPUPMENU));
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003775 menu->wMagic = MENU_MAGIC;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003776 menu->FocusedItem = NO_SELECTED_ITEM;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003777 menu->bTimeToHide = FALSE;
Juergen Schmied78513941999-04-18 14:40:32 +00003778
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003779 TRACE("return %04x\n", hMenu );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003780
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003781 return hMenu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003782}
3783
3784
3785/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003786 * DestroyMenu (USER.152)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003787 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003788BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003789{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003790 return DestroyMenu( hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003791}
3792
3793
3794/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003795 * DestroyMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003796 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003797BOOL WINAPI DestroyMenu( HMENU hMenu )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003798{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003799 TRACE("(%04x)\n", hMenu);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003800
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003801 /* Silently ignore attempts to destroy default system popup */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003802
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003803 if (hMenu && hMenu != MENU_DefSysPopup)
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003804 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003805 LPPOPUPMENU lppop = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003806
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003807 if (!lppop) return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003808
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003809 lppop->wMagic = 0; /* Mark it as destroyed */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003810
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003811 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd)
Gerard Patel8f79fdc2001-05-14 19:20:13 +00003812 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003813 DestroyWindow( lppop->hWnd );
Gerard Patel8f79fdc2001-05-14 19:20:13 +00003814 lppop->hWnd = 0;
3815 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003816
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003817 if (lppop->items) /* recursively destroy submenus */
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003818 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003819 int i;
3820 MENUITEM *item = lppop->items;
3821 for (i = lppop->nItems; i > 0; i--, item++)
3822 {
3823 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
3824 MENU_FreeItemData( item );
3825 }
3826 HeapFree( GetProcessHeap(), 0, lppop->items );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003827 }
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003828 USER_HEAP_FREE( hMenu );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003829 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003830 return (hMenu != MENU_DefSysPopup);
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003831}
3832
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003833
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003834/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003835 * GetSystemMenu (USER.156)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003836 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003837HMENU16 WINAPI GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003838{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003839 return GetSystemMenu( hWnd, bRevert );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003840}
3841
3842
3843/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003844 * GetSystemMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003845 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003846HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003847{
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003848 WND *wndPtr = WIN_FindWndPtr( hWnd );
Eric Pouech562309a1999-08-21 12:59:44 +00003849 HMENU retvalue = 0;
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003850
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003851 if (wndPtr)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003852 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003853 if( wndPtr->hSysMenu )
3854 {
3855 if( bRevert )
3856 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003857 DestroyMenu(wndPtr->hSysMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003858 wndPtr->hSysMenu = 0;
3859 }
3860 else
3861 {
Gerard Patel3e629742000-01-17 22:22:16 +00003862 POPUPMENU *menu = MENU_GetMenu( wndPtr->hSysMenu );
3863 if( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003864 {
3865 if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup )
3866 menu->items[0].hSubMenu = MENU_CopySysPopup();
3867 }
3868 else
3869 {
3870 WARN("Current sys-menu (%04x) of wnd %04x is broken\n",
3871 wndPtr->hSysMenu, hWnd);
3872 wndPtr->hSysMenu = 0;
3873 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003874 }
3875 }
3876
3877 if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003878 wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003879
3880 if( wndPtr->hSysMenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003881 {
Eric Pouech562309a1999-08-21 12:59:44 +00003882 POPUPMENU *menu;
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00003883 retvalue = GetSubMenu(wndPtr->hSysMenu, 0);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003884
3885 /* Store the dummy sysmenu handle to facilitate the refresh */
3886 /* of the close button if the SC_CLOSE item change */
Gerard Patel3e629742000-01-17 22:22:16 +00003887 menu = MENU_GetMenu(retvalue);
3888 if ( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003889 menu->hSysMenuOwner = wndPtr->hSysMenu;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003890 }
3891 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003892 }
Francois Jacques20af4c32000-06-18 17:17:54 +00003893 return bRevert ? 0 : retvalue;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003894}
3895
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003896
3897/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003898 * SetSystemMenu (USER.280)
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003899 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003900BOOL16 WINAPI SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003901{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003902 return SetSystemMenu( hwnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003903}
3904
3905
3906/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003907 * SetSystemMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003908 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003909BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003910{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003911 WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003912
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003913 if (wndPtr)
3914 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003915 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003916 wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003917 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003918 return TRUE;
3919 }
3920 return FALSE;
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003921}
3922
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003923
3924/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003925 * GetMenu (USER.157)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003926 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003927HMENU16 WINAPI GetMenu16( HWND16 hWnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003928{
Richard Cohen56753621999-09-19 14:08:13 +00003929 return (HMENU16)GetMenu(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003930}
3931
3932
3933/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003934 * GetMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003935 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003936HMENU WINAPI GetMenu( HWND hWnd )
Dmitry Timoshkovfbb2c9b2000-09-09 19:38:34 +00003937{
Alexandre Julliardde424282001-08-10 22:51:42 +00003938 HMENU retvalue = (HMENU)GetWindowLongA( hWnd, GWL_ID );
3939 TRACE("for %04x returning %04x\n", hWnd, retvalue);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003940 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003941}
3942
3943
3944/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003945 * SetMenu (USER.158)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003946 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003947BOOL16 WINAPI SetMenu16( HWND16 hWnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003948{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003949 return SetMenu( hWnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003950}
3951
3952
3953/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003954 * SetMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003955 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003956BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003957{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003958 TRACE("(%04x, %04x);\n", hWnd, hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003959
Richard Cohen56753621999-09-19 14:08:13 +00003960 if (hMenu && !IsMenu(hMenu))
3961 {
Alexandre Julliardde424282001-08-10 22:51:42 +00003962 WARN("hMenu %x is not a menu handle\n", hMenu);
3963 return FALSE;
Richard Cohen56753621999-09-19 14:08:13 +00003964 }
Alexandre Julliardde424282001-08-10 22:51:42 +00003965 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_CHILD) return FALSE;
Richard Cohen56753621999-09-19 14:08:13 +00003966
Alexandre Julliardde424282001-08-10 22:51:42 +00003967 if (GetCapture() == hWnd) ReleaseCapture();
3968
3969 if (hMenu != 0)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003970 {
Alexandre Julliardde424282001-08-10 22:51:42 +00003971 LPPOPUPMENU lpmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003972
Alexandre Julliardde424282001-08-10 22:51:42 +00003973 if (!(lpmenu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003974
Alexandre Julliardde424282001-08-10 22:51:42 +00003975 lpmenu->hWnd = hWnd;
3976 lpmenu->Height = 0; /* Make sure we recalculate the size */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003977 }
Alexandre Julliardde424282001-08-10 22:51:42 +00003978 SetWindowLongA( hWnd, GWL_ID, hMenu );
3979
3980 if (IsWindowVisible(hWnd))
3981 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
3982 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
3983 return TRUE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003984}
3985
3986
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003987
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003988/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003989 * GetSubMenu (USER.159)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003990 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003991HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003992{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003993 return GetSubMenu( hMenu, nPos );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003994}
3995
3996
3997/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003998 * GetSubMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003999 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004000HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004001{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004002 MENUITEM * lpmi;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004003
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004004 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
4005 if (!(lpmi->fType & MF_POPUP)) return 0;
4006 return lpmi->hSubMenu;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004007}
4008
4009
4010/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004011 * DrawMenuBar (USER.160)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004012 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004013void WINAPI DrawMenuBar16( HWND16 hWnd )
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004014{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004015 DrawMenuBar( hWnd );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004016}
Alexandre Julliardf7207251994-07-23 07:57:48 +00004017
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004018
4019/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004020 * DrawMenuBar (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004021 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004022BOOL WINAPI DrawMenuBar( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004023{
4024 LPPOPUPMENU lppop;
Alexandre Julliardde424282001-08-10 22:51:42 +00004025 HMENU hMenu = GetMenu(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004026
Alexandre Julliardde424282001-08-10 22:51:42 +00004027 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_CHILD) return FALSE;
4028 if (!hMenu || !(lppop = MENU_GetMenu( hMenu ))) return FALSE;
4029
4030 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
4031 lppop->hwndOwner = hWnd;
4032 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4033 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4034 return TRUE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004035}
4036
Eric Pouecha862f682001-02-26 22:33:29 +00004037/***********************************************************************
4038 * DrawMenuBarTemp (USER32.@)
4039 */
4040DWORD WINAPI DrawMenuBarTemp(DWORD p1, DWORD p2)
4041{
4042 FIXME("(%08lx %08lx): stub\n", p1, p2);
4043 return 0;
4044}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004045
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004046/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00004047 * EndMenu (USER.187)
4048 * EndMenu (USER32.@)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004049 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004050void WINAPI EndMenu(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004051{
Rob Farnumb2007932000-05-23 23:34:17 +00004052 /* if we are in the menu code, and it is active */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004053 if (!fEndMenu && top_popup)
Rob Farnumb2007932000-05-23 23:34:17 +00004054 {
4055 /* terminate the menu handling code */
4056 fEndMenu = TRUE;
Alex Korobka4f1ac051999-03-28 09:37:57 +00004057
Rob Farnumb2007932000-05-23 23:34:17 +00004058 /* needs to be posted to wakeup the internal menu handler */
4059 /* which will now terminate the menu, in the event that */
4060 /* the main window was minimized, or lost focus, so we */
4061 /* don't end up with an orphaned menu */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004062 PostMessageA( top_popup, WM_CANCELMODE, 0, 0);
Rob Farnumb2007932000-05-23 23:34:17 +00004063 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004064}
4065
4066
4067/***********************************************************************
4068 * LookupMenuHandle (USER.217)
4069 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004070HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004071{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004072 HMENU hmenu32 = hmenu;
4073 UINT id32 = id;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004074 if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
4075 else return hmenu32;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004076}
4077
4078
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004079/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004080 * LoadMenu (USER.150)
Alexandre Julliard594997c1995-04-30 10:05:20 +00004081 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004082HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, LPCSTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00004083{
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004084 HRSRC16 hRsrc;
4085 HGLOBAL16 handle;
4086 HMENU16 hMenu;
Alexandre Julliard594997c1995-04-30 10:05:20 +00004087
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004088 TRACE("(%04x,%s)\n", instance, debugres_a(name) );
4089
Alexandre Julliard594997c1995-04-30 10:05:20 +00004090 if (HIWORD(name))
4091 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004092 if (name[0] == '#') name = (LPCSTR)atoi( name + 1 );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004093 }
Alexandre Julliard594997c1995-04-30 10:05:20 +00004094
4095 if (!name) return 0;
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004096
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00004097 /* check for Win32 module */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004098 if (HIWORD(instance)) return LoadMenuA( instance, name );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00004099 instance = GetExePtr( instance );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004100
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004101 if (!(hRsrc = FindResource16( instance, name, RT_MENUA ))) return 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004102 if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
4103 hMenu = LoadMenuIndirect16(LockResource16(handle));
4104 FreeResource16( handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004105 return hMenu;
4106}
4107
4108
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004109/*****************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004110 * LoadMenuA (USER32.@)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004111 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004112HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004113{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004114 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004115 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004116 return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004117}
4118
4119
4120/*****************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004121 * LoadMenuW (USER32.@)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004122 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004123HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004124{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004125 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004126 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004127 return LoadMenuIndirectW( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004128}
4129
4130
Alexandre Julliard594997c1995-04-30 10:05:20 +00004131/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004132 * LoadMenuIndirect (USER.220)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004133 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004134HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004135{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004136 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004137 WORD version, offset;
4138 LPCSTR p = (LPCSTR)template;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004139
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004140 TRACE("(%p)\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004141 version = GET_WORD(p);
4142 p += sizeof(WORD);
4143 if (version)
4144 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004145 WARN("version must be 0 for Win16\n" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004146 return 0;
4147 }
4148 offset = GET_WORD(p);
4149 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004150 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004151 if (!MENU_ParseResource( p, hMenu, FALSE ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004152 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004153 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004154 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004155 }
4156 return hMenu;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004157}
4158
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004159
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004160/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004161 * LoadMenuIndirectA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004162 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004163HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004164{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004165 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004166 WORD version, offset;
4167 LPCSTR p = (LPCSTR)template;
4168
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004169 TRACE("%p\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004170 version = GET_WORD(p);
4171 p += sizeof(WORD);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004172 switch (version)
4173 {
4174 case 0:
4175 offset = GET_WORD(p);
4176 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004177 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004178 if (!MENU_ParseResource( p, hMenu, TRUE ))
4179 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004180 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004181 return 0;
4182 }
4183 return hMenu;
4184 case 1:
4185 offset = GET_WORD(p);
4186 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004187 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004188 if (!MENUEX_ParseResource( p, hMenu))
4189 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004190 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004191 return 0;
4192 }
4193 return hMenu;
4194 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004195 ERR("version %d not supported.\n", version);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004196 return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004197 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004198}
4199
4200
4201/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004202 * LoadMenuIndirectW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004203 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004204HMENU WINAPI LoadMenuIndirectW( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004205{
4206 /* FIXME: is there anything different between A and W? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004207 return LoadMenuIndirectA( template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004208}
4209
4210
4211/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004212 * IsMenu (USER.358)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004213 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004214BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004215{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004216 return IsMenu( hmenu );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004217}
4218
4219
4220/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004221 * IsMenu (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004222 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004223BOOL WINAPI IsMenu(HMENU hmenu)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004224{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004225 LPPOPUPMENU menu = MENU_GetMenu(hmenu);
4226 return menu != NULL;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004227}
4228
Alexandre Julliard641ee761997-08-04 16:34:36 +00004229/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004230 * GetMenuItemInfo_common
Alexandre Julliard641ee761997-08-04 16:34:36 +00004231 */
4232
Juergen Schmied78513941999-04-18 14:40:32 +00004233static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004234 LPMENUITEMINFOW lpmii, BOOL unicode)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004235{
Juergen Schmied78513941999-04-18 14:40:32 +00004236 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
4237
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004238 debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
Juergen Schmied78513941999-04-18 14:40:32 +00004239
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004240 if (!menu)
4241 return FALSE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004242
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004243 if (lpmii->fMask & MIIM_TYPE) {
4244 lpmii->fType = menu->fType;
4245 switch (MENU_ITEM_TYPE(menu->fType)) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004246 case MF_STRING:
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00004247 break; /* will be done below */
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004248 case MF_OWNERDRAW:
4249 case MF_BITMAP:
4250 lpmii->dwTypeData = menu->text;
4251 /* fall through */
4252 default:
4253 lpmii->cch = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004254 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004255 }
Juergen Schmied78513941999-04-18 14:40:32 +00004256
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00004257 /* copy the text string */
4258 if ((lpmii->fMask & (MIIM_TYPE|MIIM_STRING)) &&
4259 (MENU_ITEM_TYPE(menu->fType) == MF_STRING) && menu->text)
4260 {
4261 int len;
4262 if (unicode)
4263 {
4264 len = strlenW(menu->text);
4265 if(lpmii->dwTypeData && lpmii->cch)
4266 lstrcpynW(lpmii->dwTypeData, menu->text, lpmii->cch);
4267 }
4268 else
4269 {
4270 len = WideCharToMultiByte( CP_ACP, 0, menu->text, -1, NULL, 0, NULL, NULL );
4271 if(lpmii->dwTypeData && lpmii->cch)
4272 if (!WideCharToMultiByte( CP_ACP, 0, menu->text, -1,
4273 (LPSTR)lpmii->dwTypeData, lpmii->cch, NULL, NULL ))
4274 ((LPSTR)lpmii->dwTypeData)[lpmii->cch-1] = 0;
4275 }
4276 /* if we've copied a substring we return its length */
4277 if(lpmii->dwTypeData && lpmii->cch)
4278 {
4279 if (lpmii->cch <= len) lpmii->cch--;
4280 }
4281 else /* return length of string */
4282 lpmii->cch = len;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004283 }
Juergen Schmied78513941999-04-18 14:40:32 +00004284
4285 if (lpmii->fMask & MIIM_FTYPE)
4286 lpmii->fType = menu->fType;
4287
4288 if (lpmii->fMask & MIIM_BITMAP)
4289 lpmii->hbmpItem = menu->hbmpItem;
4290
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004291 if (lpmii->fMask & MIIM_STATE)
4292 lpmii->fState = menu->fState;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004293
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004294 if (lpmii->fMask & MIIM_ID)
4295 lpmii->wID = menu->wID;
4296
4297 if (lpmii->fMask & MIIM_SUBMENU)
4298 lpmii->hSubMenu = menu->hSubMenu;
4299
4300 if (lpmii->fMask & MIIM_CHECKMARKS) {
4301 lpmii->hbmpChecked = menu->hCheckBit;
4302 lpmii->hbmpUnchecked = menu->hUnCheckBit;
4303 }
4304 if (lpmii->fMask & MIIM_DATA)
4305 lpmii->dwItemData = menu->dwItemData;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004306
4307 return TRUE;
4308}
4309
4310/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004311 * GetMenuItemInfoA (USER32.@)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004312 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004313BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
4314 LPMENUITEMINFOA lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004315{
Aric Stewartc946b1c2000-10-24 21:28:19 +00004316 return GetMenuItemInfo_common (hmenu, item, bypos,
4317 (LPMENUITEMINFOW)lpmii, FALSE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004318}
4319
4320/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004321 * GetMenuItemInfoW (USER32.@)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004322 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004323BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
4324 LPMENUITEMINFOW lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004325{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004326 return GetMenuItemInfo_common (hmenu, item, bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004327 lpmii, TRUE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004328}
4329
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00004330
4331/* set a menu item text from a ASCII or Unicode string */
4332inline static void set_menu_item_text( MENUITEM *menu, LPCWSTR text, BOOL unicode )
4333{
4334 if (!text)
4335 {
4336 menu->text = NULL;
4337 menu->fType |= MF_SEPARATOR;
4338 }
4339 else if (unicode)
4340 {
4341 if ((menu->text = HeapAlloc( GetProcessHeap(), 0, (strlenW(text)+1) * sizeof(WCHAR) )))
4342 strcpyW( menu->text, text );
4343 }
4344 else
4345 {
4346 LPCSTR str = (LPCSTR)text;
4347 int len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
4348 if ((menu->text = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
4349 MultiByteToWideChar( CP_ACP, 0, str, -1, menu->text, len );
4350 }
4351}
4352
4353
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004354/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004355 * SetMenuItemInfo_common
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004356 */
4357
Alexandre Julliarda3960291999-02-26 11:11:13 +00004358static BOOL SetMenuItemInfo_common(MENUITEM * menu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004359 const MENUITEMINFOW *lpmii,
Alexandre Julliarda3960291999-02-26 11:11:13 +00004360 BOOL unicode)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004361{
4362 if (!menu) return FALSE;
4363
Gerard Patel2482ef32001-03-19 19:16:21 +00004364 debug_print_menuitem("MENU_SetItemInfo_common from: ", menu, "");
4365
Juergen Schmied78513941999-04-18 14:40:32 +00004366 if (lpmii->fMask & MIIM_TYPE ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004367 /* Get rid of old string. */
Juergen Schmied78513941999-04-18 14:40:32 +00004368 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004369 HeapFree(GetProcessHeap(), 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004370 menu->text = NULL;
4371 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004372
Juergen Schmied78513941999-04-18 14:40:32 +00004373 /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
4374 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4375 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Paul Millar39da2221999-04-11 12:08:42 +00004376
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004377 menu->text = lpmii->dwTypeData;
Juergen Schmied78513941999-04-18 14:40:32 +00004378
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00004379 if (IS_STRING_ITEM(menu->fType))
4380 set_menu_item_text( menu, lpmii->dwTypeData, unicode );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004381 }
Juergen Schmied78513941999-04-18 14:40:32 +00004382
4383 if (lpmii->fMask & MIIM_FTYPE ) {
4384 /* free the string when the type is changing */
4385 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004386 HeapFree(GetProcessHeap(), 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004387 menu->text = NULL;
4388 }
4389 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4390 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Gerard Patel2482ef32001-03-19 19:16:21 +00004391 if ( IS_STRING_ITEM(menu->fType) && !menu->text )
4392 menu->fType |= MF_SEPARATOR;
Juergen Schmied78513941999-04-18 14:40:32 +00004393 }
4394
4395 if (lpmii->fMask & MIIM_STRING ) {
4396 /* free the string when used */
4397 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004398 HeapFree(GetProcessHeap(), 0, menu->text);
Alexandre Julliardef06b4a2001-07-22 23:08:10 +00004399 set_menu_item_text( menu, lpmii->dwTypeData, unicode );
Juergen Schmied78513941999-04-18 14:40:32 +00004400 }
4401 }
4402
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004403 if (lpmii->fMask & MIIM_STATE)
Juergen Schmied466a6521999-05-02 11:21:08 +00004404 {
4405 /* fixme: MFS_DEFAULT do we have to reset the other menu items? */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004406 menu->fState = lpmii->fState;
Juergen Schmied466a6521999-05-02 11:21:08 +00004407 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004408
4409 if (lpmii->fMask & MIIM_ID)
4410 menu->wID = lpmii->wID;
4411
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004412 if (lpmii->fMask & MIIM_SUBMENU) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004413 menu->hSubMenu = lpmii->hSubMenu;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004414 if (menu->hSubMenu) {
Gerard Patel3e629742000-01-17 22:22:16 +00004415 POPUPMENU *subMenu = MENU_GetMenu((UINT16)menu->hSubMenu);
4416 if (subMenu) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004417 subMenu->wFlags |= MF_POPUP;
4418 menu->fType |= MF_POPUP;
4419 }
4420 else
4421 /* FIXME: Return an error ? */
4422 menu->fType &= ~MF_POPUP;
4423 }
4424 else
4425 menu->fType &= ~MF_POPUP;
4426 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004427
4428 if (lpmii->fMask & MIIM_CHECKMARKS)
4429 {
Susan Farleyf1d467a2000-05-12 21:59:31 +00004430 if (lpmii->fType & MFT_RADIOCHECK)
4431 menu->fType |= MFT_RADIOCHECK;
4432
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004433 menu->hCheckBit = lpmii->hbmpChecked;
4434 menu->hUnCheckBit = lpmii->hbmpUnchecked;
4435 }
4436 if (lpmii->fMask & MIIM_DATA)
4437 menu->dwItemData = lpmii->dwItemData;
4438
Gerard Patel2482ef32001-03-19 19:16:21 +00004439 debug_print_menuitem("SetMenuItemInfo_common to : ", menu, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004440 return TRUE;
4441}
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004442
4443/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004444 * SetMenuItemInfoA (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004445 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004446BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
4447 const MENUITEMINFOA *lpmii)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004448{
Marcus Meissner05aeaf12001-07-08 20:31:41 +00004449 if ((lpmii->fType & (MF_HILITE|MF_POPUP)) || (lpmii->fState)) {
4450 /* QuickTime does pass invalid data into SetMenuItemInfo.
4451 * do some of the checks Windows does.
4452 */
4453 WARN("Bad masks for type (0x%08x) or state (0x%08x)\n",
4454 lpmii->fType,lpmii->fState );
4455 return FALSE;
4456 }
4457
Alexandre Julliarda3960291999-02-26 11:11:13 +00004458 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004459 (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004460}
4461
4462/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004463 * SetMenuItemInfoW (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004464 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004465BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
4466 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004467{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004468 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004469 lpmii, TRUE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004470}
4471
4472/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004473 * SetMenuDefaultItem (USER32.@)
Juergen Schmied466a6521999-05-02 11:21:08 +00004474 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004475 */
Juergen Schmied466a6521999-05-02 11:21:08 +00004476BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004477{
Juergen Schmied466a6521999-05-02 11:21:08 +00004478 UINT i;
4479 POPUPMENU *menu;
4480 MENUITEM *item;
4481
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004482 TRACE("(0x%x,%d,%d)\n", hmenu, uItem, bypos);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004483
Gerard Patel3e629742000-01-17 22:22:16 +00004484 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004485
Juergen Schmied466a6521999-05-02 11:21:08 +00004486 /* reset all default-item flags */
4487 item = menu->items;
4488 for (i = 0; i < menu->nItems; i++, item++)
4489 {
4490 item->fState &= ~MFS_DEFAULT;
4491 }
4492
4493 /* no default item */
4494 if ( -1 == uItem)
4495 {
4496 return TRUE;
4497 }
Alexandre Julliarda845b881998-06-01 10:44:35 +00004498
Juergen Schmied466a6521999-05-02 11:21:08 +00004499 item = menu->items;
4500 if ( bypos )
4501 {
4502 if ( uItem >= menu->nItems ) return FALSE;
4503 item[uItem].fState |= MFS_DEFAULT;
4504 return TRUE;
4505 }
4506 else
4507 {
4508 for (i = 0; i < menu->nItems; i++, item++)
4509 {
4510 if (item->wID == uItem)
4511 {
4512 item->fState |= MFS_DEFAULT;
4513 return TRUE;
4514 }
4515 }
4516
4517 }
4518 return FALSE;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004519}
4520
Alexandre Julliarda845b881998-06-01 10:44:35 +00004521/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004522 * GetMenuDefaultItem (USER32.@)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004523 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004524UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004525{
Juergen Schmied466a6521999-05-02 11:21:08 +00004526 POPUPMENU *menu;
4527 MENUITEM * item;
4528 UINT i = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004529
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004530 TRACE("(0x%x,%d,%d)\n", hmenu, bypos, flags);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004531
Gerard Patel3e629742000-01-17 22:22:16 +00004532 if (!(menu = MENU_GetMenu(hmenu))) return -1;
Juergen Schmied466a6521999-05-02 11:21:08 +00004533
4534 /* find default item */
4535 item = menu->items;
Juergen Schmied49251861999-05-13 18:42:03 +00004536
4537 /* empty menu */
4538 if (! item) return -1;
4539
Juergen Schmied466a6521999-05-02 11:21:08 +00004540 while ( !( item->fState & MFS_DEFAULT ) )
4541 {
4542 i++; item++;
4543 if (i >= menu->nItems ) return -1;
4544 }
4545
4546 /* default: don't return disabled items */
4547 if ( (!(GMDI_USEDISABLED & flags)) && (item->fState & MFS_DISABLED )) return -1;
4548
4549 /* search rekursiv when needed */
4550 if ( (item->fType & MF_POPUP) && (flags & GMDI_GOINTOPOPUPS) )
4551 {
4552 UINT ret;
4553 ret = GetMenuDefaultItem( item->hSubMenu, bypos, flags );
4554 if ( -1 != ret ) return ret;
4555
4556 /* when item not found in submenu, return the popup item */
4557 }
4558 return ( bypos ) ? i : item->wID;
4559
Alexandre Julliarda845b881998-06-01 10:44:35 +00004560}
4561
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004562/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004563 * InsertMenuItem (USER.441)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004564 *
4565 * FIXME: untested
4566 */
4567BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
4568 const MENUITEMINFO16 *mii )
4569{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004570 MENUITEMINFOA miia;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004571
4572 miia.cbSize = sizeof(miia);
4573 miia.fMask = mii->fMask;
Alexandre Julliard982a2232000-12-13 20:20:09 +00004574 miia.dwTypeData = (LPSTR)mii->dwTypeData;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004575 miia.fType = mii->fType;
4576 miia.fState = mii->fState;
4577 miia.wID = mii->wID;
4578 miia.hSubMenu = mii->hSubMenu;
4579 miia.hbmpChecked = mii->hbmpChecked;
4580 miia.hbmpUnchecked = mii->hbmpUnchecked;
4581 miia.dwItemData = mii->dwItemData;
4582 miia.cch = mii->cch;
4583 if (IS_STRING_ITEM(miia.fType))
Alexandre Julliard982a2232000-12-13 20:20:09 +00004584 miia.dwTypeData = MapSL(mii->dwTypeData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004585 return InsertMenuItemA( hmenu, pos, byposition, &miia );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004586}
4587
4588
4589/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004590 * InsertMenuItemA (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004591 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004592BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
4593 const MENUITEMINFOA *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004594{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004595 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004596 return SetMenuItemInfo_common(item, (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004597}
4598
4599
4600/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004601 * InsertMenuItemW (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004602 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004603BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
4604 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004605{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004606 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004607 return SetMenuItemInfo_common(item, lpmii, TRUE);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004608}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004609
4610/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004611 * CheckMenuRadioItem (USER32.@)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004612 */
4613
Alexandre Julliarda3960291999-02-26 11:11:13 +00004614BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
4615 UINT first, UINT last, UINT check,
4616 UINT bypos)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004617{
4618 MENUITEM *mifirst, *milast, *micheck;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004619 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004620
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004621 TRACE("ox%x: %d-%d, check %d, bypos=%d\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004622 hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004623
4624 mifirst = MENU_FindItem (&mfirst, &first, bypos);
4625 milast = MENU_FindItem (&mlast, &last, bypos);
4626 micheck = MENU_FindItem (&mcheck, &check, bypos);
4627
4628 if (mifirst == NULL || milast == NULL || micheck == NULL ||
4629 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
4630 micheck > milast || micheck < mifirst)
4631 return FALSE;
4632
4633 while (mifirst <= milast)
4634 {
4635 if (mifirst == micheck)
4636 {
4637 mifirst->fType |= MFT_RADIOCHECK;
4638 mifirst->fState |= MFS_CHECKED;
4639 } else {
4640 mifirst->fType &= ~MFT_RADIOCHECK;
4641 mifirst->fState &= ~MFS_CHECKED;
4642 }
4643 mifirst++;
4644 }
4645
4646 return TRUE;
4647}
4648
4649/**********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00004650 * CheckMenuRadioItem (USER.666)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004651 */
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004652BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu,
4653 UINT16 first, UINT16 last, UINT16 check,
4654 BOOL16 bypos)
4655{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004656 return CheckMenuRadioItem (hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004657}
4658
4659/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004660 * GetMenuItemRect (USER32.@)
Pascal Lessard47274231999-02-13 12:21:46 +00004661 *
4662 * ATTENTION: Here, the returned values in rect are the screen
4663 * coordinates of the item just like if the menu was
4664 * always on the upper left side of the application.
4665 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004666 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004667BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
4668 LPRECT rect)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004669{
Pascal Lessard47274231999-02-13 12:21:46 +00004670 POPUPMENU *itemMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004671 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004672 HWND referenceHwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004673
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004674 TRACE("(0x%x,0x%x,%d,%p)\n", hwnd, hMenu, uItem, rect);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004675
4676 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
Pascal Lessard47274231999-02-13 12:21:46 +00004677 referenceHwnd = hwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004678
Pascal Lessard47274231999-02-13 12:21:46 +00004679 if(!hwnd)
4680 {
Gerard Patel3e629742000-01-17 22:22:16 +00004681 itemMenu = MENU_GetMenu(hMenu);
Pascal Lessard47274231999-02-13 12:21:46 +00004682 if (itemMenu == NULL)
4683 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004684
Marcus Meissnerac593bb1999-03-17 15:18:28 +00004685 if(itemMenu->hWnd == 0)
Pascal Lessard47274231999-02-13 12:21:46 +00004686 return FALSE;
4687 referenceHwnd = itemMenu->hWnd;
4688 }
4689
4690 if ((rect == NULL) || (item == NULL))
4691 return FALSE;
4692
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004693 *rect = item->rect;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004694
Alexandre Julliarda3960291999-02-26 11:11:13 +00004695 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
Pascal Lessard47274231999-02-13 12:21:46 +00004696
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004697 return TRUE;
4698}
4699
4700/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004701 * GetMenuItemRect (USER.665)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004702 */
4703
4704BOOL16 WINAPI GetMenuItemRect16 (HWND16 hwnd, HMENU16 hMenu, UINT16 uItem,
4705 LPRECT16 rect)
4706{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004707 RECT r32;
4708 BOOL res;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004709
4710 if (!rect) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004711 res = GetMenuItemRect (hwnd, hMenu, uItem, &r32);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004712 CONV_RECT32TO16 (&r32, rect);
4713 return res;
4714}
Paul Quinn1beaae51998-12-15 15:38:36 +00004715
4716/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004717 * SetMenuInfo (USER32.@)
Juergen Schmied78513941999-04-18 14:40:32 +00004718 *
4719 * FIXME
4720 * MIM_APPLYTOSUBMENUS
4721 * actually use the items to draw the menu
4722 */
4723BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
4724{
4725 POPUPMENU *menu;
4726
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004727 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004728
Gerard Patel3e629742000-01-17 22:22:16 +00004729 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004730 {
4731
4732 if (lpmi->fMask & MIM_BACKGROUND)
4733 menu->hbrBack = lpmi->hbrBack;
4734
4735 if (lpmi->fMask & MIM_HELPID)
4736 menu->dwContextHelpID = lpmi->dwContextHelpID;
4737
4738 if (lpmi->fMask & MIM_MAXHEIGHT)
4739 menu->cyMax = lpmi->cyMax;
4740
4741 if (lpmi->fMask & MIM_MENUDATA)
4742 menu->dwMenuData = lpmi->dwMenuData;
4743
4744 if (lpmi->fMask & MIM_STYLE)
4745 menu->dwStyle = lpmi->dwStyle;
4746
4747 return TRUE;
4748 }
4749 return FALSE;
4750}
4751
4752/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004753 * GetMenuInfo (USER32.@)
Juergen Schmied78513941999-04-18 14:40:32 +00004754 *
4755 * NOTES
4756 * win98/NT5.0
4757 *
4758 */
4759BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
4760{ POPUPMENU *menu;
4761
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004762 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004763
Gerard Patel3e629742000-01-17 22:22:16 +00004764 if (lpmi && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004765 {
4766
4767 if (lpmi->fMask & MIM_BACKGROUND)
4768 lpmi->hbrBack = menu->hbrBack;
4769
4770 if (lpmi->fMask & MIM_HELPID)
4771 lpmi->dwContextHelpID = menu->dwContextHelpID;
4772
4773 if (lpmi->fMask & MIM_MAXHEIGHT)
4774 lpmi->cyMax = menu->cyMax;
4775
4776 if (lpmi->fMask & MIM_MENUDATA)
4777 lpmi->dwMenuData = menu->dwMenuData;
4778
4779 if (lpmi->fMask & MIM_STYLE)
4780 lpmi->dwStyle = menu->dwStyle;
4781
4782 return TRUE;
4783 }
4784 return FALSE;
4785}
4786
4787/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004788 * SetMenuContextHelpId (USER.384)
Paul Quinn1beaae51998-12-15 15:38:36 +00004789 */
Juergen Schmied78513941999-04-18 14:40:32 +00004790BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004791{
Juergen Schmied78513941999-04-18 14:40:32 +00004792 return SetMenuContextHelpId( hMenu, dwContextHelpID );
Paul Quinn1beaae51998-12-15 15:38:36 +00004793}
4794
4795
4796/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004797 * SetMenuContextHelpId (USER32.@)
Paul Quinn1beaae51998-12-15 15:38:36 +00004798 */
Juergen Schmied78513941999-04-18 14:40:32 +00004799BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004800{
Juergen Schmied78513941999-04-18 14:40:32 +00004801 LPPOPUPMENU menu;
4802
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004803 TRACE("(0x%04x 0x%08lx)\n", hMenu, dwContextHelpID);
Juergen Schmied78513941999-04-18 14:40:32 +00004804
Gerard Patel3e629742000-01-17 22:22:16 +00004805 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004806 {
4807 menu->dwContextHelpID = dwContextHelpID;
4808 return TRUE;
4809 }
4810 return FALSE;
Paul Quinn1beaae51998-12-15 15:38:36 +00004811}
4812
4813/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004814 * GetMenuContextHelpId (USER.385)
Paul Quinn1beaae51998-12-15 15:38:36 +00004815 */
4816DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
4817{
Juergen Schmied78513941999-04-18 14:40:32 +00004818 return GetMenuContextHelpId( hMenu );
Paul Quinn1beaae51998-12-15 15:38:36 +00004819}
4820
4821/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004822 * GetMenuContextHelpId (USER32.@)
Paul Quinn1beaae51998-12-15 15:38:36 +00004823 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004824DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
Paul Quinn1beaae51998-12-15 15:38:36 +00004825{
Juergen Schmied78513941999-04-18 14:40:32 +00004826 LPPOPUPMENU menu;
4827
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004828 TRACE("(0x%04x)\n", hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00004829
Gerard Patel3e629742000-01-17 22:22:16 +00004830 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004831 {
4832 return menu->dwContextHelpID;
4833 }
4834 return 0;
Paul Quinn1beaae51998-12-15 15:38:36 +00004835}
Eric Pouech0c62bf01999-09-13 15:11:35 +00004836
4837/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004838 * MenuItemFromPoint (USER32.@)
Eric Pouech0c62bf01999-09-13 15:11:35 +00004839 */
4840UINT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
4841{
4842 FIXME("(0x%04x,0x%04x,(%ld,%ld)):stub\n",
4843 hWnd, hMenu, ptScreen.x, ptScreen.y);
4844 return 0;
4845}
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004846
4847
4848/**********************************************************************
4849 * translate_accelerator
4850 */
4851static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
4852 BYTE fVirt, WORD key, WORD cmd )
4853{
4854 UINT mesg = 0;
4855
4856 if (wParam != key) return FALSE;
4857
4858 if (message == WM_CHAR)
4859 {
4860 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
4861 {
4862 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", wParam & 0xff);
4863 goto found;
4864 }
4865 }
4866 else
4867 {
4868 if(fVirt & FVIRTKEY)
4869 {
4870 INT mask = 0;
4871 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
4872 wParam, 0xff & HIWORD(lParam));
4873 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
4874 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
4875 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
4876 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
4877 TRACE_(accel)(", but incorrect SHIFT/CTRL/ALT-state\n");
4878 }
4879 else
4880 {
4881 if (!(lParam & 0x01000000)) /* no special_key */
4882 {
4883 if ((fVirt & FALT) && (lParam & 0x20000000))
4884 { /* ^^ ALT pressed */
4885 TRACE_(accel)("found accel for Alt-%c\n", wParam & 0xff);
4886 goto found;
4887 }
4888 }
4889 }
4890 }
4891 return FALSE;
4892
4893 found:
4894 if (message == WM_KEYUP || message == WM_SYSKEYUP)
4895 mesg = 1;
4896 else if (GetCapture())
4897 mesg = 2;
4898 else if (!IsWindowEnabled(hWnd))
4899 mesg = 3;
4900 else
4901 {
4902 HMENU hMenu, hSubMenu, hSysMenu;
4903 UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004904
Alexandre Julliardde424282001-08-10 22:51:42 +00004905 hMenu = (GetWindowLongA( hWnd, GWL_STYLE ) & WS_CHILD) ? 0 : GetMenu(hWnd);
4906 hSysMenu = get_win_sys_menu( hWnd );
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004907
4908 /* find menu item and ask application to initialize it */
4909 /* 1. in the system menu */
4910 hSubMenu = hSysMenu;
4911 nPos = cmd;
4912 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
4913 {
4914 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L);
4915 if(hSubMenu != hSysMenu)
4916 {
4917 nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu);
4918 TRACE_(accel)("hSysMenu = %04x, hSubMenu = %04x, nPos = %d\n", hSysMenu, hSubMenu, nPos);
4919 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
4920 }
4921 uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
4922 }
4923 else /* 2. in the window's menu */
4924 {
4925 hSubMenu = hMenu;
4926 nPos = cmd;
4927 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
4928 {
4929 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L);
4930 if(hSubMenu != hMenu)
4931 {
4932 nPos = MENU_FindSubMenu(&hMenu, hSubMenu);
4933 TRACE_(accel)("hMenu = %04x, hSubMenu = %04x, nPos = %d\n", hMenu, hSubMenu, nPos);
4934 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
4935 }
4936 uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
4937 }
4938 }
4939
4940 if (uSysStat != (UINT)-1)
4941 {
4942 if (uSysStat & (MF_DISABLED|MF_GRAYED))
4943 mesg=4;
4944 else
4945 mesg=WM_SYSCOMMAND;
4946 }
4947 else
4948 {
4949 if (uStat != (UINT)-1)
4950 {
4951 if (IsIconic(hWnd))
4952 mesg=5;
4953 else
4954 {
4955 if (uStat & (MF_DISABLED|MF_GRAYED))
4956 mesg=6;
4957 else
4958 mesg=WM_COMMAND;
4959 }
4960 }
4961 else
4962 mesg=WM_COMMAND;
4963 }
4964 }
4965
4966 if( mesg==WM_COMMAND )
4967 {
4968 TRACE_(accel)(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
4969 SendMessageA(hWnd, mesg, 0x10000 | cmd, 0L);
4970 }
4971 else if( mesg==WM_SYSCOMMAND )
4972 {
4973 TRACE_(accel)(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
4974 SendMessageA(hWnd, mesg, cmd, 0x00010000L);
4975 }
4976 else
4977 {
4978 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
4979 * #0: unknown (please report!)
4980 * #1: for WM_KEYUP,WM_SYSKEYUP
4981 * #2: mouse is captured
4982 * #3: window is disabled
4983 * #4: it's a disabled system menu option
4984 * #5: it's a menu option, but window is iconic
4985 * #6: it's a menu option, but disabled
4986 */
4987 TRACE_(accel)(", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
4988 if(mesg==0)
4989 ERR_(accel)(" unknown reason - please report!");
4990 }
4991 return TRUE;
4992}
4993
4994/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004995 * TranslateAccelerator (USER32.@)
Patrik Stridvall17fd4e32001-06-28 18:04:41 +00004996 * TranslateAcceleratorA (USER32.@)
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004997 * TranslateAcceleratorW (USER32.@)
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004998 */
4999INT WINAPI TranslateAccelerator( HWND hWnd, HACCEL hAccel, LPMSG msg )
5000{
5001 /* YES, Accel16! */
5002 LPACCEL16 lpAccelTbl;
5003 int i;
5004
5005 if (msg == NULL)
5006 {
5007 WARN_(accel)("msg null; should hang here to be win compatible\n");
5008 return 0;
5009 }
5010 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5011 {
5012 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5013 return 0;
5014 }
5015 if ((msg->message != WM_KEYDOWN &&
5016 msg->message != WM_KEYUP &&
5017 msg->message != WM_SYSKEYDOWN &&
5018 msg->message != WM_SYSKEYUP &&
5019 msg->message != WM_CHAR)) return 0;
5020
5021 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5022 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
5023 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5024
5025 i = 0;
5026 do
5027 {
5028 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5029 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd))
5030 return 1;
5031 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5032 WARN_(accel)("couldn't translate accelerator key\n");
5033 return 0;
5034}
5035
5036
5037/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00005038 * TranslateAccelerator (USER.178)
Dmitry Timoshkovef559322000-10-26 21:47:20 +00005039 */
5040INT16 WINAPI TranslateAccelerator16( HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg )
5041{
5042 LPACCEL16 lpAccelTbl;
5043 int i;
5044
5045 if (msg == NULL)
5046 {
5047 WARN_(accel)("msg null; should hang here to be win compatible\n");
5048 return 0;
5049 }
5050 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5051 {
5052 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5053 return 0;
5054 }
5055 if ((msg->message != WM_KEYDOWN &&
5056 msg->message != WM_KEYUP &&
5057 msg->message != WM_SYSKEYDOWN &&
5058 msg->message != WM_SYSKEYUP &&
5059 msg->message != WM_CHAR)) return 0;
5060
5061 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5062 "msg->hwnd=%04x, msg->message=%04x, wParam=%04x, lParam=%lx\n",
5063 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5064
5065 i = 0;
5066 do
5067 {
5068 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5069 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd ))
5070 return 1;
5071 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5072 WARN_(accel)("couldn't translate accelerator key\n");
5073 return 0;
5074}