4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994 Alexandre Julliard
6 * Copyright 1997 Morten Welinder
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.
22 #include "wine/winbase16.h"
23 #include "sysmetrics.h"
29 #include "nonclient.h"
38 /* internal popup menu window messages */
40 #define MM_SETMENUHANDLE (WM_USER + 0)
41 #define MM_GETMENUHANDLE (WM_USER + 1)
43 /* Menu item structure */
45 /* ----------- MENUITEMINFO Stuff ----------- */
46 UINT32 fType
; /* Item type. */
47 UINT32 fState
; /* Item state. */
48 UINT32 wID
; /* Item id. */
49 HMENU32 hSubMenu
; /* Pop-up menu. */
50 HBITMAP32 hCheckBit
; /* Bitmap when checked. */
51 HBITMAP32 hUnCheckBit
; /* Bitmap when unchecked. */
52 LPSTR text
; /* Item text or bitmap handle. */
53 DWORD dwItemData
; /* Application defined. */
54 /* ----------- Wine stuff ----------- */
55 RECT32 rect
; /* Item area (relative to menu window) */
56 UINT32 xTab
; /* X position of text after Tab */
59 /* Popup menu structure */
61 WORD wFlags
; /* Menu flags (MF_POPUP, MF_SYSMENU) */
62 WORD wMagic
; /* Magic number */
63 HQUEUE16 hTaskQ
; /* Task queue for this menu */
64 WORD Width
; /* Width of the whole menu */
65 WORD Height
; /* Height of the whole menu */
66 WORD nItems
; /* Number of items in the menu */
67 HWND32 hWnd
; /* Window containing the menu */
68 MENUITEM
*items
; /* Array of menu items */
69 UINT32 FocusedItem
; /* Currently focused item */
70 WORD defitem
; /* default item position. Unused (except for set/get)*/
71 } POPUPMENU
, *LPPOPUPMENU
;
73 /* internal flags for menu tracking */
75 #define TF_ENDMENU 0x0001
76 #define TF_SUSPENDPOPUP 0x0002
77 #define TF_SKIPREMOVE 0x0004
82 HMENU32 hCurrentMenu
; /* current submenu (can be equal to hTopMenu)*/
83 HMENU32 hTopMenu
; /* initial menu */
84 HWND32 hOwnerWnd
; /* where notifications are sent */
88 #define MENU_MAGIC 0x554d /* 'MU' */
89 #define IS_A_MENU(pmenu) ((pmenu) && (pmenu)->wMagic == MENU_MAGIC)
94 /* Internal MENU_TrackMenu() flags */
95 #define TPM_INTERNAL 0xF0000000
96 #define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
97 #define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
98 #define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
100 /* popup menu shade thickness */
101 #define POPUP_XSHADE 4
102 #define POPUP_YSHADE 4
104 /* Space between 2 menu bar items */
105 #define MENU_BAR_ITEMS_SPACE 12
107 /* Minimum width of a tab character */
108 #define MENU_TAB_SPACE 8
110 /* Height of a separator item */
111 #define SEPARATOR_HEIGHT 5
113 /* (other menu->FocusedItem values give the position of the focused item) */
114 #define NO_SELECTED_ITEM 0xffff
116 #define MENU_ITEM_TYPE(flags) \
117 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
119 #define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
121 #define IS_SYSTEM_MENU(menu) \
122 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
123 #define IS_SYSTEM_POPUP(menu) \
124 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
126 #define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
127 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
128 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
129 MF_POPUP | MF_SYSMENU | MF_HELP)
130 #define STATE_MASK (~TYPE_MASK)
132 /* Dimension of the menu bitmaps */
133 static WORD check_bitmap_width
= 0, check_bitmap_height
= 0;
134 static WORD arrow_bitmap_width
= 0, arrow_bitmap_height
= 0;
136 static HBITMAP32 hStdRadioCheck
= 0;
137 static HBITMAP32 hStdCheck
= 0;
138 static HBITMAP32 hStdMnArrow
= 0;
140 // Minimze/restore/close buttons to be inserted in menubar
141 static HBITMAP32 hBmpMinimize
= 0;
142 static HBITMAP32 hBmpMinimizeD
= 0;
143 static HBITMAP32 hBmpMaximize
= 0;
144 static HBITMAP32 hBmpMaximizeD
= 0;
145 static HBITMAP32 hBmpClose
= 0;
146 static HBITMAP32 hBmpCloseD
= 0;
149 static HBRUSH32 hShadeBrush
= 0;
150 static HMENU32 MENU_DefSysPopup
= 0; /* Default system menu popup */
152 /* Use global popup window because there's no way 2 menus can
153 * be tracked at the same time. */
155 static WND
* pTopPopupWnd
= 0;
156 static UINT32 uSubPWndLevel
= 0;
158 /* Flag set by EndMenu() to force an exit from menu tracking */
159 static BOOL32 fEndMenu
= FALSE
;
162 /***********************************************************************
163 * debug_print_menuitem
165 * Print a menuitem in readable form.
168 #define debug_print_menuitem(pre, mp, post) \
169 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
171 #define MENUOUT(text) \
172 dsprintf(menu, "%s%s", (count++ ? "," : ""), (text))
174 #define MENUFLAG(bit,text) \
176 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
179 static void do_debug_print_menuitem(const char *prefix
, MENUITEM
* mp
,
182 dbg_decl_str(menu
, 256);
185 UINT32 flags
= mp
->fType
;
186 int typ
= MENU_ITEM_TYPE(flags
);
187 dsprintf(menu
, "{ ID=0x%x", mp
->wID
);
188 if (flags
& MF_POPUP
)
189 dsprintf(menu
, ", Sub=0x%x", mp
->hSubMenu
);
192 dsprintf(menu
, ", Typ=");
193 if (typ
== MFT_STRING
)
195 else if (typ
== MFT_SEPARATOR
)
197 else if (typ
== MFT_OWNERDRAW
)
199 else if (typ
== MFT_BITMAP
)
205 MENUFLAG(MF_POPUP
, "pop");
206 MENUFLAG(MFT_MENUBARBREAK
, "barbrk");
207 MENUFLAG(MFT_MENUBREAK
, "brk");
208 MENUFLAG(MFT_RADIOCHECK
, "radio");
209 MENUFLAG(MFT_RIGHTORDER
, "rorder");
210 MENUFLAG(MF_SYSMENU
, "sys");
211 MENUFLAG(MFT_RIGHTJUSTIFY
, "right");
214 dsprintf(menu
, "+0x%x", flags
);
219 dsprintf(menu
, ", State=");
220 MENUFLAG(MFS_GRAYED
, "grey");
221 MENUFLAG(MFS_DISABLED
, "dis");
222 MENUFLAG(MFS_CHECKED
, "check");
223 MENUFLAG(MFS_HILITE
, "hi");
224 MENUFLAG(MF_USECHECKBITMAPS
, "usebit");
225 MENUFLAG(MF_MOUSESELECT
, "mouse");
227 dsprintf(menu
, "+0x%x", flags
);
230 dsprintf(menu
, ", Chk=0x%x", mp
->hCheckBit
);
232 dsprintf(menu
, ", Unc=0x%x", mp
->hUnCheckBit
);
234 if (typ
== MFT_STRING
) {
236 dsprintf(menu
, ", Text=\"%s\"", mp
->text
);
238 dsprintf(menu
, ", Text=Null");
239 } else if (mp
->text
== NULL
)
242 dsprintf(menu
, ", Text=%p", mp
->text
);
243 dsprintf(menu
, " }");
245 dsprintf(menu
, "NULL");
248 TRACE(menu
, "%s %s %s\n", prefix
, dbg_str(menu
), postfix
);
254 /***********************************************************************
257 * Return the default system menu.
259 static HMENU32
MENU_CopySysPopup(void)
261 HMENU32 hMenu
= LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU
));
264 POPUPMENU
* menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hMenu
);
265 menu
->wFlags
|= MF_SYSMENU
| MF_POPUP
;
269 ERR(menu
, "Unable to load default system menu\n" );
272 TRACE(menu
, "returning %x.\n", hMenu
);
278 /**********************************************************************
281 * Create a copy of the system menu. System menu in Windows is
282 * a special menu-bar with the single entry - system menu popup.
283 * This popup is presented to the outside world as a "system menu".
284 * However, the real system menu handle is sometimes seen in the
285 * WM_MENUSELECT paramemters (and Word 6 likes it this way).
287 HMENU32
MENU_GetSysMenu( HWND32 hWnd
, HMENU32 hPopupMenu
)
291 if ((hMenu
= CreateMenu32()))
293 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hMenu
);
294 menu
->wFlags
= MF_SYSMENU
;
297 if (hPopupMenu
== (HMENU32
)(-1))
298 hPopupMenu
= MENU_CopySysPopup();
299 else if( !hPopupMenu
) hPopupMenu
= MENU_DefSysPopup
;
303 InsertMenu32A( hMenu
, -1, MF_SYSMENU
| MF_POPUP
| MF_BYPOSITION
, hPopupMenu
, NULL
);
305 menu
->items
[0].fType
= MF_SYSMENU
| MF_POPUP
;
306 menu
->items
[0].fState
= 0;
307 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hPopupMenu
);
308 menu
->wFlags
|= MF_SYSMENU
;
310 TRACE(menu
,"GetSysMenu hMenu=%04x (%04x)\n", hMenu
, hPopupMenu
);
313 DestroyMenu32( hMenu
);
315 ERR(menu
, "failed to load system menu!\n");
320 /***********************************************************************
323 * Menus initialisation.
328 static unsigned char shade_bits
[16] = { 0x55, 0, 0xAA, 0,
333 /* Load menu bitmaps */
334 hStdCheck
= LoadBitmap32A(0, MAKEINTRESOURCE32A(OBM_CHECK
));
335 hStdRadioCheck
= LoadBitmap32A(0, MAKEINTRESOURCE32A(OBM_RADIOCHECK
));
336 hStdMnArrow
= LoadBitmap32A(0, MAKEINTRESOURCE32A(OBM_MNARROW
));
337 /* Load system buttons bitmaps */
338 hBmpMinimize
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_REDUCE
));
339 hBmpMinimizeD
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_REDUCED
));
340 hBmpMaximize
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_RESTORE
));
341 hBmpMaximizeD
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_RESTORED
));
342 hBmpClose
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_CLOSE
));
343 hBmpCloseD
= LoadBitmap32A(0,MAKEINTRESOURCE32A(OBM_CLOSED
));
348 GetObject32A( hStdCheck
, sizeof(bm
), &bm
);
349 check_bitmap_width
= bm
.bmWidth
;
350 check_bitmap_height
= bm
.bmHeight
;
354 /* Assume that radio checks have the same size as regular check. */
361 GetObject32A( hStdMnArrow
, sizeof(bm
), &bm
);
362 arrow_bitmap_width
= bm
.bmWidth
;
363 arrow_bitmap_height
= bm
.bmHeight
;
367 if ((hBitmap
= CreateBitmap32( 8, 8, 1, 1, shade_bits
)))
369 if((hShadeBrush
= CreatePatternBrush32( hBitmap
)))
371 DeleteObject32( hBitmap
);
372 if ((MENU_DefSysPopup
= MENU_CopySysPopup()))
380 /***********************************************************************
381 * MENU_InitSysMenuPopup
383 * Grey the appropriate items in System menu.
385 static void MENU_InitSysMenuPopup( HMENU32 hmenu
, DWORD style
, DWORD clsStyle
)
389 gray
= !(style
& WS_THICKFRAME
) || (style
& (WS_MAXIMIZE
| WS_MINIMIZE
));
390 EnableMenuItem32( hmenu
, SC_SIZE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
391 gray
= ((style
& WS_MAXIMIZE
) != 0);
392 EnableMenuItem32( hmenu
, SC_MOVE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
393 gray
= !(style
& WS_MINIMIZEBOX
) || (style
& WS_MINIMIZE
);
394 EnableMenuItem32( hmenu
, SC_MINIMIZE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
395 gray
= !(style
& WS_MAXIMIZEBOX
) || (style
& WS_MAXIMIZE
);
396 EnableMenuItem32( hmenu
, SC_MAXIMIZE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
397 gray
= !(style
& (WS_MAXIMIZE
| WS_MINIMIZE
));
398 EnableMenuItem32( hmenu
, SC_RESTORE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
399 gray
= (clsStyle
& CS_NOCLOSE
) != 0;
400 EnableMenuItem32( hmenu
, SC_CLOSE
, (gray
? MF_GRAYED
: MF_ENABLED
) );
404 /******************************************************************************
406 * UINT32 MENU_GetStartOfNextColumn(
409 *****************************************************************************/
411 static UINT32
MENU_GetStartOfNextColumn(
414 POPUPMENU
*menu
= (POPUPMENU
*)USER_HEAP_LIN_ADDR(hMenu
);
415 UINT32 i
= menu
->FocusedItem
+ 1;
418 return NO_SELECTED_ITEM
;
420 if( i
== NO_SELECTED_ITEM
)
423 for( ; i
< menu
->nItems
; ++i
) {
424 if (menu
->items
[i
].fType
& MF_MENUBARBREAK
)
428 return NO_SELECTED_ITEM
;
432 /******************************************************************************
434 * UINT32 MENU_GetStartOfPrevColumn(
437 *****************************************************************************/
439 static UINT32
MENU_GetStartOfPrevColumn(
442 POPUPMENU
const *menu
= (POPUPMENU
*)USER_HEAP_LIN_ADDR(hMenu
);
446 return NO_SELECTED_ITEM
;
448 if( menu
->FocusedItem
== 0 || menu
->FocusedItem
== NO_SELECTED_ITEM
)
449 return NO_SELECTED_ITEM
;
451 /* Find the start of the column */
453 for(i
= menu
->FocusedItem
; i
!= 0 &&
454 !(menu
->items
[i
].fType
& MF_MENUBARBREAK
);
458 return NO_SELECTED_ITEM
;
460 for(--i
; i
!= 0; --i
) {
461 if (menu
->items
[i
].fType
& MF_MENUBARBREAK
)
465 TRACE(menu
, "ret %d.\n", i
);
472 /***********************************************************************
475 * Find a menu item. Return a pointer on the item, and modifies *hmenu
476 * in case the item was in a sub-menu.
478 static MENUITEM
*MENU_FindItem( HMENU32
*hmenu
, UINT32
*nPos
, UINT32 wFlags
)
483 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(*hmenu
))) return NULL
;
484 if (wFlags
& MF_BYPOSITION
)
486 if (*nPos
>= menu
->nItems
) return NULL
;
487 return &menu
->items
[*nPos
];
491 MENUITEM
*item
= menu
->items
;
492 for (i
= 0; i
< menu
->nItems
; i
++, item
++)
494 if (item
->wID
== *nPos
)
499 else if (item
->fType
& MF_POPUP
)
501 HMENU32 hsubmenu
= item
->hSubMenu
;
502 MENUITEM
*subitem
= MENU_FindItem( &hsubmenu
, nPos
, wFlags
);
514 /***********************************************************************
517 static void MENU_FreeItemData( MENUITEM
* item
)
520 if (IS_STRING_ITEM(item
->fType
) && item
->text
)
521 HeapFree( SystemHeap
, 0, item
->text
);
524 /***********************************************************************
525 * MENU_FindItemByCoords
527 * Find the item at the specified coordinates (screen coords). Does
528 * not work for child windows and therefore should not be called for
529 * an arbitrary system menu.
531 static MENUITEM
*MENU_FindItemByCoords( POPUPMENU
*menu
,
532 POINT32 pt
, UINT32
*pos
)
538 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
))) return NULL
;
539 pt
.x
-= wndPtr
->rectWindow
.left
;
540 pt
.y
-= wndPtr
->rectWindow
.top
;
542 for (i
= 0; i
< menu
->nItems
; i
++, item
++)
544 if ((pt
.x
>= item
->rect
.left
) && (pt
.x
< item
->rect
.right
) &&
545 (pt
.y
>= item
->rect
.top
) && (pt
.y
< item
->rect
.bottom
))
555 /***********************************************************************
558 * Find the menu item selected by a key press.
559 * Return item id, -1 if none, -2 if we should close the menu.
561 static UINT32
MENU_FindItemByKey( HWND32 hwndOwner
, HMENU32 hmenu
,
562 UINT32 key
, BOOL32 forceMenuChar
)
564 TRACE(menu
,"\tlooking for '%c' in [%04x]\n", (char)key
, (UINT16
)hmenu
);
566 if (!IsMenu32( hmenu
))
568 WND
* w
= WIN_FindWndPtr(hwndOwner
);
569 hmenu
= GetSubMenu32(w
->hSysMenu
, 0);
574 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
575 MENUITEM
*item
= menu
->items
;
583 for (i
= 0; i
< menu
->nItems
; i
++, item
++)
585 if (item
->text
&& (IS_STRING_ITEM(item
->fType
)))
587 char *p
= item
->text
- 2;
590 p
= strchr (p
+ 2, '&');
592 while (p
!= NULL
&& p
[1] == '&');
593 if (p
&& (toupper(p
[1]) == key
)) return i
;
597 menuchar
= SendMessage32A( hwndOwner
, WM_MENUCHAR
,
598 MAKEWPARAM( key
, menu
->wFlags
), hmenu
);
599 if (HIWORD(menuchar
) == 2) return LOWORD(menuchar
);
600 if (HIWORD(menuchar
) == 1) return (UINT32
)(-2);
604 /***********************************************************************
607 * Load the bitmap associated with the magic menu item and its style
610 static HBITMAP32
MENU_LoadMagicItem(UINT32 id
,BOOL32 hilite
)
612 // Magic menu item id's section
613 // These magic id's are used by windows to insert "standard" mdi
614 // buttons (minimize,restore,close) on menu. Under windows,
615 // these magic id's make sure the right things appear when those
616 // bitmap buttons are pressed/selected/released.
620 case MAGIC_REDUCE
: return (hilite
? hBmpMinimizeD
: hBmpMinimize
);
621 case MAGIC_RESTORE
: return (hilite
? hBmpMaximizeD
: hBmpMaximize
);
622 case MAGIC_CLOSE
: return (hilite
? hBmpCloseD
: hBmpClose
);
628 /***********************************************************************
631 * Calculate the size of the menu item and store it in lpitem->rect.
633 static void MENU_CalcItemSize( HDC32 hdc
, MENUITEM
*lpitem
, HWND32 hwndOwner
,
634 INT32 orgX
, INT32 orgY
, BOOL32 menuBar
)
639 TRACE(menu
, "HDC 0x%x at (%d,%d)\n",
641 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem
,
642 (menuBar
? " (MenuBar)" : ""));
644 SetRect32( &lpitem
->rect
, orgX
, orgY
, orgX
, orgY
);
646 if (lpitem
->fType
& MF_OWNERDRAW
)
648 MEASUREITEMSTRUCT32 mis
;
649 mis
.CtlType
= ODT_MENU
;
650 mis
.itemID
= lpitem
->wID
;
651 mis
.itemData
= (DWORD
)lpitem
->text
;
654 SendMessage32A( hwndOwner
, WM_MEASUREITEM
, 0, (LPARAM
)&mis
);
655 lpitem
->rect
.bottom
+= mis
.itemHeight
;
656 lpitem
->rect
.right
+= mis
.itemWidth
;
657 TRACE(menu
, "%08x %dx%d\n",
658 lpitem
->wID
, mis
.itemWidth
, mis
.itemHeight
);
662 if (lpitem
->fType
& MF_SEPARATOR
)
664 lpitem
->rect
.bottom
+= SEPARATOR_HEIGHT
;
670 lpitem
->rect
.right
+= 2 * check_bitmap_width
;
671 if (lpitem
->fType
& MF_POPUP
)
672 lpitem
->rect
.right
+= arrow_bitmap_width
;
675 if (lpitem
->fType
& MF_BITMAP
)
678 HBITMAP32 resBmp
= 0;
680 // Check if there is a magic menu item associated with this item
681 if((LOWORD((int)lpitem
->text
))<6)
683 resBmp
= MENU_LoadMagicItem((int)lpitem
->text
,
684 (lpitem
->fType
& MF_HILITE
));
687 resBmp
= (HBITMAP32
)lpitem
->text
;
689 if (GetObject32A(resBmp
, sizeof(bm
), &bm
))
691 lpitem
->rect
.right
+= bm
.bmWidth
;
692 lpitem
->rect
.bottom
+= bm
.bmHeight
;
700 /* If we get here, then it must be a text item */
702 if (IS_STRING_ITEM( lpitem
->fType
))
704 dwSize
= GetTextExtent( hdc
, lpitem
->text
, strlen(lpitem
->text
) );
705 lpitem
->rect
.right
+= LOWORD(dwSize
);
706 if (TWEAK_WineLook
== WIN31_LOOK
)
707 lpitem
->rect
.bottom
+= MAX( HIWORD(dwSize
), SYSMETRICS_CYMENU
);
709 lpitem
->rect
.bottom
+= MAX (HIWORD(dwSize
), sysMetrics
[SM_CYMENU
]- 1);
712 if (menuBar
) lpitem
->rect
.right
+= MENU_BAR_ITEMS_SPACE
;
713 else if ((p
= strchr( lpitem
->text
, '\t' )) != NULL
)
715 /* Item contains a tab (only meaningful in popup menus) */
716 lpitem
->xTab
= check_bitmap_width
+ MENU_TAB_SPACE
+
717 LOWORD( GetTextExtent( hdc
, lpitem
->text
,
718 (int)(p
- lpitem
->text
) ));
719 lpitem
->rect
.right
+= MENU_TAB_SPACE
;
723 if (strchr( lpitem
->text
, '\b' ))
724 lpitem
->rect
.right
+= MENU_TAB_SPACE
;
725 lpitem
->xTab
= lpitem
->rect
.right
- check_bitmap_width
726 - arrow_bitmap_width
;
732 /***********************************************************************
733 * MENU_PopupMenuCalcSize
735 * Calculate the size of a popup menu.
737 static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop
, HWND32 hwndOwner
)
742 int orgX
, orgY
, maxX
, maxTab
, maxTabWidth
;
744 lppop
->Width
= lppop
->Height
= 0;
745 if (lppop
->nItems
== 0) return;
748 maxX
= SYSMETRICS_CXBORDER
;
749 while (start
< lppop
->nItems
)
751 lpitem
= &lppop
->items
[start
];
753 orgY
= SYSMETRICS_CYBORDER
;
755 maxTab
= maxTabWidth
= 0;
757 /* Parse items until column break or end of menu */
758 for (i
= start
; i
< lppop
->nItems
; i
++, lpitem
++)
761 (lpitem
->fType
& (MF_MENUBREAK
| MF_MENUBARBREAK
))) break;
763 if (TWEAK_WineLook
> WIN31_LOOK
)
766 MENU_CalcItemSize( hdc
, lpitem
, hwndOwner
, orgX
, orgY
, FALSE
);
768 if (lpitem
->fType
& MF_MENUBARBREAK
) orgX
++;
769 maxX
= MAX( maxX
, lpitem
->rect
.right
);
770 orgY
= lpitem
->rect
.bottom
;
771 if (IS_STRING_ITEM(lpitem
->fType
) && lpitem
->xTab
)
773 maxTab
= MAX( maxTab
, lpitem
->xTab
);
774 maxTabWidth
= MAX(maxTabWidth
,lpitem
->rect
.right
-lpitem
->xTab
);
778 /* Finish the column (set all items to the largest width found) */
779 maxX
= MAX( maxX
, maxTab
+ maxTabWidth
);
780 for (lpitem
= &lppop
->items
[start
]; start
< i
; start
++, lpitem
++)
782 lpitem
->rect
.right
= maxX
;
783 if (IS_STRING_ITEM(lpitem
->fType
) && lpitem
->xTab
)
784 lpitem
->xTab
= maxTab
;
786 lppop
->Height
= MAX( lppop
->Height
, orgY
);
789 if(TWEAK_WineLook
> WIN31_LOOK
)
793 ReleaseDC32( 0, hdc
);
797 /***********************************************************************
798 * MENU_MenuBarCalcSize
800 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
801 * height is off by 1 pixel which causes lengthy window relocations when
802 * active document window is maximized/restored.
804 * Calculate the size of the menu bar.
806 static void MENU_MenuBarCalcSize( HDC32 hdc
, LPRECT32 lprect
,
807 LPPOPUPMENU lppop
, HWND32 hwndOwner
)
810 int start
, i
, orgX
, orgY
, maxY
, helpPos
;
812 if ((lprect
== NULL
) || (lppop
== NULL
)) return;
813 if (lppop
->nItems
== 0) return;
814 TRACE(menu
,"left=%d top=%d right=%d bottom=%d\n",
815 lprect
->left
, lprect
->top
, lprect
->right
, lprect
->bottom
);
816 lppop
->Width
= lprect
->right
- lprect
->left
;
821 while (start
< lppop
->nItems
)
823 lpitem
= &lppop
->items
[start
];
827 /* Parse items until line break or end of menu */
828 for (i
= start
; i
< lppop
->nItems
; i
++, lpitem
++)
830 if ((helpPos
== -1) && (lpitem
->fType
& MF_HELP
)) helpPos
= i
;
832 (lpitem
->fType
& (MF_MENUBREAK
| MF_MENUBARBREAK
))) break;
834 TRACE(menu
, "calling MENU_CalcItemSize org=(%d, %d)\n",
836 debug_print_menuitem (" item: ", lpitem
, "");
837 MENU_CalcItemSize( hdc
, lpitem
, hwndOwner
, orgX
, orgY
, TRUE
);
839 if (lpitem
->rect
.right
> lprect
->right
)
841 if (i
!= start
) break;
842 else lpitem
->rect
.right
= lprect
->right
;
844 maxY
= MAX( maxY
, lpitem
->rect
.bottom
);
845 orgX
= lpitem
->rect
.right
;
848 /* Finish the line (set all items to the largest height found) */
849 while (start
< i
) lppop
->items
[start
++].rect
.bottom
= maxY
;
852 lprect
->bottom
= maxY
;
853 lppop
->Height
= lprect
->bottom
- lprect
->top
;
855 /* Flush right all items between the MF_HELP and the last item */
856 /* (if several lines, only move the last line) */
859 lpitem
= &lppop
->items
[lppop
->nItems
-1];
860 orgY
= lpitem
->rect
.top
;
861 orgX
= lprect
->right
;
862 for (i
= lppop
->nItems
- 1; i
>= helpPos
; i
--, lpitem
--)
864 if (lpitem
->rect
.top
!= orgY
) break; /* Other line */
865 if (lpitem
->rect
.right
>= orgX
) break; /* Too far right already */
866 lpitem
->rect
.left
+= orgX
- lpitem
->rect
.right
;
867 lpitem
->rect
.right
= orgX
;
868 orgX
= lpitem
->rect
.left
;
873 /***********************************************************************
876 * Draw a single menu item.
878 static void MENU_DrawMenuItem( HWND32 hwnd
, HDC32 hdc
, MENUITEM
*lpitem
,
879 UINT32 height
, BOOL32 menuBar
, UINT32 odaction
)
883 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem
, "");
885 if (lpitem
->fType
& MF_SYSMENU
)
887 if( !IsIconic32(hwnd
) ) {
888 if (TWEAK_WineLook
> WIN31_LOOK
)
889 NC_DrawSysButton95( hwnd
, hdc
,
891 (MF_HILITE
| MF_MOUSESELECT
) );
893 NC_DrawSysButton( hwnd
, hdc
,
895 (MF_HILITE
| MF_MOUSESELECT
) );
901 if (lpitem
->fType
& MF_OWNERDRAW
)
903 DRAWITEMSTRUCT32 dis
;
905 dis
.CtlType
= ODT_MENU
;
906 dis
.itemID
= lpitem
->wID
;
907 dis
.itemData
= (DWORD
)lpitem
->text
;
909 if (lpitem
->fState
& MF_CHECKED
) dis
.itemState
|= ODS_CHECKED
;
910 if (lpitem
->fState
& MF_GRAYED
) dis
.itemState
|= ODS_GRAYED
;
911 if (lpitem
->fState
& MF_HILITE
) dis
.itemState
|= ODS_SELECTED
;
912 dis
.itemAction
= odaction
; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
915 dis
.rcItem
= lpitem
->rect
;
916 TRACE(menu
, "Ownerdraw: itemID=%d, itemState=%d, itemAction=%d, "
917 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n",dis
.itemID
,
918 dis
.itemState
, dis
.itemAction
, dis
.hwndItem
, dis
.hDC
,
919 dis
.rcItem
.left
, dis
.rcItem
.top
, dis
.rcItem
.right
,
921 SendMessage32A( GetWindow32(hwnd
,GW_OWNER
), WM_DRAWITEM
, 0, (LPARAM
)&dis
);
925 if (menuBar
&& (lpitem
->fType
& MF_SEPARATOR
)) return;
928 /* Draw the background */
929 if (TWEAK_WineLook
> WIN31_LOOK
) {
939 InflateRect32( &rect, -1, -1 );
943 if ((lpitem
->fState
& MF_HILITE
) && !(lpitem
->fType
& MF_BITMAP
) )
944 FillRect32( hdc
, &rect
, GetSysColorBrush32(COLOR_HIGHLIGHT
) );
946 FillRect32( hdc
, &rect
, GetSysColorBrush32(COLOR_MENU
) );
948 SetBkMode32( hdc
, TRANSPARENT
);
950 /* Draw the separator bar (if any) */
952 if (!menuBar
&& (lpitem
->fType
& MF_MENUBARBREAK
))
954 /* vertical separator */
955 if (TWEAK_WineLook
> WIN31_LOOK
) {
958 rc
.bottom
= height
- 3;
959 DrawEdge32 (hdc
, &rc
, EDGE_ETCHED
, BF_LEFT
);
962 SelectObject32( hdc
, GetSysColorPen32(COLOR_WINDOWFRAME
) );
963 MoveTo( hdc
, rect
.left
, 0 );
964 LineTo32( hdc
, rect
.left
, height
);
967 if (lpitem
->fType
& MF_SEPARATOR
)
969 /* horizontal separator */
970 if (TWEAK_WineLook
> WIN31_LOOK
) {
974 rc
.top
+= SEPARATOR_HEIGHT
/ 2;
975 DrawEdge32 (hdc
, &rc
, EDGE_ETCHED
, BF_TOP
);
978 SelectObject32( hdc
, GetSysColorPen32(COLOR_WINDOWFRAME
) );
979 MoveTo( hdc
, rect
.left
, rect
.top
+ SEPARATOR_HEIGHT
/2 );
980 LineTo32( hdc
, rect
.right
, rect
.top
+ SEPARATOR_HEIGHT
/2 );
988 if ((lpitem
->fState
& MF_HILITE
) && !(lpitem
->fType
& MF_BITMAP
) )
990 if (lpitem
->fState
& MF_GRAYED
)
991 SetTextColor32( hdc
, GetSysColor32( COLOR_GRAYTEXT
) );
993 SetTextColor32( hdc
, GetSysColor32( COLOR_HIGHLIGHTTEXT
) );
994 SetBkColor32( hdc
, GetSysColor32( COLOR_HIGHLIGHT
) );
998 if (lpitem
->fState
& MF_GRAYED
)
999 SetTextColor32( hdc
, GetSysColor32( COLOR_GRAYTEXT
) );
1001 SetTextColor32( hdc
, GetSysColor32( COLOR_MENUTEXT
) );
1002 SetBkColor32( hdc
, GetSysColor32( COLOR_MENU
) );
1007 INT32 y
= rect
.top
+ rect
.bottom
;
1009 /* Draw the check mark
1012 * Custom checkmark bitmaps are monochrome but not always 1bpp.
1015 if (lpitem
->fState
& MF_CHECKED
)
1018 lpitem
->hCheckBit
? lpitem
->hCheckBit
:
1019 ((lpitem
->fType
& MFT_RADIOCHECK
)
1020 ? hStdRadioCheck
: hStdCheck
);
1021 HDC32 hdcMem
= CreateCompatibleDC32( hdc
);
1023 SelectObject32( hdcMem
, bm
);
1024 BitBlt32( hdc
, rect
.left
, (y
- check_bitmap_height
) / 2,
1025 check_bitmap_width
, check_bitmap_height
,
1026 hdcMem
, 0, 0, SRCCOPY
);
1027 DeleteDC32( hdcMem
);
1028 } else if (lpitem
->hUnCheckBit
) {
1029 HDC32 hdcMem
= CreateCompatibleDC32( hdc
);
1031 SelectObject32( hdcMem
, lpitem
->hUnCheckBit
);
1032 BitBlt32( hdc
, rect
.left
, (y
- check_bitmap_height
) / 2,
1033 check_bitmap_width
, check_bitmap_height
,
1034 hdcMem
, 0, 0, SRCCOPY
);
1035 DeleteDC32( hdcMem
);
1038 /* Draw the popup-menu arrow */
1040 if (lpitem
->fType
& MF_POPUP
)
1042 HDC32 hdcMem
= CreateCompatibleDC32( hdc
);
1044 SelectObject32( hdcMem
, hStdMnArrow
);
1045 BitBlt32( hdc
, rect
.right
- arrow_bitmap_width
- 1,
1046 (y
- arrow_bitmap_height
) / 2,
1047 arrow_bitmap_width
, arrow_bitmap_height
,
1048 hdcMem
, 0, 0, SRCCOPY
);
1049 DeleteDC32( hdcMem
);
1052 rect
.left
+= check_bitmap_width
;
1053 rect
.right
-= arrow_bitmap_width
;
1056 /* Draw the item text or bitmap */
1058 if (lpitem
->fType
& MF_BITMAP
)
1060 HBITMAP32 resBmp
= 0;
1062 HDC32 hdcMem
= CreateCompatibleDC32( hdc
);
1064 // Check if there is a magic menu item associated with this item
1065 // and load the appropriate bitmap
1066 if((LOWORD((int)lpitem
->text
)) < 6)
1068 resBmp
= MENU_LoadMagicItem((int)lpitem
->text
,
1069 (lpitem
->fState
& MF_HILITE
));
1072 resBmp
= (HBITMAP32
)lpitem
->text
;
1074 SelectObject32(hdcMem
,resBmp
);
1075 BitBlt32( hdc
, rect
.left
, rect
.top
+3, rect
.right
- rect
.left
+3,
1076 rect
.bottom
- rect
.top
, hdcMem
, 0, 0, SRCCOPY
);
1077 DeleteDC32( hdcMem
);
1082 /* No bitmap - process text if present */
1083 else if (IS_STRING_ITEM(lpitem
->fType
))
1089 rect
.left
+= MENU_BAR_ITEMS_SPACE
/ 2;
1090 rect
.right
-= MENU_BAR_ITEMS_SPACE
/ 2;
1091 i
= strlen( lpitem
->text
);
1095 for (i
= 0; lpitem
->text
[i
]; i
++)
1096 if ((lpitem
->text
[i
] == '\t') || (lpitem
->text
[i
] == '\b'))
1100 if((TWEAK_WineLook
== WIN31_LOOK
) || !(lpitem
->fState
& MF_GRAYED
)) {
1101 DrawText32A( hdc
, lpitem
->text
, i
, &rect
,
1102 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
1105 if (!(lpitem
->fState
& MF_HILITE
))
1111 SetTextColor32(hdc
, RGB(0xff, 0xff, 0xff));
1112 DrawText32A( hdc
, lpitem
->text
, i
, &rect
,
1113 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
1119 SetTextColor32(hdc
, RGB(0x80, 0x80, 0x80));
1120 DrawText32A( hdc
, lpitem
->text
, i
, &rect
,
1121 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
1124 if (lpitem
->text
[i
]) /* There's a tab or flush-right char */
1126 if (lpitem
->text
[i
] == '\t')
1128 rect
.left
= lpitem
->xTab
;
1129 DrawText32A( hdc
, lpitem
->text
+ i
+ 1, -1, &rect
,
1130 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
1132 else DrawText32A( hdc
, lpitem
->text
+ i
+ 1, -1, &rect
,
1133 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
1139 /***********************************************************************
1140 * MENU_DrawPopupMenu
1142 * Paint a popup menu.
1144 static void MENU_DrawPopupMenu( HWND32 hwnd
, HDC32 hdc
, HMENU32 hmenu
)
1146 HBRUSH32 hPrevBrush
= 0;
1149 GetClientRect32( hwnd
, &rect
);
1151 /* if(!TWEAK_Win95Look) { */
1152 rect
.bottom
-= POPUP_YSHADE
* SYSMETRICS_CYBORDER
;
1153 rect
.right
-= POPUP_XSHADE
* SYSMETRICS_CXBORDER
;
1156 if((hPrevBrush
= SelectObject32( hdc
, GetSysColorBrush32(COLOR_MENU
) )))
1160 Rectangle32( hdc
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1162 hPrevPen
= SelectObject32( hdc
, GetStockObject32( NULL_PEN
) );
1168 /* draw 3-d shade */
1169 if(TWEAK_WineLook
== WIN31_LOOK
) {
1170 SelectObject32( hdc
, hShadeBrush
);
1171 SetBkMode32( hdc
, TRANSPARENT
);
1172 ropPrev
= SetROP232( hdc
, R2_MASKPEN
);
1174 i
= rect
.right
; /* why SetBrushOrg() doesn't? */
1175 PatBlt32( hdc
, i
& 0xfffffffe,
1176 rect
.top
+ POPUP_YSHADE
*SYSMETRICS_CYBORDER
,
1177 i
%2 + POPUP_XSHADE
*SYSMETRICS_CXBORDER
,
1178 rect
.bottom
- rect
.top
, 0x00a000c9 );
1180 PatBlt32( hdc
, rect
.left
+ POPUP_XSHADE
*SYSMETRICS_CXBORDER
,
1181 i
& 0xfffffffe,rect
.right
- rect
.left
,
1182 i
%2 + POPUP_YSHADE
*SYSMETRICS_CYBORDER
, 0x00a000c9 );
1183 SelectObject32( hdc
, hPrevPen
);
1184 SelectObject32( hdc
, hPrevBrush
);
1185 SetROP232( hdc
, ropPrev
);
1188 DrawEdge32 (hdc
, &rect
, EDGE_RAISED
, BF_RECT
);
1190 /* draw menu items */
1192 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
1193 if (menu
&& menu
->nItems
)
1198 for (u
= menu
->nItems
, item
= menu
->items
; u
> 0; u
--, item
++)
1199 MENU_DrawMenuItem( hwnd
, hdc
, item
, menu
->Height
, FALSE
,
1203 } else SelectObject32( hdc
, hPrevBrush
);
1208 /***********************************************************************
1211 * Paint a menu bar. Returns the height of the menu bar.
1213 UINT32
MENU_DrawMenuBar( HDC32 hDC
, LPRECT32 lprect
, HWND32 hwnd
,
1214 BOOL32 suppress_draw
)
1218 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1220 lppop
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR( (HMENU16
)wndPtr
->wIDmenu
);
1221 if (lppop
== NULL
|| lprect
== NULL
) return SYSMETRICS_CYMENU
;
1222 TRACE(menu
,"(%04x, %p, %p); !\n",
1223 hDC
, lprect
, lppop
);
1224 if (lppop
->Height
== 0) MENU_MenuBarCalcSize(hDC
, lprect
, lppop
, hwnd
);
1225 lprect
->bottom
= lprect
->top
+ lppop
->Height
;
1226 if (suppress_draw
) return lppop
->Height
;
1228 FillRect32(hDC
, lprect
, GetSysColorBrush32(COLOR_MENU
) );
1230 if (TWEAK_WineLook
== WIN31_LOOK
) {
1231 SelectObject32( hDC
, GetSysColorPen32(COLOR_WINDOWFRAME
) );
1232 MoveTo( hDC
, lprect
->left
, lprect
->bottom
);
1233 LineTo32( hDC
, lprect
->right
, lprect
->bottom
);
1236 SelectObject32( hDC
, GetSysColorPen32(COLOR_3DFACE
));
1237 MoveTo( hDC
, lprect
->left
, lprect
->bottom
);
1238 LineTo32( hDC
, lprect
->right
, lprect
->bottom
);
1241 if (lppop
->nItems
== 0) return SYSMETRICS_CYMENU
;
1242 for (i
= 0; i
< lppop
->nItems
; i
++)
1244 MENU_DrawMenuItem( hwnd
, hDC
, &lppop
->items
[i
], lppop
->Height
, TRUE
,
1247 return lppop
->Height
;
1251 /***********************************************************************
1252 * MENU_PatchResidentPopup
1254 BOOL32
MENU_PatchResidentPopup( HQUEUE16 checkQueue
, WND
* checkWnd
)
1260 TRACE(menu
,"patching resident popup: %04x %04x [%04x %04x]\n",
1261 checkQueue
, checkWnd
? checkWnd
->hwndSelf
: 0, pTopPopupWnd
->hmemTaskQ
,
1262 pTopPopupWnd
->owner
? pTopPopupWnd
->owner
->hwndSelf
: 0);
1264 switch( checkQueue
)
1266 case 0: /* checkWnd is the new popup owner */
1269 pTopPopupWnd
->owner
= checkWnd
;
1270 if( pTopPopupWnd
->hmemTaskQ
!= checkWnd
->hmemTaskQ
)
1271 hTask
= QUEUE_GetQueueTask( checkWnd
->hmemTaskQ
);
1275 case 0xFFFF: /* checkWnd is destroyed */
1276 if( pTopPopupWnd
->owner
== checkWnd
)
1277 pTopPopupWnd
->owner
= NULL
;
1280 default: /* checkQueue is exiting */
1281 if( pTopPopupWnd
->hmemTaskQ
== checkQueue
)
1283 hTask
= QUEUE_GetQueueTask( pTopPopupWnd
->hmemTaskQ
);
1284 hTask
= TASK_GetNextTask( hTask
);
1291 TDB
* task
= (TDB
*)GlobalLock16( hTask
);
1294 pTopPopupWnd
->hInstance
= task
->hInstance
;
1295 pTopPopupWnd
->hmemTaskQ
= task
->hQueue
;
1298 else WARN(menu
,"failed to patch resident popup.\n");
1304 /***********************************************************************
1307 * Display a popup menu.
1309 static BOOL32
MENU_ShowPopup( HWND32 hwndOwner
, HMENU32 hmenu
, UINT32 id
,
1310 INT32 x
, INT32 y
, INT32 xanchor
, INT32 yanchor
)
1313 WND
*wndOwner
= NULL
;
1315 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
))) return FALSE
;
1316 if (menu
->FocusedItem
!= NO_SELECTED_ITEM
)
1318 menu
->items
[menu
->FocusedItem
].fState
&= ~(MF_HILITE
|MF_MOUSESELECT
);
1319 menu
->FocusedItem
= NO_SELECTED_ITEM
;
1322 if( (wndOwner
= WIN_FindWndPtr( hwndOwner
)) )
1324 UINT32 width
, height
;
1326 MENU_PopupMenuCalcSize( menu
, hwndOwner
);
1328 /* adjust popup menu pos so that it fits within the desktop */
1330 width
= menu
->Width
+ SYSMETRICS_CXBORDER
;
1331 height
= menu
->Height
+ SYSMETRICS_CYBORDER
;
1333 if( x
+ width
> SYSMETRICS_CXSCREEN
)
1336 x
-= width
- xanchor
;
1337 if( x
+ width
> SYSMETRICS_CXSCREEN
)
1338 x
= SYSMETRICS_CXSCREEN
- width
;
1342 if( y
+ height
> SYSMETRICS_CYSCREEN
)
1345 y
-= height
+ yanchor
;
1346 if( y
+ height
> SYSMETRICS_CYSCREEN
)
1347 y
= SYSMETRICS_CYSCREEN
- height
;
1351 width
+= POPUP_XSHADE
* SYSMETRICS_CXBORDER
; /* add space for shading */
1352 height
+= POPUP_YSHADE
* SYSMETRICS_CYBORDER
;
1354 /* NOTE: In Windows, top menu popup is not owned. */
1355 if (!pTopPopupWnd
) /* create top level popup menu window */
1357 assert( uSubPWndLevel
== 0 );
1359 pTopPopupWnd
= WIN_FindWndPtr(CreateWindow32A( POPUPMENU_CLASS_ATOM
, NULL
,
1360 WS_POPUP
, x
, y
, width
, height
,
1361 hwndOwner
, 0, wndOwner
->hInstance
,
1363 if (!pTopPopupWnd
) return FALSE
;
1364 menu
->hWnd
= pTopPopupWnd
->hwndSelf
;
1369 /* create a new window for the submenu */
1371 menu
->hWnd
= CreateWindow32A( POPUPMENU_CLASS_ATOM
, NULL
,
1372 WS_POPUP
, x
, y
, width
, height
,
1373 menu
->hWnd
, 0, wndOwner
->hInstance
,
1375 if( !menu
->hWnd
) return FALSE
;
1377 else /* top level popup menu window already exists */
1379 menu
->hWnd
= pTopPopupWnd
->hwndSelf
;
1381 MENU_PatchResidentPopup( 0, wndOwner
);
1382 SendMessage16( pTopPopupWnd
->hwndSelf
, MM_SETMENUHANDLE
, (WPARAM16
)hmenu
, 0L);
1384 /* adjust its size */
1386 SetWindowPos32( menu
->hWnd
, 0, x
, y
, width
, height
,
1387 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOREDRAW
);
1390 uSubPWndLevel
++; /* menu level counter */
1392 /* Display the window */
1394 SetWindowPos32( menu
->hWnd
, HWND_TOP
, 0, 0, 0, 0,
1395 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1396 UpdateWindow32( menu
->hWnd
);
1403 /***********************************************************************
1406 static void MENU_SelectItem( HWND32 hwndOwner
, HMENU32 hmenu
, UINT32 wIndex
,
1407 BOOL32 sendMenuSelect
)
1412 lppop
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
1413 if (!lppop
->nItems
) return;
1415 if ((wIndex
!= NO_SELECTED_ITEM
) &&
1416 (lppop
->items
[wIndex
].fType
& MF_SEPARATOR
))
1417 wIndex
= NO_SELECTED_ITEM
;
1419 if (lppop
->FocusedItem
== wIndex
) return;
1420 if (lppop
->wFlags
& MF_POPUP
) hdc
= GetDC32( lppop
->hWnd
);
1421 else hdc
= GetDCEx32( lppop
->hWnd
, 0, DCX_CACHE
| DCX_WINDOW
);
1423 /* Clear previous highlighted item */
1424 if (lppop
->FocusedItem
!= NO_SELECTED_ITEM
)
1426 lppop
->items
[lppop
->FocusedItem
].fState
&= ~(MF_HILITE
|MF_MOUSESELECT
);
1427 MENU_DrawMenuItem(lppop
->hWnd
,hdc
,&lppop
->items
[lppop
->FocusedItem
],
1428 lppop
->Height
, !(lppop
->wFlags
& MF_POPUP
),
1432 /* Highlight new item (if any) */
1433 lppop
->FocusedItem
= wIndex
;
1434 if (lppop
->FocusedItem
!= NO_SELECTED_ITEM
)
1436 lppop
->items
[lppop
->FocusedItem
].fState
|= MF_HILITE
;
1437 MENU_DrawMenuItem( lppop
->hWnd
, hdc
, &lppop
->items
[lppop
->FocusedItem
],
1438 lppop
->Height
, !(lppop
->wFlags
& MF_POPUP
),
1442 MENUITEM
*ip
= &lppop
->items
[lppop
->FocusedItem
];
1443 SendMessage16( hwndOwner
, WM_MENUSELECT
, ip
->wID
,
1444 MAKELONG(ip
->fType
| (ip
->fState
| MF_MOUSESELECT
),
1448 else if (sendMenuSelect
) {
1449 SendMessage16( hwndOwner
, WM_MENUSELECT
, hmenu
,
1450 MAKELONG( lppop
->wFlags
| MF_MOUSESELECT
, hmenu
) );
1452 ReleaseDC32( lppop
->hWnd
, hdc
);
1456 /***********************************************************************
1457 * MENU_MoveSelection
1459 * Moves currently selected item according to the offset parameter.
1460 * If there is no selection then it should select the last item if
1461 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
1463 static void MENU_MoveSelection( HWND32 hwndOwner
, HMENU32 hmenu
, INT32 offset
)
1468 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
1469 if (!menu
->items
) return;
1471 if ( menu
->FocusedItem
!= NO_SELECTED_ITEM
)
1473 if( menu
->nItems
== 1 ) return; else
1474 for (i
= menu
->FocusedItem
+ offset
; i
>= 0 && i
< menu
->nItems
1476 if (!(menu
->items
[i
].fType
& MF_SEPARATOR
))
1478 MENU_SelectItem( hwndOwner
, hmenu
, i
, TRUE
);
1483 for ( i
= (offset
> 0) ? 0 : menu
->nItems
- 1;
1484 i
>= 0 && i
< menu
->nItems
; i
+= offset
)
1485 if (!(menu
->items
[i
].fType
& MF_SEPARATOR
))
1487 MENU_SelectItem( hwndOwner
, hmenu
, i
, TRUE
);
1493 /**********************************************************************
1496 * Set an item flags, id and text ptr. Called by InsertMenu() and
1499 static BOOL32
MENU_SetItemData( MENUITEM
*item
, UINT32 flags
, UINT32 id
,
1502 LPSTR prevText
= IS_STRING_ITEM(item
->fType
) ? item
->text
: NULL
;
1504 debug_print_menuitem("MENU_SetItemData from: ", item
, "");
1506 if (IS_STRING_ITEM(flags
))
1510 flags
|= MF_SEPARATOR
;
1516 /* Item beginning with a backspace is a help item */
1522 if (!(text
= HEAP_strdupA( SystemHeap
, 0, str
))) return FALSE
;
1526 else if (flags
& MF_BITMAP
) item
->text
= (LPSTR
)(HBITMAP32
)LOWORD(str
);
1527 else item
->text
= NULL
;
1529 if (flags
& MF_OWNERDRAW
)
1530 item
->dwItemData
= (DWORD
)str
;
1532 item
->dwItemData
= 0;
1534 if ((item
->fType
& MF_POPUP
) && (flags
& MF_POPUP
) && (item
->hSubMenu
!= id
) )
1535 DestroyMenu32( item
->hSubMenu
); /* ModifyMenu() spec */
1537 if (flags
& MF_POPUP
)
1539 POPUPMENU
*menu
= (POPUPMENU
*)USER_HEAP_LIN_ADDR((UINT16
)id
);
1540 if (IS_A_MENU(menu
)) menu
->wFlags
|= MF_POPUP
;
1552 if (flags
& MF_POPUP
)
1553 item
->hSubMenu
= id
;
1555 if ((item
->fType
& MF_POPUP
) && !(flags
& MF_POPUP
) )
1556 flags
|= MF_POPUP
; /* keep popup */
1558 item
->fType
= flags
& TYPE_MASK
;
1559 item
->fState
= (flags
& STATE_MASK
) &
1560 ~(MF_HILITE
| MF_MOUSESELECT
| MF_BYPOSITION
);
1563 /* Don't call SetRectEmpty here! */
1566 if (prevText
) HeapFree( SystemHeap
, 0, prevText
);
1568 debug_print_menuitem("MENU_SetItemData to : ", item
, "");
1573 /**********************************************************************
1576 * Insert a new item into a menu.
1578 static MENUITEM
*MENU_InsertItem( HMENU32 hMenu
, UINT32 pos
, UINT32 flags
)
1583 if (!(menu
= (POPUPMENU
*)USER_HEAP_LIN_ADDR(hMenu
)))
1585 WARN(menu
, "%04x not a menu handle\n",
1590 /* Find where to insert new item */
1592 if ((flags
& MF_BYPOSITION
) &&
1593 ((pos
== (UINT32
)-1) || (pos
== menu
->nItems
)))
1595 /* Special case: append to menu */
1596 /* Some programs specify the menu length to do that */
1601 if (!MENU_FindItem( &hMenu
, &pos
, flags
))
1603 WARN(menu
, "item %x not found\n",
1607 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
)))
1609 WARN(menu
,"%04x not a menu handle\n",
1615 /* Create new items array */
1617 newItems
= HeapAlloc( SystemHeap
, 0, sizeof(MENUITEM
) * (menu
->nItems
+1) );
1620 WARN(menu
, "allocation failed\n" );
1623 if (menu
->nItems
> 0)
1625 /* Copy the old array into the new */
1626 if (pos
> 0) memcpy( newItems
, menu
->items
, pos
* sizeof(MENUITEM
) );
1627 if (pos
< menu
->nItems
) memcpy( &newItems
[pos
+1], &menu
->items
[pos
],
1628 (menu
->nItems
-pos
)*sizeof(MENUITEM
) );
1629 HeapFree( SystemHeap
, 0, menu
->items
);
1631 menu
->items
= newItems
;
1633 memset( &newItems
[pos
], 0, sizeof(*newItems
) );
1634 return &newItems
[pos
];
1638 /**********************************************************************
1639 * MENU_ParseResource
1641 * Parse a standard menu resource and add items to the menu.
1642 * Return a pointer to the end of the resource.
1644 static LPCSTR
MENU_ParseResource( LPCSTR res
, HMENU32 hMenu
, BOOL32 unicode
)
1651 flags
= GET_WORD(res
);
1652 res
+= sizeof(WORD
);
1653 if (!(flags
& MF_POPUP
))
1656 res
+= sizeof(WORD
);
1658 if (!IS_STRING_ITEM(flags
))
1659 ERR(menu
, "not a string item %04x\n", flags
);
1661 if (!unicode
) res
+= strlen(str
) + 1;
1662 else res
+= (lstrlen32W((LPCWSTR
)str
) + 1) * sizeof(WCHAR
);
1663 if (flags
& MF_POPUP
)
1665 HMENU32 hSubMenu
= CreatePopupMenu32();
1666 if (!hSubMenu
) return NULL
;
1667 if (!(res
= MENU_ParseResource( res
, hSubMenu
, unicode
)))
1669 if (!unicode
) AppendMenu32A( hMenu
, flags
, (UINT32
)hSubMenu
, str
);
1670 else AppendMenu32W( hMenu
, flags
, (UINT32
)hSubMenu
, (LPCWSTR
)str
);
1672 else /* Not a popup */
1674 if (!unicode
) AppendMenu32A( hMenu
, flags
, id
, *str
? str
: NULL
);
1675 else AppendMenu32W( hMenu
, flags
, id
,
1676 *(LPCWSTR
)str
? (LPCWSTR
)str
: NULL
);
1678 } while (!(flags
& MF_END
));
1683 /**********************************************************************
1684 * MENUEX_ParseResource
1686 * Parse an extended menu resource and add items to the menu.
1687 * Return a pointer to the end of the resource.
1689 static LPCSTR
MENUEX_ParseResource( LPCSTR res
, HMENU32 hMenu
)
1693 MENUITEMINFO32W mii
;
1695 mii
.cbSize
= sizeof(mii
);
1696 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
;
1697 mii
.fType
= GET_DWORD(res
);
1698 res
+= sizeof(DWORD
);
1699 mii
.fState
= GET_DWORD(res
);
1700 res
+= sizeof(DWORD
);
1701 mii
.wID
= GET_DWORD(res
);
1702 res
+= sizeof(DWORD
);
1703 resinfo
= GET_WORD(res
); /* FIXME: for 16-bit apps this is a byte. */
1704 res
+= sizeof(WORD
);
1705 /* Align the text on a word boundary. */
1706 res
+= (~((int)res
- 1)) & 1;
1707 mii
.dwTypeData
= (LPWSTR
) res
;
1708 res
+= (1 + lstrlen32W(mii
.dwTypeData
)) * sizeof(WCHAR
);
1709 /* Align the following fields on a dword boundary. */
1710 res
+= (~((int)res
- 1)) & 3;
1712 /* FIXME: This is inefficient and cannot be optimised away by gcc. */
1714 LPSTR newstr
= HEAP_strdupWtoA(GetProcessHeap(),
1716 TRACE(menu
, "Menu item: [%08x,%08x,%04x,%04x,%s]\n",
1717 mii
.fType
, mii
.fState
, mii
.wID
, resinfo
, newstr
);
1718 HeapFree( GetProcessHeap(), 0, newstr
);
1721 if (resinfo
& 1) { /* Pop-up? */
1722 DWORD helpid
= GET_DWORD(res
); /* FIXME: use this. */
1723 res
+= sizeof(DWORD
);
1724 mii
.hSubMenu
= CreatePopupMenu32();
1727 if (!(res
= MENUEX_ParseResource(res
, mii
.hSubMenu
))) {
1728 DestroyMenu32(mii
.hSubMenu
);
1731 mii
.fMask
|= MIIM_SUBMENU
;
1732 mii
.fType
|= MF_POPUP
;
1734 InsertMenuItem32W(hMenu
, -1, MF_BYPOSITION
, &mii
);
1735 } while (!(resinfo
& MF_END
));
1740 /***********************************************************************
1743 * Return the handle of the selected sub-popup menu (if any).
1745 static HMENU32
MENU_GetSubPopup( HMENU32 hmenu
)
1750 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
1752 if (menu
->FocusedItem
== NO_SELECTED_ITEM
) return 0;
1754 item
= &menu
->items
[menu
->FocusedItem
];
1755 if ((item
->fType
& MF_POPUP
) && (item
->fState
& MF_MOUSESELECT
))
1756 return item
->hSubMenu
;
1761 /***********************************************************************
1762 * MENU_HideSubPopups
1764 * Hide the sub-popup menus of this menu.
1766 static void MENU_HideSubPopups( HWND32 hwndOwner
, HMENU32 hmenu
,
1767 BOOL32 sendMenuSelect
)
1769 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);;
1771 if (menu
&& uSubPWndLevel
)
1777 if (menu
->FocusedItem
!= NO_SELECTED_ITEM
)
1779 item
= &menu
->items
[menu
->FocusedItem
];
1780 if (!(item
->fType
& MF_POPUP
) ||
1781 !(item
->fState
& MF_MOUSESELECT
)) return;
1782 item
->fState
&= ~MF_MOUSESELECT
;
1783 hsubmenu
= item
->hSubMenu
;
1786 submenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hsubmenu
);
1787 MENU_HideSubPopups( hwndOwner
, hsubmenu
, FALSE
);
1788 MENU_SelectItem( hwndOwner
, hsubmenu
, NO_SELECTED_ITEM
, sendMenuSelect
);
1790 if (submenu
->hWnd
== pTopPopupWnd
->hwndSelf
)
1792 ShowWindow32( submenu
->hWnd
, SW_HIDE
);
1797 DestroyWindow32( submenu
->hWnd
);
1804 /***********************************************************************
1807 * Display the sub-menu of the selected item of this menu.
1808 * Return the handle of the submenu, or hmenu if no submenu to display.
1810 static HMENU32
MENU_ShowSubPopup( HWND32 hwndOwner
, HMENU32 hmenu
,
1811 BOOL32 selectFirst
)
1819 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
))) return hmenu
;
1821 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
)) ||
1822 (menu
->FocusedItem
== NO_SELECTED_ITEM
)) return hmenu
;
1824 item
= &menu
->items
[menu
->FocusedItem
];
1825 if (!(item
->fType
& MF_POPUP
) ||
1826 (item
->fState
& (MF_GRAYED
| MF_DISABLED
))) return hmenu
;
1828 /* message must be send before using item,
1829 because nearly everything may by changed by the application ! */
1831 SendMessage16( hwndOwner
, WM_INITMENUPOPUP
, (WPARAM16
)item
->hSubMenu
,
1832 MAKELONG( menu
->FocusedItem
, IS_SYSTEM_MENU(menu
) ));
1834 item
= &menu
->items
[menu
->FocusedItem
];
1837 /* correct item if modified as a reaction to WM_INITMENUPOPUP-message */
1838 if (!(item
->fState
& MF_HILITE
))
1840 if (menu
->wFlags
& MF_POPUP
) hdc
= GetDC32( menu
->hWnd
);
1841 else hdc
= GetDCEx32( menu
->hWnd
, 0, DCX_CACHE
| DCX_WINDOW
);
1842 item
->fState
|= MF_HILITE
;
1843 MENU_DrawMenuItem( menu
->hWnd
, hdc
, item
, menu
->Height
, !(menu
->wFlags
& MF_POPUP
), ODA_DRAWENTIRE
);
1844 ReleaseDC32( menu
->hWnd
, hdc
);
1846 if (!item
->rect
.top
&& !item
->rect
.left
&& !item
->rect
.bottom
&& !item
->rect
.right
)
1849 item
->fState
|= MF_MOUSESELECT
;
1851 if (IS_SYSTEM_MENU(menu
))
1853 MENU_InitSysMenuPopup(item
->hSubMenu
, wndPtr
->dwStyle
, wndPtr
->class->style
);
1855 NC_GetSysPopupPos( wndPtr
, &rect
);
1856 rect
.top
= rect
.bottom
;
1857 rect
.right
= SYSMETRICS_CXSIZE
;
1858 rect
.bottom
= SYSMETRICS_CYSIZE
;
1862 if (menu
->wFlags
& MF_POPUP
)
1864 rect
.left
= wndPtr
->rectWindow
.left
+ item
->rect
.right
-arrow_bitmap_width
;
1865 rect
.top
= wndPtr
->rectWindow
.top
+ item
->rect
.top
;
1866 rect
.right
= item
->rect
.left
- item
->rect
.right
+ 2*arrow_bitmap_width
;
1867 rect
.bottom
= item
->rect
.top
- item
->rect
.bottom
;
1871 rect
.left
= wndPtr
->rectWindow
.left
+ item
->rect
.left
;
1872 rect
.top
= wndPtr
->rectWindow
.top
+ item
->rect
.bottom
;
1873 rect
.right
= item
->rect
.right
- item
->rect
.left
;
1874 rect
.bottom
= item
->rect
.bottom
- item
->rect
.top
;
1878 MENU_ShowPopup( hwndOwner
, item
->hSubMenu
, menu
->FocusedItem
,
1879 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1881 MENU_MoveSelection( hwndOwner
, item
->hSubMenu
, ITEM_NEXT
);
1882 return item
->hSubMenu
;
1885 /***********************************************************************
1888 * Walks menu chain trying to find a menu pt maps to.
1890 static HMENU32
MENU_PtMenu( HMENU32 hMenu
, POINT16 pt
)
1892 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hMenu
);
1893 register UINT32 ht
= menu
->FocusedItem
;
1895 /* try subpopup first (if any) */
1896 ht
= (ht
!= NO_SELECTED_ITEM
&&
1897 (menu
->items
[ht
].fType
& MF_POPUP
) &&
1898 (menu
->items
[ht
].fState
& MF_MOUSESELECT
))
1899 ? (UINT32
) MENU_PtMenu(menu
->items
[ht
].hSubMenu
, pt
) : 0;
1901 if( !ht
) /* check the current window (avoiding WM_HITTEST) */
1903 ht
= (UINT32
)NC_HandleNCHitTest( menu
->hWnd
, pt
);
1904 if( menu
->wFlags
& MF_POPUP
)
1905 ht
= (ht
!= (UINT32
)HTNOWHERE
&&
1906 ht
!= (UINT32
)HTERROR
) ? (UINT32
)hMenu
: 0;
1909 WND
* wndPtr
= WIN_FindWndPtr(menu
->hWnd
);
1911 ht
= ( ht
== HTSYSMENU
) ? (UINT32
)(wndPtr
->hSysMenu
)
1912 : ( ht
== HTMENU
) ? (UINT32
)(wndPtr
->wIDmenu
) : 0;
1917 /***********************************************************************
1918 * MENU_ExecFocusedItem
1920 * Execute a menu item (for instance when user pressed Enter).
1921 * Return the wID of the executed item. Otherwise, zero indicating
1922 * that no menu item wase executed;
1924 static INT32
MENU_ExecFocusedItem( MTRACKER
* pmt
, HMENU32 hMenu
)
1927 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hMenu
);
1928 if (!menu
|| !menu
->nItems
||
1929 (menu
->FocusedItem
== NO_SELECTED_ITEM
)) return 0;
1931 item
= &menu
->items
[menu
->FocusedItem
];
1933 TRACE(menu
, "%08x %08x %08x\n",
1934 hMenu
, item
->wID
, item
->hSubMenu
);
1936 if (!(item
->fType
& MF_POPUP
))
1938 if (!(item
->fState
& (MF_GRAYED
| MF_DISABLED
)))
1940 if( menu
->wFlags
& MF_SYSMENU
)
1942 PostMessage16( pmt
->hOwnerWnd
, WM_SYSCOMMAND
, item
->wID
,
1943 MAKELPARAM((INT16
)pmt
->pt
.x
, (INT16
)pmt
->pt
.y
) );
1947 PostMessage16( pmt
->hOwnerWnd
, WM_COMMAND
, item
->wID
, 0 );
1955 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
, hMenu
, TRUE
);
1960 /***********************************************************************
1961 * MENU_SwitchTracking
1963 * Helper function for menu navigation routines.
1965 static void MENU_SwitchTracking( MTRACKER
* pmt
, HMENU32 hPtMenu
, UINT32 id
)
1967 POPUPMENU
*ptmenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hPtMenu
);
1968 POPUPMENU
*topmenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( pmt
->hTopMenu
);
1970 if( pmt
->hTopMenu
!= hPtMenu
&&
1971 !((ptmenu
->wFlags
| topmenu
->wFlags
) & MF_POPUP
) )
1973 /* both are top level menus (system and menu-bar) */
1975 MENU_HideSubPopups( pmt
->hOwnerWnd
, pmt
->hTopMenu
, FALSE
);
1976 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hTopMenu
, NO_SELECTED_ITEM
, FALSE
);
1977 pmt
->hTopMenu
= hPtMenu
;
1979 else MENU_HideSubPopups( pmt
->hOwnerWnd
, hPtMenu
, FALSE
);
1980 MENU_SelectItem( pmt
->hOwnerWnd
, hPtMenu
, id
, TRUE
);
1984 /***********************************************************************
1987 * Return TRUE if we can go on with menu tracking.
1989 static BOOL32
MENU_ButtonDown( MTRACKER
* pmt
, HMENU32 hPtMenu
)
1994 POPUPMENU
*ptmenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hPtMenu
);
1997 if( IS_SYSTEM_MENU(ptmenu
) )
1998 item
= ptmenu
->items
;
2000 item
= MENU_FindItemByCoords( ptmenu
, pmt
->pt
, &id
);
2004 if( ptmenu
->FocusedItem
== id
)
2006 /* nothing to do with already selected non-popup */
2007 if( !(item
->fType
& MF_POPUP
) ) return TRUE
;
2009 if( item
->fState
& MF_MOUSESELECT
)
2011 if( ptmenu
->wFlags
& MF_POPUP
)
2013 /* hide selected subpopup */
2015 MENU_HideSubPopups( pmt
->hOwnerWnd
, hPtMenu
, TRUE
);
2016 pmt
->hCurrentMenu
= hPtMenu
;
2019 return FALSE
; /* shouldn't get here */
2022 else MENU_SwitchTracking( pmt
, hPtMenu
, id
);
2024 /* try to display a subpopup */
2026 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
, hPtMenu
, FALSE
);
2029 else WARN(menu
, "\tunable to find clicked item!\n");
2034 /***********************************************************************
2037 * Return the the value of MENU_ExecFocusedItem if
2038 * the selected item was not a popup
2039 * 1 if the item was a popup
2041 * A zero return value indicates that we can't go on with menu tracking.
2043 static INT32
MENU_ButtonUp( MTRACKER
* pmt
, HMENU32 hPtMenu
)
2048 POPUPMENU
*ptmenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hPtMenu
);
2051 if( IS_SYSTEM_MENU(ptmenu
) )
2052 item
= ptmenu
->items
;
2054 item
= MENU_FindItemByCoords( ptmenu
, pmt
->pt
, &id
);
2056 if( item
&& (ptmenu
->FocusedItem
== id
))
2058 if( !(item
->fType
& MF_POPUP
) )
2059 return MENU_ExecFocusedItem( pmt
, hPtMenu
);
2060 hPtMenu
= item
->hSubMenu
;
2061 if( hPtMenu
== pmt
->hCurrentMenu
)
2063 /* Select first item of sub-popup */
2065 MENU_SelectItem( pmt
->hOwnerWnd
, hPtMenu
, NO_SELECTED_ITEM
, FALSE
);
2066 MENU_MoveSelection( pmt
->hOwnerWnd
, hPtMenu
, ITEM_NEXT
);
2075 /***********************************************************************
2078 * Return TRUE if we can go on with menu tracking.
2080 static BOOL32
MENU_MouseMove( MTRACKER
* pmt
, HMENU32 hPtMenu
)
2082 UINT32 id
= NO_SELECTED_ITEM
;
2083 POPUPMENU
*ptmenu
= NULL
;
2087 ptmenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hPtMenu
);
2088 if( IS_SYSTEM_MENU(ptmenu
) )
2091 MENU_FindItemByCoords( ptmenu
, pmt
->pt
, &id
);
2094 if( id
== NO_SELECTED_ITEM
)
2096 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hCurrentMenu
,
2097 NO_SELECTED_ITEM
, TRUE
);
2099 else if( ptmenu
->FocusedItem
!= id
)
2101 MENU_SwitchTracking( pmt
, hPtMenu
, id
);
2102 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
, hPtMenu
, FALSE
);
2108 /***********************************************************************
2111 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
2113 static LRESULT
MENU_DoNextMenu( MTRACKER
* pmt
, UINT32 vk
)
2115 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( pmt
->hTopMenu
);
2117 if( (vk
== VK_LEFT
&& menu
->FocusedItem
== 0 ) ||
2118 (vk
== VK_RIGHT
&& menu
->FocusedItem
== menu
->nItems
- 1))
2124 LRESULT l
= SendMessage16( pmt
->hOwnerWnd
, WM_NEXTMENU
, (WPARAM16
)vk
,
2125 (IS_SYSTEM_MENU(menu
)) ? GetSubMenu16(pmt
->hTopMenu
,0) : pmt
->hTopMenu
);
2127 TRACE(menu
,"%04x [%04x] -> %04x [%04x]\n",
2128 (UINT16
)pmt
->hCurrentMenu
, (UINT16
)pmt
->hOwnerWnd
, LOWORD(l
), HIWORD(l
) );
2132 wndPtr
= WIN_FindWndPtr(pmt
->hOwnerWnd
);
2134 hNewWnd
= pmt
->hOwnerWnd
;
2135 if( IS_SYSTEM_MENU(menu
) )
2137 /* switch to the menu bar */
2139 if( wndPtr
->dwStyle
& WS_CHILD
|| !wndPtr
->wIDmenu
)
2142 hNewMenu
= wndPtr
->wIDmenu
;
2145 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hNewMenu
);
2146 id
= menu
->nItems
- 1;
2149 else if( wndPtr
->dwStyle
& WS_SYSMENU
)
2151 /* switch to the system menu */
2152 hNewMenu
= wndPtr
->hSysMenu
;
2156 else /* application returned a new menu to switch to */
2158 hNewMenu
= LOWORD(l
); hNewWnd
= HIWORD(l
);
2160 if( IsMenu32(hNewMenu
) && IsWindow32(hNewWnd
) )
2162 wndPtr
= WIN_FindWndPtr(hNewWnd
);
2164 if( wndPtr
->dwStyle
& WS_SYSMENU
&&
2165 GetSubMenu16(wndPtr
->hSysMenu
, 0) == hNewMenu
)
2167 /* get the real system menu */
2168 hNewMenu
= wndPtr
->hSysMenu
;
2170 else if( wndPtr
->dwStyle
& WS_CHILD
|| wndPtr
->wIDmenu
!= hNewMenu
)
2172 /* FIXME: Not sure what to do here, perhaps,
2173 * try to track hNewMenu as a popup? */
2175 TRACE(menu
," -- got confused.\n");
2182 if( hNewMenu
!= pmt
->hTopMenu
)
2184 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hTopMenu
, NO_SELECTED_ITEM
, FALSE
);
2185 if( pmt
->hCurrentMenu
!= pmt
->hTopMenu
)
2186 MENU_HideSubPopups( pmt
->hOwnerWnd
, pmt
->hTopMenu
, FALSE
);
2189 if( hNewWnd
!= pmt
->hOwnerWnd
)
2192 pmt
->hOwnerWnd
= hNewWnd
;
2193 EVENT_Capture( pmt
->hOwnerWnd
, HTMENU
);
2196 pmt
->hTopMenu
= pmt
->hCurrentMenu
= hNewMenu
; /* all subpopups are hidden */
2197 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hTopMenu
, id
, TRUE
);
2204 /***********************************************************************
2207 * The idea is not to show the popup if the next input message is
2208 * going to hide it anyway.
2210 static BOOL32
MENU_SuspendPopup( MTRACKER
* pmt
, UINT16 uMsg
)
2214 msg
.hwnd
= pmt
->hOwnerWnd
;
2216 PeekMessage16( &msg
, 0, 0, 0, PM_NOYIELD
| PM_REMOVE
);
2217 pmt
->trackFlags
|= TF_SKIPREMOVE
;
2222 PeekMessage16( &msg
, 0, 0, 0, PM_NOYIELD
| PM_NOREMOVE
);
2223 if( msg
.message
== WM_KEYUP
|| msg
.message
== WM_PAINT
)
2225 PeekMessage16( &msg
, 0, 0, 0, PM_NOYIELD
| PM_REMOVE
);
2226 PeekMessage16( &msg
, 0, 0, 0, PM_NOYIELD
| PM_NOREMOVE
);
2227 if( msg
.message
== WM_KEYDOWN
&&
2228 (msg
.wParam
== VK_LEFT
|| msg
.wParam
== VK_RIGHT
))
2230 pmt
->trackFlags
|= TF_SUSPENDPOPUP
;
2237 /* failures go through this */
2238 pmt
->trackFlags
&= ~TF_SUSPENDPOPUP
;
2242 /***********************************************************************
2245 * Handle a VK_LEFT key event in a menu.
2247 static void MENU_KeyLeft( MTRACKER
* pmt
)
2250 HMENU32 hmenutmp
, hmenuprev
;
2253 hmenuprev
= hmenutmp
= pmt
->hTopMenu
;
2254 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenutmp
);
2256 /* Try to move 1 column left (if possible) */
2257 if( (prevcol
= MENU_GetStartOfPrevColumn( pmt
->hCurrentMenu
)) !=
2258 NO_SELECTED_ITEM
) {
2260 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hCurrentMenu
,
2265 /* close topmost popup */
2266 while (hmenutmp
!= pmt
->hCurrentMenu
)
2268 hmenuprev
= hmenutmp
;
2269 hmenutmp
= MENU_GetSubPopup( hmenuprev
);
2272 MENU_HideSubPopups( pmt
->hOwnerWnd
, hmenuprev
, TRUE
);
2273 pmt
->hCurrentMenu
= hmenuprev
;
2275 if ( (hmenuprev
== pmt
->hTopMenu
) && !(menu
->wFlags
& MF_POPUP
) )
2277 /* move menu bar selection if no more popups are left */
2279 if( !MENU_DoNextMenu( pmt
, VK_LEFT
) )
2280 MENU_MoveSelection( pmt
->hOwnerWnd
, pmt
->hTopMenu
, ITEM_PREV
);
2282 if ( hmenuprev
!= hmenutmp
|| pmt
->trackFlags
& TF_SUSPENDPOPUP
)
2284 /* A sublevel menu was displayed - display the next one
2285 * unless there is another displacement coming up */
2287 if( !MENU_SuspendPopup( pmt
, WM_KEYDOWN
) )
2288 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
,
2289 pmt
->hTopMenu
, TRUE
);
2295 /***********************************************************************
2298 * Handle a VK_RIGHT key event in a menu.
2300 static void MENU_KeyRight( MTRACKER
* pmt
)
2303 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( pmt
->hTopMenu
);
2306 TRACE(menu
, "MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
2308 ((POPUPMENU
*)USER_HEAP_LIN_ADDR(pmt
->hCurrentMenu
))->
2310 pmt
->hTopMenu
, menu
->items
[0].text
);
2312 if ( (menu
->wFlags
& MF_POPUP
) || (pmt
->hCurrentMenu
!= pmt
->hTopMenu
))
2314 /* If already displaying a popup, try to display sub-popup */
2316 hmenutmp
= pmt
->hCurrentMenu
;
2317 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
, hmenutmp
, TRUE
);
2319 /* if subpopup was displayed then we are done */
2320 if (hmenutmp
!= pmt
->hCurrentMenu
) return;
2323 /* Check to see if there's another column */
2324 if( (nextcol
= MENU_GetStartOfNextColumn( pmt
->hCurrentMenu
)) !=
2325 NO_SELECTED_ITEM
) {
2326 TRACE(menu
, "Going to %d.\n", nextcol
);
2327 MENU_SelectItem( pmt
->hOwnerWnd
, pmt
->hCurrentMenu
,
2332 if (!(menu
->wFlags
& MF_POPUP
)) /* menu bar tracking */
2334 if( pmt
->hCurrentMenu
!= pmt
->hTopMenu
)
2336 MENU_HideSubPopups( pmt
->hOwnerWnd
, pmt
->hTopMenu
, FALSE
);
2337 hmenutmp
= pmt
->hCurrentMenu
= pmt
->hTopMenu
;
2338 } else hmenutmp
= 0;
2340 /* try to move to the next item */
2341 if( !MENU_DoNextMenu( pmt
, VK_RIGHT
) )
2342 MENU_MoveSelection( pmt
->hOwnerWnd
, pmt
->hTopMenu
, ITEM_NEXT
);
2344 if( hmenutmp
|| pmt
->trackFlags
& TF_SUSPENDPOPUP
)
2345 if( !MENU_SuspendPopup(pmt
, WM_KEYDOWN
) )
2346 pmt
->hCurrentMenu
= MENU_ShowSubPopup( pmt
->hOwnerWnd
,
2347 pmt
->hTopMenu
, TRUE
);
2351 /***********************************************************************
2354 * Menu tracking code.
2356 static INT32
MENU_TrackMenu( HMENU32 hmenu
, UINT32 wFlags
, INT32 x
, INT32 y
,
2357 HWND32 hwnd
, const RECT32
*lprect
)
2362 INT32 executedMenuId
= 0;
2363 MTRACKER mt
= { 0, hmenu
, hmenu
, hwnd
, {x
, y
} }; /* control struct */
2366 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
))) return FALSE
;
2368 if (wFlags
& TPM_BUTTONDOWN
) MENU_ButtonDown( &mt
, hmenu
);
2370 EVENT_Capture( mt
.hOwnerWnd
, HTMENU
);
2374 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( mt
.hCurrentMenu
);
2375 msg
.hwnd
= (wFlags
& TPM_ENTERIDLEEX
&& menu
->wFlags
& MF_POPUP
) ? menu
->hWnd
: 0;
2377 /* we have to keep the message in the queue until it's
2378 * clear that menu loop is not over yet. */
2380 if (!MSG_InternalGetMessage( &msg
, msg
.hwnd
, mt
.hOwnerWnd
,
2381 MSGF_MENU
, PM_NOREMOVE
, TRUE
)) break;
2383 TranslateMessage32( &msg
);
2387 if ((msg
.message
>= WM_MOUSEFIRST
) && (msg
.message
<= WM_MOUSELAST
))
2389 /* Find a menu for this mouse event */
2391 CONV_POINT32TO16( &msg
.pt
, &pt16
);
2392 hmenu
= MENU_PtMenu( mt
.hTopMenu
, pt16
);
2396 /* no WM_NC... messages in captured state */
2398 case WM_RBUTTONDBLCLK
:
2399 case WM_RBUTTONDOWN
:
2400 if (!(wFlags
& TPM_RIGHTBUTTON
)) break;
2402 case WM_LBUTTONDBLCLK
:
2403 case WM_LBUTTONDOWN
:
2404 fEndMenu
|= !MENU_ButtonDown( &mt
, hmenu
);
2408 if (!(wFlags
& TPM_RIGHTBUTTON
)) break;
2411 /* Check if a menu was selected by the mouse */
2414 executedMenuId
= MENU_ButtonUp( &mt
, hmenu
);
2416 /* the executedMenuId higher than one means that it contains
2417 the id of the selected item so we have to put the fEndMenu to TRUE.
2418 Otherwise, it contains a continue
2419 flag returned by MENU_ButtonUp indicating if we can continue with
2420 menu tracking or not*/
2421 fEndMenu
= ((executedMenuId
> 1) ? TRUE
: FALSE
);
2424 /* No menu was selected by the mouse */
2425 /* if the function was called by TrackPopupMenu, continue
2426 with the menu tracking. If not, stop it */
2428 fEndMenu
= ((wFlags
& TPM_POPUPMENU
) ? FALSE
: TRUE
);
2433 /* In win95 winelook, the selected menu item must be changed every time the
2434 mouse moves. In Win31 winelook, the mouse button has to be held down */
2436 if ( (TWEAK_WineLook
> WIN31_LOOK
) ||
2437 ( (msg
.wParam
& MK_LBUTTON
) ||
2438 ((wFlags
& TPM_RIGHTBUTTON
) && (msg
.wParam
& MK_RBUTTON
))) )
2440 fEndMenu
|= !MENU_MouseMove( &mt
, hmenu
);
2442 } /* switch(msg.message) - mouse */
2444 else if ((msg
.message
>= WM_KEYFIRST
) && (msg
.message
<= WM_KEYLAST
))
2446 fRemove
= TRUE
; /* Keyboard messages are always removed */
2454 MENU_SelectItem( mt
.hOwnerWnd
, mt
.hCurrentMenu
,
2455 NO_SELECTED_ITEM
, FALSE
);
2458 MENU_MoveSelection( mt
.hOwnerWnd
, mt
.hCurrentMenu
,
2459 (msg
.wParam
== VK_HOME
)? ITEM_NEXT
: ITEM_PREV
);
2462 case VK_DOWN
: /* If on menu bar, pull-down the menu */
2464 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( mt
.hCurrentMenu
);
2465 if (!(menu
->wFlags
& MF_POPUP
))
2466 mt
.hCurrentMenu
= MENU_ShowSubPopup( mt
.hOwnerWnd
, mt
.hTopMenu
, TRUE
);
2467 else /* otherwise try to move selection */
2468 MENU_MoveSelection( mt
.hOwnerWnd
, mt
.hCurrentMenu
, ITEM_NEXT
);
2472 MENU_KeyLeft( &mt
);
2476 MENU_KeyRight( &mt
);
2486 break; /* WM_KEYDOWN */
2496 break; /* WM_SYSKEYDOWN */
2502 if (msg
.wParam
== '\r' || msg
.wParam
== ' ')
2504 executedMenuId
= MENU_ExecFocusedItem(&mt
,mt
.hCurrentMenu
);
2505 fEndMenu
= ((executedMenuId
!= 0) ? TRUE
:FALSE
);
2510 /* Hack to avoid control chars. */
2511 /* We will find a better way real soon... */
2512 if ((msg
.wParam
<= 32) || (msg
.wParam
>= 127)) break;
2514 pos
= MENU_FindItemByKey( mt
.hOwnerWnd
, mt
.hCurrentMenu
,
2515 LOWORD(msg
.wParam
), FALSE
);
2516 if (pos
== (UINT32
)-2) fEndMenu
= TRUE
;
2517 else if (pos
== (UINT32
)-1) MessageBeep32(0);
2520 MENU_SelectItem( mt
.hOwnerWnd
, mt
.hCurrentMenu
, pos
, TRUE
);
2521 executedMenuId
= MENU_ExecFocusedItem(&mt
,mt
.hCurrentMenu
);
2522 fEndMenu
= ((executedMenuId
!= 0) ? TRUE
:FALSE
);
2526 } /* switch(msg.message) - kbd */
2530 DispatchMessage32A( &msg
);
2533 if (!fEndMenu
) fRemove
= TRUE
;
2535 /* finally remove message from the queue */
2537 if (fRemove
&& !(mt
.trackFlags
& TF_SKIPREMOVE
) )
2538 PeekMessage32A( &msg
, 0, msg
.message
, msg
.message
, PM_REMOVE
);
2539 else mt
.trackFlags
&= ~TF_SKIPREMOVE
;
2543 if( IsWindow32( mt
.hOwnerWnd
) )
2545 MENU_HideSubPopups( mt
.hOwnerWnd
, mt
.hTopMenu
, FALSE
);
2547 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( mt
.hTopMenu
);
2548 if (menu
&& menu
->wFlags
& MF_POPUP
)
2550 ShowWindow32( menu
->hWnd
, SW_HIDE
);
2553 MENU_SelectItem( mt
.hOwnerWnd
, mt
.hTopMenu
, NO_SELECTED_ITEM
, FALSE
);
2554 SendMessage16( mt
.hOwnerWnd
, WM_MENUSELECT
, 0, MAKELONG( 0xffff, 0 ) );
2557 /* returning the id of the selected menu.
2558 The return value is only used by TrackPopupMenu */
2559 return executedMenuId
;
2562 /***********************************************************************
2565 static BOOL32
MENU_InitTracking(HWND32 hWnd
, HMENU32 hMenu
)
2568 SendMessage16( hWnd
, WM_ENTERMENULOOP
, 0, 0 );
2569 SendMessage16( hWnd
, WM_SETCURSOR
, hWnd
, HTCAPTION
);
2570 SendMessage16( hWnd
, WM_INITMENU
, hMenu
, 0 );
2574 /***********************************************************************
2575 * MENU_TrackMouseMenuBar
2577 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
2579 void MENU_TrackMouseMenuBar( WND
* wndPtr
, INT32 ht
, POINT32 pt
)
2581 HWND32 hWnd
= wndPtr
->hwndSelf
;
2582 HMENU32 hMenu
= (ht
== HTSYSMENU
) ? wndPtr
->hSysMenu
: wndPtr
->wIDmenu
;
2584 if (IsMenu32(hMenu
))
2586 MENU_InitTracking( hWnd
, hMenu
);
2587 MENU_TrackMenu( hMenu
, TPM_ENTERIDLEEX
| TPM_BUTTONDOWN
|
2588 TPM_LEFTALIGN
| TPM_LEFTBUTTON
, pt
.x
, pt
.y
, hWnd
, NULL
);
2590 SendMessage16( hWnd
, WM_EXITMENULOOP
, 0, 0 );
2596 /***********************************************************************
2597 * MENU_TrackKbdMenuBar
2599 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
2601 void MENU_TrackKbdMenuBar( WND
* wndPtr
, UINT32 wParam
, INT32 vkey
)
2603 UINT32 uItem
= NO_SELECTED_ITEM
;
2606 /* find window that has a menu */
2608 while( wndPtr
->dwStyle
& WS_CHILD
&& !(wndPtr
->dwStyle
& WS_SYSMENU
) )
2609 if( !(wndPtr
= wndPtr
->parent
) ) return;
2611 /* check if we have to track a system menu */
2613 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_MINIMIZE
)) ||
2614 !wndPtr
->wIDmenu
|| vkey
== VK_SPACE
)
2616 if( !(wndPtr
->dwStyle
& WS_SYSMENU
) ) return;
2617 hTrackMenu
= wndPtr
->hSysMenu
;
2619 wParam
|= HTSYSMENU
; /* prevent item lookup */
2622 hTrackMenu
= wndPtr
->wIDmenu
;
2624 if (IsMenu32( hTrackMenu
))
2626 MENU_InitTracking( wndPtr
->hwndSelf
, hTrackMenu
);
2628 if( vkey
&& vkey
!= VK_SPACE
)
2630 uItem
= MENU_FindItemByKey( wndPtr
->hwndSelf
, hTrackMenu
,
2631 vkey
, (wParam
& HTSYSMENU
) );
2632 if( uItem
>= (UINT32
)(-2) )
2634 if( uItem
== (UINT32
)(-1) ) MessageBeep32(0);
2641 MENU_SelectItem( wndPtr
->hwndSelf
, hTrackMenu
, uItem
, TRUE
);
2643 if( uItem
== NO_SELECTED_ITEM
)
2644 MENU_MoveSelection( wndPtr
->hwndSelf
, hTrackMenu
, ITEM_NEXT
);
2646 PostMessage16( wndPtr
->hwndSelf
, WM_KEYDOWN
, VK_DOWN
, 0L );
2648 MENU_TrackMenu( hTrackMenu
, TPM_ENTERIDLEEX
| TPM_LEFTALIGN
| TPM_LEFTBUTTON
,
2649 0, 0, wndPtr
->hwndSelf
, NULL
);
2651 SendMessage16( wndPtr
->hwndSelf
, WM_EXITMENULOOP
, 0, 0 );
2657 /**********************************************************************
2658 * TrackPopupMenu16 (USER.416)
2660 BOOL16 WINAPI
TrackPopupMenu16( HMENU16 hMenu
, UINT16 wFlags
, INT16 x
, INT16 y
,
2661 INT16 nReserved
, HWND16 hWnd
, const RECT16
*lpRect
)
2665 CONV_RECT16TO32( lpRect
, &r
);
2666 return TrackPopupMenu32( hMenu
, wFlags
, x
, y
, nReserved
, hWnd
,
2667 lpRect
? &r
: NULL
);
2671 /**********************************************************************
2672 * TrackPopupMenu32 (USER32.549)
2674 BOOL32 WINAPI
TrackPopupMenu32( HMENU32 hMenu
, UINT32 wFlags
, INT32 x
, INT32 y
,
2675 INT32 nReserved
, HWND32 hWnd
, const RECT32
*lpRect
)
2680 SendMessage16( hWnd
, WM_INITMENUPOPUP
, (WPARAM16
)hMenu
, 0);
2681 if (MENU_ShowPopup( hWnd
, hMenu
, 0, x
, y
, 0, 0 ))
2682 ret
= MENU_TrackMenu( hMenu
, wFlags
| TPM_POPUPMENU
, 0, 0, hWnd
, lpRect
);
2687 /**********************************************************************
2688 * TrackPopupMenuEx (USER32.550)
2690 BOOL32 WINAPI
TrackPopupMenuEx( HMENU32 hMenu
, UINT32 wFlags
, INT32 x
, INT32 y
,
2691 HWND32 hWnd
, LPTPMPARAMS lpTpm
)
2693 FIXME(menu
, "not fully implemented\n" );
2694 return TrackPopupMenu32( hMenu
, wFlags
, x
, y
, 0, hWnd
,
2695 lpTpm
? &lpTpm
->rcExclude
: NULL
);
2698 /***********************************************************************
2701 * NOTE: Windows has totally different (and undocumented) popup wndproc.
2703 LRESULT WINAPI
PopupMenuWndProc( HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
2706 WND
* wndPtr
= WIN_FindWndPtr(hwnd
);
2712 CREATESTRUCT32A
*cs
= (CREATESTRUCT32A
*)lParam
;
2713 SetWindowLong32A( hwnd
, 0, (LONG
)cs
->lpCreateParams
);
2717 case WM_MOUSEACTIVATE
: /* We don't want to be activated */
2718 return MA_NOACTIVATE
;
2723 BeginPaint32( hwnd
, &ps
);
2724 MENU_DrawPopupMenu( hwnd
, ps
.hdc
,
2725 (HMENU32
)GetWindowLong32A( hwnd
, 0 ) );
2726 EndPaint32( hwnd
, &ps
);
2734 /* zero out global pointer in case resident popup window
2735 * was somehow destroyed. */
2739 if( hwnd
== pTopPopupWnd
->hwndSelf
)
2741 ERR(menu
, "resident popup destroyed!\n");
2743 pTopPopupWnd
= NULL
;
2755 if( !(*(HMENU32
*)wndPtr
->wExtra
) )
2756 ERR(menu
,"no menu to display\n");
2759 *(HMENU32
*)wndPtr
->wExtra
= 0;
2762 case MM_SETMENUHANDLE
:
2764 *(HMENU32
*)wndPtr
->wExtra
= (HMENU32
)wParam
;
2767 case MM_GETMENUHANDLE
:
2769 return *(HMENU32
*)wndPtr
->wExtra
;
2772 return DefWindowProc32A( hwnd
, message
, wParam
, lParam
);
2778 /***********************************************************************
2779 * MENU_GetMenuBarHeight
2781 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
2783 UINT32
MENU_GetMenuBarHeight( HWND32 hwnd
, UINT32 menubarWidth
,
2784 INT32 orgX
, INT32 orgY
)
2791 TRACE(menu
, "HWND 0x%x, width %d, "
2792 "at (%d, %d).\n", hwnd
, menubarWidth
, orgX
, orgY
);
2794 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
2795 if (!(lppop
= (LPPOPUPMENU
)USER_HEAP_LIN_ADDR((HMENU16
)wndPtr
->wIDmenu
)))
2797 hdc
= GetDCEx32( hwnd
, 0, DCX_CACHE
| DCX_WINDOW
);
2798 SetRect32(&rectBar
, orgX
, orgY
, orgX
+menubarWidth
, orgY
+SYSMETRICS_CYMENU
);
2799 MENU_MenuBarCalcSize( hdc
, &rectBar
, lppop
, hwnd
);
2800 ReleaseDC32( hwnd
, hdc
);
2801 return lppop
->Height
;
2805 /*******************************************************************
2806 * ChangeMenu16 (USER.153)
2808 BOOL16 WINAPI
ChangeMenu16( HMENU16 hMenu
, UINT16 pos
, SEGPTR data
,
2809 UINT16 id
, UINT16 flags
)
2811 TRACE(menu
,"menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
2812 hMenu
, pos
, (DWORD
)data
, id
, flags
);
2813 if (flags
& MF_APPEND
) return AppendMenu16( hMenu
, flags
& ~MF_APPEND
,
2816 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
2817 /* for MF_DELETE. We should check the parameters for all others */
2818 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
2820 if (flags
& MF_DELETE
) return DeleteMenu16(hMenu
, pos
, flags
& ~MF_DELETE
);
2821 if (flags
& MF_CHANGE
) return ModifyMenu16(hMenu
, pos
, flags
& ~MF_CHANGE
,
2823 if (flags
& MF_REMOVE
) return RemoveMenu16(hMenu
,
2824 flags
& MF_BYPOSITION
? pos
: id
,
2825 flags
& ~MF_REMOVE
);
2826 /* Default: MF_INSERT */
2827 return InsertMenu16( hMenu
, pos
, flags
, id
, data
);
2831 /*******************************************************************
2832 * ChangeMenu32A (USER32.23)
2834 BOOL32 WINAPI
ChangeMenu32A( HMENU32 hMenu
, UINT32 pos
, LPCSTR data
,
2835 UINT32 id
, UINT32 flags
)
2837 TRACE(menu
,"menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
2838 hMenu
, pos
, (DWORD
)data
, id
, flags
);
2839 if (flags
& MF_APPEND
) return AppendMenu32A( hMenu
, flags
& ~MF_APPEND
,
2841 if (flags
& MF_DELETE
) return DeleteMenu32(hMenu
, pos
, flags
& ~MF_DELETE
);
2842 if (flags
& MF_CHANGE
) return ModifyMenu32A(hMenu
, pos
, flags
& ~MF_CHANGE
,
2844 if (flags
& MF_REMOVE
) return RemoveMenu32( hMenu
,
2845 flags
& MF_BYPOSITION
? pos
: id
,
2846 flags
& ~MF_REMOVE
);
2847 /* Default: MF_INSERT */
2848 return InsertMenu32A( hMenu
, pos
, flags
, id
, data
);
2852 /*******************************************************************
2853 * ChangeMenu32W (USER32.24)
2855 BOOL32 WINAPI
ChangeMenu32W( HMENU32 hMenu
, UINT32 pos
, LPCWSTR data
,
2856 UINT32 id
, UINT32 flags
)
2858 TRACE(menu
,"menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
2859 hMenu
, pos
, (DWORD
)data
, id
, flags
);
2860 if (flags
& MF_APPEND
) return AppendMenu32W( hMenu
, flags
& ~MF_APPEND
,
2862 if (flags
& MF_DELETE
) return DeleteMenu32(hMenu
, pos
, flags
& ~MF_DELETE
);
2863 if (flags
& MF_CHANGE
) return ModifyMenu32W(hMenu
, pos
, flags
& ~MF_CHANGE
,
2865 if (flags
& MF_REMOVE
) return RemoveMenu32( hMenu
,
2866 flags
& MF_BYPOSITION
? pos
: id
,
2867 flags
& ~MF_REMOVE
);
2868 /* Default: MF_INSERT */
2869 return InsertMenu32W( hMenu
, pos
, flags
, id
, data
);
2873 /*******************************************************************
2874 * CheckMenuItem16 (USER.154)
2876 BOOL16 WINAPI
CheckMenuItem16( HMENU16 hMenu
, UINT16 id
, UINT16 flags
)
2878 return (BOOL16
)CheckMenuItem32( hMenu
, id
, flags
);
2882 /*******************************************************************
2883 * CheckMenuItem32 (USER32.46)
2885 DWORD WINAPI
CheckMenuItem32( HMENU32 hMenu
, UINT32 id
, UINT32 flags
)
2890 TRACE(menu
,"%04x %04x %04x\n", hMenu
, id
, flags
);
2891 if (!(item
= MENU_FindItem( &hMenu
, &id
, flags
))) return -1;
2892 ret
= item
->fState
& MF_CHECKED
;
2893 if (flags
& MF_CHECKED
) item
->fState
|= MF_CHECKED
;
2894 else item
->fState
&= ~MF_CHECKED
;
2899 /**********************************************************************
2900 * EnableMenuItem16 (USER.155)
2902 UINT16 WINAPI
EnableMenuItem16( HMENU16 hMenu
, UINT16 wItemID
, UINT16 wFlags
)
2904 return EnableMenuItem32( hMenu
, wItemID
, wFlags
);
2908 /**********************************************************************
2909 * EnableMenuItem32 (USER32.170)
2911 UINT32 WINAPI
EnableMenuItem32( HMENU32 hMenu
, UINT32 wItemID
, UINT32 wFlags
)
2916 TRACE(menu
,"(%04x, %04X, %04X) !\n",
2917 hMenu
, wItemID
, wFlags
);
2919 if (!(item
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
)))
2922 oldflags
= item
->fState
& (MF_GRAYED
| MF_DISABLED
);
2923 item
->fState
^= (oldflags
^ wFlags
) & (MF_GRAYED
| MF_DISABLED
);
2928 /*******************************************************************
2929 * GetMenuString16 (USER.161)
2931 INT16 WINAPI
GetMenuString16( HMENU16 hMenu
, UINT16 wItemID
,
2932 LPSTR str
, INT16 nMaxSiz
, UINT16 wFlags
)
2934 return GetMenuString32A( hMenu
, wItemID
, str
, nMaxSiz
, wFlags
);
2938 /*******************************************************************
2939 * GetMenuString32A (USER32.268)
2941 INT32 WINAPI
GetMenuString32A( HMENU32 hMenu
, UINT32 wItemID
,
2942 LPSTR str
, INT32 nMaxSiz
, UINT32 wFlags
)
2946 TRACE(menu
, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
2947 hMenu
, wItemID
, str
, nMaxSiz
, wFlags
);
2948 if (!str
|| !nMaxSiz
) return 0;
2950 if (!(item
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
))) return 0;
2951 if (!IS_STRING_ITEM(item
->fType
)) return 0;
2952 lstrcpyn32A( str
, item
->text
, nMaxSiz
);
2953 TRACE(menu
, "returning '%s'\n", str
);
2958 /*******************************************************************
2959 * GetMenuString32W (USER32.269)
2961 INT32 WINAPI
GetMenuString32W( HMENU32 hMenu
, UINT32 wItemID
,
2962 LPWSTR str
, INT32 nMaxSiz
, UINT32 wFlags
)
2966 TRACE(menu
, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
2967 hMenu
, wItemID
, str
, nMaxSiz
, wFlags
);
2968 if (!str
|| !nMaxSiz
) return 0;
2970 if (!(item
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
))) return 0;
2971 if (!IS_STRING_ITEM(item
->fType
)) return 0;
2972 lstrcpynAtoW( str
, item
->text
, nMaxSiz
);
2973 return lstrlen32W(str
);
2977 /**********************************************************************
2978 * HiliteMenuItem16 (USER.162)
2980 BOOL16 WINAPI
HiliteMenuItem16( HWND16 hWnd
, HMENU16 hMenu
, UINT16 wItemID
,
2983 return HiliteMenuItem32( hWnd
, hMenu
, wItemID
, wHilite
);
2987 /**********************************************************************
2988 * HiliteMenuItem32 (USER32.318)
2990 BOOL32 WINAPI
HiliteMenuItem32( HWND32 hWnd
, HMENU32 hMenu
, UINT32 wItemID
,
2994 TRACE(menu
,"(%04x, %04x, %04x, %04x);\n",
2995 hWnd
, hMenu
, wItemID
, wHilite
);
2996 if (!MENU_FindItem( &hMenu
, &wItemID
, wHilite
)) return FALSE
;
2997 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return FALSE
;
2998 if (menu
->FocusedItem
== wItemID
) return TRUE
;
2999 MENU_HideSubPopups( hWnd
, hMenu
, FALSE
);
3000 MENU_SelectItem( hWnd
, hMenu
, wItemID
, TRUE
);
3005 /**********************************************************************
3006 * GetMenuState16 (USER.250)
3008 UINT16 WINAPI
GetMenuState16( HMENU16 hMenu
, UINT16 wItemID
, UINT16 wFlags
)
3010 return GetMenuState32( hMenu
, wItemID
, wFlags
);
3014 /**********************************************************************
3015 * GetMenuState32 (USER32.267)
3017 UINT32 WINAPI
GetMenuState32( HMENU32 hMenu
, UINT32 wItemID
, UINT32 wFlags
)
3020 TRACE(menu
,"(%04x, %04x, %04x);\n",
3021 hMenu
, wItemID
, wFlags
);
3022 if (!(item
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
))) return -1;
3023 debug_print_menuitem (" item: ", item
, "");
3024 if (item
->fType
& MF_POPUP
)
3026 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( item
->hSubMenu
);
3027 if (!menu
) return -1;
3028 else return (menu
->nItems
<< 8) | ((item
->fState
|item
->fType
) & 0xff);
3032 /* We used to (from way back then) mask the result to 0xff. */
3033 /* I don't know why and it seems wrong as the documented */
3034 /* return flag MF_SEPARATOR is outside that mask. */
3035 return (item
->fType
| item
->fState
);
3040 /**********************************************************************
3041 * GetMenuItemCount16 (USER.263)
3043 INT16 WINAPI
GetMenuItemCount16( HMENU16 hMenu
)
3045 LPPOPUPMENU menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
);
3046 if (!IS_A_MENU(menu
)) return -1;
3047 TRACE(menu
,"(%04x) returning %d\n",
3048 hMenu
, menu
->nItems
);
3049 return menu
->nItems
;
3053 /**********************************************************************
3054 * GetMenuItemCount32 (USER32.262)
3056 INT32 WINAPI
GetMenuItemCount32( HMENU32 hMenu
)
3058 LPPOPUPMENU menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
);
3059 if (!IS_A_MENU(menu
)) return -1;
3060 TRACE(menu
,"(%04x) returning %d\n",
3061 hMenu
, menu
->nItems
);
3062 return menu
->nItems
;
3066 /**********************************************************************
3067 * GetMenuItemID16 (USER.264)
3069 UINT16 WINAPI
GetMenuItemID16( HMENU16 hMenu
, INT16 nPos
)
3073 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return -1;
3074 if ((nPos
< 0) || ((UINT16
) nPos
>= menu
->nItems
)) return -1;
3075 if (menu
->items
[nPos
].fType
& MF_POPUP
) return -1;
3076 return menu
->items
[nPos
].wID
;
3080 /**********************************************************************
3081 * GetMenuItemID32 (USER32.263)
3083 UINT32 WINAPI
GetMenuItemID32( HMENU32 hMenu
, INT32 nPos
)
3087 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return -1;
3088 if ((nPos
< 0) || (nPos
>= menu
->nItems
)) return -1;
3089 if (menu
->items
[nPos
].fType
& MF_POPUP
) return -1;
3090 return menu
->items
[nPos
].wID
;
3094 /*******************************************************************
3095 * InsertMenu16 (USER.410)
3097 BOOL16 WINAPI
InsertMenu16( HMENU16 hMenu
, UINT16 pos
, UINT16 flags
,
3098 UINT16 id
, SEGPTR data
)
3100 UINT32 pos32
= (UINT32
)pos
;
3101 if ((pos
== (UINT16
)-1) && (flags
& MF_BYPOSITION
)) pos32
= (UINT32
)-1;
3102 if (IS_STRING_ITEM(flags
) && data
)
3103 return InsertMenu32A( hMenu
, pos32
, flags
, id
,
3104 (LPSTR
)PTR_SEG_TO_LIN(data
) );
3105 return InsertMenu32A( hMenu
, pos32
, flags
, id
, (LPSTR
)data
);
3109 /*******************************************************************
3110 * InsertMenu32A (USER32.322)
3112 BOOL32 WINAPI
InsertMenu32A( HMENU32 hMenu
, UINT32 pos
, UINT32 flags
,
3113 UINT32 id
, LPCSTR str
)
3117 if (IS_STRING_ITEM(flags
) && str
)
3118 TRACE(menu
, "hMenu %04x, pos %d, flags %08x, "
3119 "id %04x, str '%s'\n",
3120 hMenu
, pos
, flags
, id
, str
);
3121 else TRACE(menu
, "hMenu %04x, pos %d, flags %08x, "
3122 "id %04x, str %08lx (not a string)\n",
3123 hMenu
, pos
, flags
, id
, (DWORD
)str
);
3125 if (!(item
= MENU_InsertItem( hMenu
, pos
, flags
))) return FALSE
;
3127 if (!(MENU_SetItemData( item
, flags
, id
, str
)))
3129 RemoveMenu32( hMenu
, pos
, flags
);
3133 if (flags
& MF_POPUP
) /* Set the MF_POPUP flag on the popup-menu */
3134 ((POPUPMENU
*)USER_HEAP_LIN_ADDR((HMENU16
)id
))->wFlags
|= MF_POPUP
;
3136 item
->hCheckBit
= item
->hUnCheckBit
= 0;
3141 /*******************************************************************
3142 * InsertMenu32W (USER32.325)
3144 BOOL32 WINAPI
InsertMenu32W( HMENU32 hMenu
, UINT32 pos
, UINT32 flags
,
3145 UINT32 id
, LPCWSTR str
)
3149 if (IS_STRING_ITEM(flags
) && str
)
3151 LPSTR newstr
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
3152 ret
= InsertMenu32A( hMenu
, pos
, flags
, id
, newstr
);
3153 HeapFree( GetProcessHeap(), 0, newstr
);
3156 else return InsertMenu32A( hMenu
, pos
, flags
, id
, (LPCSTR
)str
);
3160 /*******************************************************************
3161 * AppendMenu16 (USER.411)
3163 BOOL16 WINAPI
AppendMenu16(HMENU16 hMenu
, UINT16 flags
, UINT16 id
, SEGPTR data
)
3165 return InsertMenu16( hMenu
, -1, flags
| MF_BYPOSITION
, id
, data
);
3169 /*******************************************************************
3170 * AppendMenu32A (USER32.5)
3172 BOOL32 WINAPI
AppendMenu32A( HMENU32 hMenu
, UINT32 flags
,
3173 UINT32 id
, LPCSTR data
)
3175 return InsertMenu32A( hMenu
, -1, flags
| MF_BYPOSITION
, id
, data
);
3179 /*******************************************************************
3180 * AppendMenu32W (USER32.6)
3182 BOOL32 WINAPI
AppendMenu32W( HMENU32 hMenu
, UINT32 flags
,
3183 UINT32 id
, LPCWSTR data
)
3185 return InsertMenu32W( hMenu
, -1, flags
| MF_BYPOSITION
, id
, data
);
3189 /**********************************************************************
3190 * RemoveMenu16 (USER.412)
3192 BOOL16 WINAPI
RemoveMenu16( HMENU16 hMenu
, UINT16 nPos
, UINT16 wFlags
)
3194 return RemoveMenu32( hMenu
, nPos
, wFlags
);
3198 /**********************************************************************
3199 * RemoveMenu32 (USER32.441)
3201 BOOL32 WINAPI
RemoveMenu32( HMENU32 hMenu
, UINT32 nPos
, UINT32 wFlags
)
3206 TRACE(menu
,"(%04x, %04x, %04x)\n",hMenu
, nPos
, wFlags
);
3207 if (!(item
= MENU_FindItem( &hMenu
, &nPos
, wFlags
))) return FALSE
;
3208 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return FALSE
;
3212 MENU_FreeItemData( item
);
3214 if (--menu
->nItems
== 0)
3216 HeapFree( SystemHeap
, 0, menu
->items
);
3221 while(nPos
< menu
->nItems
)
3227 menu
->items
= HeapReAlloc( SystemHeap
, 0, menu
->items
,
3228 menu
->nItems
* sizeof(MENUITEM
) );
3234 /**********************************************************************
3235 * DeleteMenu16 (USER.413)
3237 BOOL16 WINAPI
DeleteMenu16( HMENU16 hMenu
, UINT16 nPos
, UINT16 wFlags
)
3239 return DeleteMenu32( hMenu
, nPos
, wFlags
);
3243 /**********************************************************************
3244 * DeleteMenu32 (USER32.129)
3246 BOOL32 WINAPI
DeleteMenu32( HMENU32 hMenu
, UINT32 nPos
, UINT32 wFlags
)
3248 MENUITEM
*item
= MENU_FindItem( &hMenu
, &nPos
, wFlags
);
3249 if (!item
) return FALSE
;
3250 if (item
->fType
& MF_POPUP
) DestroyMenu32( item
->hSubMenu
);
3251 /* nPos is now the position of the item */
3252 RemoveMenu32( hMenu
, nPos
, wFlags
| MF_BYPOSITION
);
3257 /*******************************************************************
3258 * ModifyMenu16 (USER.414)
3260 BOOL16 WINAPI
ModifyMenu16( HMENU16 hMenu
, UINT16 pos
, UINT16 flags
,
3261 UINT16 id
, SEGPTR data
)
3263 if (IS_STRING_ITEM(flags
))
3264 return ModifyMenu32A( hMenu
, pos
, flags
, id
,
3265 (LPSTR
)PTR_SEG_TO_LIN(data
) );
3266 return ModifyMenu32A( hMenu
, pos
, flags
, id
, (LPSTR
)data
);
3270 /*******************************************************************
3271 * ModifyMenu32A (USER32.397)
3273 BOOL32 WINAPI
ModifyMenu32A( HMENU32 hMenu
, UINT32 pos
, UINT32 flags
,
3274 UINT32 id
, LPCSTR str
)
3278 if (IS_STRING_ITEM(flags
))
3280 TRACE(menu
, "%04x %d %04x %04x '%s'\n",
3281 hMenu
, pos
, flags
, id
, str
? str
: "#NULL#" );
3282 if (!str
) return FALSE
;
3286 TRACE(menu
, "%04x %d %04x %04x %08lx\n",
3287 hMenu
, pos
, flags
, id
, (DWORD
)str
);
3290 if (!(item
= MENU_FindItem( &hMenu
, &pos
, flags
))) return FALSE
;
3291 return MENU_SetItemData( item
, flags
, id
, str
);
3295 /*******************************************************************
3296 * ModifyMenu32W (USER32.398)
3298 BOOL32 WINAPI
ModifyMenu32W( HMENU32 hMenu
, UINT32 pos
, UINT32 flags
,
3299 UINT32 id
, LPCWSTR str
)
3303 if (IS_STRING_ITEM(flags
) && str
)
3305 LPSTR newstr
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
3306 ret
= ModifyMenu32A( hMenu
, pos
, flags
, id
, newstr
);
3307 HeapFree( GetProcessHeap(), 0, newstr
);
3310 else return ModifyMenu32A( hMenu
, pos
, flags
, id
, (LPCSTR
)str
);
3314 /**********************************************************************
3315 * CreatePopupMenu16 (USER.415)
3317 HMENU16 WINAPI
CreatePopupMenu16(void)
3319 return CreatePopupMenu32();
3323 /**********************************************************************
3324 * CreatePopupMenu32 (USER32.82)
3326 HMENU32 WINAPI
CreatePopupMenu32(void)
3331 if (!(hmenu
= CreateMenu32())) return 0;
3332 menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR( hmenu
);
3333 menu
->wFlags
|= MF_POPUP
;
3338 /**********************************************************************
3339 * GetMenuCheckMarkDimensions (USER.417) (USER32.258)
3341 DWORD WINAPI
GetMenuCheckMarkDimensions(void)
3343 return MAKELONG( check_bitmap_width
, check_bitmap_height
);
3347 /**********************************************************************
3348 * SetMenuItemBitmaps16 (USER.418)
3350 BOOL16 WINAPI
SetMenuItemBitmaps16( HMENU16 hMenu
, UINT16 nPos
, UINT16 wFlags
,
3351 HBITMAP16 hNewUnCheck
, HBITMAP16 hNewCheck
)
3353 return SetMenuItemBitmaps32( hMenu
, nPos
, wFlags
, hNewUnCheck
, hNewCheck
);
3357 /**********************************************************************
3358 * SetMenuItemBitmaps32 (USER32.490)
3360 BOOL32 WINAPI
SetMenuItemBitmaps32( HMENU32 hMenu
, UINT32 nPos
, UINT32 wFlags
,
3361 HBITMAP32 hNewUnCheck
, HBITMAP32 hNewCheck
)
3364 TRACE(menu
,"(%04x, %04x, %04x, %04x, %04x)\n",
3365 hMenu
, nPos
, wFlags
, hNewCheck
, hNewUnCheck
);
3366 if (!(item
= MENU_FindItem( &hMenu
, &nPos
, wFlags
))) return FALSE
;
3368 if (!hNewCheck
&& !hNewUnCheck
)
3370 item
->fState
&= ~MF_USECHECKBITMAPS
;
3372 else /* Install new bitmaps */
3374 item
->hCheckBit
= hNewCheck
;
3375 item
->hUnCheckBit
= hNewUnCheck
;
3376 item
->fState
|= MF_USECHECKBITMAPS
;
3382 /**********************************************************************
3383 * CreateMenu16 (USER.151)
3385 HMENU16 WINAPI
CreateMenu16(void)
3387 return CreateMenu32();
3391 /**********************************************************************
3392 * CreateMenu32 (USER32.81)
3394 HMENU32 WINAPI
CreateMenu32(void)
3398 if (!(hMenu
= USER_HEAP_ALLOC( sizeof(POPUPMENU
) ))) return 0;
3399 menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
);
3401 menu
->wMagic
= MENU_MAGIC
;
3408 menu
->FocusedItem
= NO_SELECTED_ITEM
;
3409 TRACE(menu
, "return %04x\n", hMenu
);
3414 /**********************************************************************
3415 * DestroyMenu16 (USER.152)
3417 BOOL16 WINAPI
DestroyMenu16( HMENU16 hMenu
)
3419 return DestroyMenu32( hMenu
);
3423 /**********************************************************************
3424 * DestroyMenu32 (USER32.134)
3426 BOOL32 WINAPI
DestroyMenu32( HMENU32 hMenu
)
3428 TRACE(menu
,"(%04x)\n", hMenu
);
3430 /* Silently ignore attempts to destroy default system popup */
3432 if (hMenu
&& hMenu
!= MENU_DefSysPopup
)
3434 LPPOPUPMENU lppop
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
);
3436 if( pTopPopupWnd
&& (hMenu
== *(HMENU32
*)pTopPopupWnd
->wExtra
) )
3437 *(UINT32
*)pTopPopupWnd
->wExtra
= 0;
3439 if (IS_A_MENU( lppop
))
3441 lppop
->wMagic
= 0; /* Mark it as destroyed */
3443 if ((lppop
->wFlags
& MF_POPUP
) && lppop
->hWnd
&&
3444 (!pTopPopupWnd
|| (lppop
->hWnd
!= pTopPopupWnd
->hwndSelf
)))
3445 DestroyWindow32( lppop
->hWnd
);
3447 if (lppop
->items
) /* recursively destroy submenus */
3450 MENUITEM
*item
= lppop
->items
;
3451 for (i
= lppop
->nItems
; i
> 0; i
--, item
++)
3453 if (item
->fType
& MF_POPUP
) DestroyMenu32(item
->hSubMenu
);
3454 MENU_FreeItemData( item
);
3456 HeapFree( SystemHeap
, 0, lppop
->items
);
3458 USER_HEAP_FREE( hMenu
);
3462 return (hMenu
!= MENU_DefSysPopup
);
3466 /**********************************************************************
3467 * GetSystemMenu16 (USER.156)
3469 HMENU16 WINAPI
GetSystemMenu16( HWND16 hWnd
, BOOL16 bRevert
)
3471 return GetSystemMenu32( hWnd
, bRevert
);
3475 /**********************************************************************
3476 * GetSystemMenu32 (USER32.291)
3478 HMENU32 WINAPI
GetSystemMenu32( HWND32 hWnd
, BOOL32 bRevert
)
3480 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
3484 if( wndPtr
->hSysMenu
)
3488 DestroyMenu32(wndPtr
->hSysMenu
);
3489 wndPtr
->hSysMenu
= 0;
3493 POPUPMENU
*menu
= (POPUPMENU
*)
3494 USER_HEAP_LIN_ADDR(wndPtr
->hSysMenu
);
3495 if( menu
->items
[0].hSubMenu
== MENU_DefSysPopup
)
3496 menu
->items
[0].hSubMenu
= MENU_CopySysPopup();
3500 if(!wndPtr
->hSysMenu
&& (wndPtr
->dwStyle
& WS_SYSMENU
) )
3501 wndPtr
->hSysMenu
= MENU_GetSysMenu( hWnd
, (HMENU32
)(-1) );
3503 if( wndPtr
->hSysMenu
)
3504 return GetSubMenu16(wndPtr
->hSysMenu
, 0);
3510 /*******************************************************************
3511 * SetSystemMenu16 (USER.280)
3513 BOOL16 WINAPI
SetSystemMenu16( HWND16 hwnd
, HMENU16 hMenu
)
3515 return SetSystemMenu32( hwnd
, hMenu
);
3519 /*******************************************************************
3520 * SetSystemMenu32 (USER32.508)
3522 BOOL32 WINAPI
SetSystemMenu32( HWND32 hwnd
, HMENU32 hMenu
)
3524 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3528 if (wndPtr
->hSysMenu
) DestroyMenu32( wndPtr
->hSysMenu
);
3529 wndPtr
->hSysMenu
= MENU_GetSysMenu( hwnd
, hMenu
);
3536 /**********************************************************************
3537 * GetMenu16 (USER.157)
3539 HMENU16 WINAPI
GetMenu16( HWND16 hWnd
)
3541 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
3542 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
))
3543 return (HMENU16
)wndPtr
->wIDmenu
;
3548 /**********************************************************************
3549 * GetMenu32 (USER32.257)
3551 HMENU32 WINAPI
GetMenu32( HWND32 hWnd
)
3553 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
3554 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
))
3555 return (HMENU32
)wndPtr
->wIDmenu
;
3560 /**********************************************************************
3561 * SetMenu16 (USER.158)
3563 BOOL16 WINAPI
SetMenu16( HWND16 hWnd
, HMENU16 hMenu
)
3565 return SetMenu32( hWnd
, hMenu
);
3569 /**********************************************************************
3570 * SetMenu32 (USER32.487)
3572 BOOL32 WINAPI
SetMenu32( HWND32 hWnd
, HMENU32 hMenu
)
3574 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
3576 TRACE(menu
,"(%04x, %04x);\n", hWnd
, hMenu
);
3578 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
))
3580 if (GetCapture32() == hWnd
) ReleaseCapture();
3582 wndPtr
->wIDmenu
= (UINT32
)hMenu
;
3587 if (!(lpmenu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return FALSE
;
3588 lpmenu
->hWnd
= hWnd
;
3589 lpmenu
->wFlags
&= ~MF_POPUP
; /* Can't be a popup */
3590 lpmenu
->Height
= 0; /* Make sure we recalculate the size */
3592 if (IsWindowVisible32(hWnd
))
3593 SetWindowPos32( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3594 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3602 /**********************************************************************
3603 * GetSubMenu16 (USER.159)
3605 HMENU16 WINAPI
GetSubMenu16( HMENU16 hMenu
, INT16 nPos
)
3607 return GetSubMenu32( hMenu
, nPos
);
3611 /**********************************************************************
3612 * GetSubMenu32 (USER32.288)
3614 HMENU32 WINAPI
GetSubMenu32( HMENU32 hMenu
, INT32 nPos
)
3618 if (!(lppop
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hMenu
))) return 0;
3619 if ((UINT32
)nPos
>= lppop
->nItems
) return 0;
3620 if (!(lppop
->items
[nPos
].fType
& MF_POPUP
)) return 0;
3621 return lppop
->items
[nPos
].hSubMenu
;
3625 /**********************************************************************
3626 * DrawMenuBar16 (USER.160)
3628 void WINAPI
DrawMenuBar16( HWND16 hWnd
)
3630 DrawMenuBar32( hWnd
);
3634 /**********************************************************************
3635 * DrawMenuBar32 (USER32.161)
3637 BOOL32 WINAPI
DrawMenuBar32( HWND32 hWnd
)
3640 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
3641 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && wndPtr
->wIDmenu
)
3643 lppop
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR((HMENU16
)wndPtr
->wIDmenu
);
3644 if (lppop
== NULL
) return FALSE
;
3646 lppop
->Height
= 0; /* Make sure we call MENU_MenuBarCalcSize */
3647 SetWindowPos32( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3648 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3655 /***********************************************************************
3656 * EndMenu (USER.187) (USER32.175)
3658 void WINAPI
EndMenu(void)
3664 /***********************************************************************
3665 * LookupMenuHandle (USER.217)
3667 HMENU16 WINAPI
LookupMenuHandle( HMENU16 hmenu
, INT16 id
)
3669 HMENU32 hmenu32
= hmenu
;
3671 if (!MENU_FindItem( &hmenu32
, &id32
, MF_BYCOMMAND
)) return 0;
3672 else return hmenu32
;
3676 /**********************************************************************
3677 * LoadMenu16 (USER.150)
3679 HMENU16 WINAPI
LoadMenu16( HINSTANCE16 instance
, SEGPTR name
)
3687 char *str
= (char *)PTR_SEG_TO_LIN( name
);
3688 TRACE(menu
, "(%04x,'%s')\n", instance
, str
);
3689 if (str
[0] == '#') name
= (SEGPTR
)atoi( str
+ 1 );
3692 TRACE(resource
,"(%04x,%04x)\n",instance
,LOWORD(name
));
3694 if (!name
) return 0;
3696 /* check for Win32 module */
3697 if (HIWORD(instance
))
3698 return LoadMenu32A(instance
,PTR_SEG_TO_LIN(name
));
3699 instance
= GetExePtr( instance
);
3701 if (!(hRsrc
= FindResource16( instance
, name
, RT_MENU16
))) return 0;
3702 if (!(handle
= LoadResource16( instance
, hRsrc
))) return 0;
3703 hMenu
= LoadMenuIndirect16(LockResource16(handle
));
3704 FreeResource16( handle
);
3709 /*****************************************************************
3710 * LoadMenu32A (USER32.370)
3712 HMENU32 WINAPI
LoadMenu32A( HINSTANCE32 instance
, LPCSTR name
)
3714 HRSRC32 hrsrc
= FindResource32A( instance
, name
, RT_MENU32A
);
3715 if (!hrsrc
) return 0;
3716 return LoadMenuIndirect32A( (LPCVOID
)LoadResource32( instance
, hrsrc
));
3720 /*****************************************************************
3721 * LoadMenu32W (USER32.373)
3723 HMENU32 WINAPI
LoadMenu32W( HINSTANCE32 instance
, LPCWSTR name
)
3725 HRSRC32 hrsrc
= FindResource32W( instance
, name
, RT_MENU32W
);
3726 if (!hrsrc
) return 0;
3727 return LoadMenuIndirect32W( (LPCVOID
)LoadResource32( instance
, hrsrc
));
3731 /**********************************************************************
3732 * LoadMenuIndirect16 (USER.220)
3734 HMENU16 WINAPI
LoadMenuIndirect16( LPCVOID
template )
3737 WORD version
, offset
;
3738 LPCSTR p
= (LPCSTR
)template;
3740 TRACE(menu
,"(%p)\n", template );
3741 version
= GET_WORD(p
);
3745 WARN(menu
, "version must be 0 for Win16\n" );
3748 offset
= GET_WORD(p
);
3749 p
+= sizeof(WORD
) + offset
;
3750 if (!(hMenu
= CreateMenu32())) return 0;
3751 if (!MENU_ParseResource( p
, hMenu
, FALSE
))
3753 DestroyMenu32( hMenu
);
3760 /**********************************************************************
3761 * LoadMenuIndirect32A (USER32.371)
3763 HMENU32 WINAPI
LoadMenuIndirect32A( LPCVOID
template )
3766 WORD version
, offset
;
3767 LPCSTR p
= (LPCSTR
)template;
3769 TRACE(menu
,"%p\n", template );
3770 version
= GET_WORD(p
);
3775 offset
= GET_WORD(p
);
3776 p
+= sizeof(WORD
) + offset
;
3777 if (!(hMenu
= CreateMenu32())) return 0;
3778 if (!MENU_ParseResource( p
, hMenu
, TRUE
))
3780 DestroyMenu32( hMenu
);
3785 offset
= GET_WORD(p
);
3786 p
+= sizeof(WORD
) + offset
;
3787 if (!(hMenu
= CreateMenu32())) return 0;
3788 if (!MENUEX_ParseResource( p
, hMenu
))
3790 DestroyMenu32( hMenu
);
3795 ERR(menu
, "version %d not supported.\n", version
);
3801 /**********************************************************************
3802 * LoadMenuIndirect32W (USER32.372)
3804 HMENU32 WINAPI
LoadMenuIndirect32W( LPCVOID
template )
3806 /* FIXME: is there anything different between A and W? */
3807 return LoadMenuIndirect32A( template );
3811 /**********************************************************************
3812 * IsMenu16 (USER.358)
3814 BOOL16 WINAPI
IsMenu16( HMENU16 hmenu
)
3816 LPPOPUPMENU menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hmenu
);
3817 return IS_A_MENU(menu
);
3821 /**********************************************************************
3822 * IsMenu32 (USER32.346)
3824 BOOL32 WINAPI
IsMenu32(HMENU32 hmenu
)
3826 LPPOPUPMENU menu
= (LPPOPUPMENU
) USER_HEAP_LIN_ADDR(hmenu
);
3827 return IS_A_MENU(menu
);
3830 /**********************************************************************
3831 * GetMenuItemInfo32_common
3834 static BOOL32
GetMenuItemInfo32_common ( HMENU32 hmenu
, UINT32 item
,
3836 LPMENUITEMINFO32A lpmii
,
3839 MENUITEM
*menu
= MENU_FindItem (&hmenu
, &item
, bypos
? MF_BYPOSITION
: 0);
3840 debug_print_menuitem("GetMenuItemInfo32_common: ", menu
, "");
3844 if (lpmii
->fMask
& MIIM_TYPE
) {
3845 lpmii
->fType
= menu
->fType
;
3846 switch (MENU_ITEM_TYPE(menu
->fType
)) {
3848 if (menu
->text
&& lpmii
->dwTypeData
&& lpmii
->cch
) {
3850 lstrcpynAtoW((LPWSTR
) lpmii
->dwTypeData
,
3854 lstrcpyn32A(lpmii
->dwTypeData
,
3861 lpmii
->dwTypeData
= menu
->text
;
3867 if (lpmii
->fMask
& MIIM_STATE
)
3868 lpmii
->fState
= menu
->fState
;
3870 if (lpmii
->fMask
& MIIM_ID
)
3871 lpmii
->wID
= menu
->wID
;
3873 if (lpmii
->fMask
& MIIM_SUBMENU
)
3874 lpmii
->hSubMenu
= menu
->hSubMenu
;
3876 if (lpmii
->fMask
& MIIM_CHECKMARKS
) {
3877 lpmii
->hbmpChecked
= menu
->hCheckBit
;
3878 lpmii
->hbmpUnchecked
= menu
->hUnCheckBit
;
3880 if (lpmii
->fMask
& MIIM_DATA
)
3881 lpmii
->dwItemData
= menu
->dwItemData
;
3886 /**********************************************************************
3887 * GetMenuItemInfo32A (USER32.264)
3889 BOOL32 WINAPI
GetMenuItemInfo32A( HMENU32 hmenu
, UINT32 item
, BOOL32 bypos
,
3890 LPMENUITEMINFO32A lpmii
)
3892 return GetMenuItemInfo32_common (hmenu
, item
, bypos
, lpmii
, FALSE
);
3895 /**********************************************************************
3896 * GetMenuItemInfo32W (USER32.265)
3898 BOOL32 WINAPI
GetMenuItemInfo32W( HMENU32 hmenu
, UINT32 item
, BOOL32 bypos
,
3899 LPMENUITEMINFO32W lpmii
)
3901 return GetMenuItemInfo32_common (hmenu
, item
, bypos
,
3902 (LPMENUITEMINFO32A
)lpmii
, TRUE
);
3905 /**********************************************************************
3906 * SetMenuItemInfo32_common
3909 static BOOL32
SetMenuItemInfo32_common(MENUITEM
* menu
,
3910 const MENUITEMINFO32A
*lpmii
,
3913 if (!menu
) return FALSE
;
3915 if (lpmii
->fMask
& MIIM_TYPE
) {
3916 /* Get rid of old string. */
3917 if (IS_STRING_ITEM(menu
->fType
) && menu
->text
)
3918 HeapFree(SystemHeap
, 0, menu
->text
);
3920 menu
->fType
= lpmii
->fType
;
3921 menu
->text
= lpmii
->dwTypeData
;
3922 if (IS_STRING_ITEM(menu
->fType
) && menu
->text
) {
3925 ? HEAP_strdupWtoA(SystemHeap
, 0,
3926 (LPWSTR
) lpmii
->dwTypeData
)
3927 : HEAP_strdupA(SystemHeap
, 0, lpmii
->dwTypeData
);
3930 if (lpmii
->fMask
& MIIM_STATE
)
3931 menu
->fState
= lpmii
->fState
;
3933 if (lpmii
->fMask
& MIIM_ID
)
3934 menu
->wID
= lpmii
->wID
;
3936 if (lpmii
->fMask
& MIIM_SUBMENU
) {
3937 menu
->hSubMenu
= lpmii
->hSubMenu
;
3938 if (menu
->hSubMenu
) {
3939 POPUPMENU
*subMenu
= (POPUPMENU
*)USER_HEAP_LIN_ADDR((UINT16
)menu
->hSubMenu
);
3940 if (IS_A_MENU(subMenu
)) {
3941 subMenu
->wFlags
|= MF_POPUP
;
3942 menu
->fType
|= MF_POPUP
;
3945 /* FIXME: Return an error ? */
3946 menu
->fType
&= ~MF_POPUP
;
3949 menu
->fType
&= ~MF_POPUP
;
3952 if (lpmii
->fMask
& MIIM_CHECKMARKS
)
3954 menu
->hCheckBit
= lpmii
->hbmpChecked
;
3955 menu
->hUnCheckBit
= lpmii
->hbmpUnchecked
;
3957 if (lpmii
->fMask
& MIIM_DATA
)
3958 menu
->dwItemData
= lpmii
->dwItemData
;
3960 debug_print_menuitem("SetMenuItemInfo32_common: ", menu
, "");
3964 /**********************************************************************
3965 * SetMenuItemInfo32A (USER32.491)
3967 BOOL32 WINAPI
SetMenuItemInfo32A(HMENU32 hmenu
, UINT32 item
, BOOL32 bypos
,
3968 const MENUITEMINFO32A
*lpmii
)
3970 return SetMenuItemInfo32_common(MENU_FindItem(&hmenu
, &item
, bypos
? MF_BYPOSITION
: 0),
3974 /**********************************************************************
3975 * SetMenuItemInfo32W (USER32.492)
3977 BOOL32 WINAPI
SetMenuItemInfo32W(HMENU32 hmenu
, UINT32 item
, BOOL32 bypos
,
3978 const MENUITEMINFO32W
*lpmii
)
3980 return SetMenuItemInfo32_common(MENU_FindItem(&hmenu
, &item
, bypos
? MF_BYPOSITION
: 0),
3981 (const MENUITEMINFO32A
*)lpmii
, TRUE
);
3984 /**********************************************************************
3985 * SetMenuDefaultItem32 (USER32.489)
3987 BOOL32 WINAPI
SetMenuDefaultItem32(HMENU32 hmenu
, UINT32 item
, UINT32 bypos
)
3989 MENUITEM
*menuitem
= MENU_FindItem(&hmenu
, &item
, bypos
);
3992 if (!menuitem
) return FALSE
;
3993 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hmenu
))) return FALSE
;
3995 menu
->defitem
= item
; /* position */
3997 debug_print_menuitem("SetMenuDefaultItem32: ", menuitem
, "");
3998 FIXME(menu
, "(0x%x,%d,%d), empty stub!\n",
3999 hmenu
, item
, bypos
);
4003 /**********************************************************************
4004 * GetMenuDefaultItem32 (USER32.260)
4006 UINT32 WINAPI
GetMenuDefaultItem32(HMENU32 hmenu
, UINT32 bypos
, UINT32 flags
)
4010 if (!(menu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hmenu
)))
4013 FIXME(menu
, "(0x%x,%d,%d), stub!\n", hmenu
, bypos
, flags
);
4014 if (bypos
& MF_BYPOSITION
)
4015 return menu
->defitem
;
4017 FIXME (menu
, "default item 0x%x\n", menu
->defitem
);
4018 if ((menu
->defitem
> 0) && (menu
->defitem
< menu
->nItems
))
4019 return menu
->items
[menu
->defitem
].wID
;
4024 /*******************************************************************
4025 * InsertMenuItem16 (USER.441)
4029 BOOL16 WINAPI
InsertMenuItem16( HMENU16 hmenu
, UINT16 pos
, BOOL16 byposition
,
4030 const MENUITEMINFO16
*mii
)
4032 MENUITEMINFO32A miia
;
4034 miia
.cbSize
= sizeof(miia
);
4035 miia
.fMask
= mii
->fMask
;
4036 miia
.dwTypeData
= mii
->dwTypeData
;
4037 miia
.fType
= mii
->fType
;
4038 miia
.fState
= mii
->fState
;
4039 miia
.wID
= mii
->wID
;
4040 miia
.hSubMenu
= mii
->hSubMenu
;
4041 miia
.hbmpChecked
= mii
->hbmpChecked
;
4042 miia
.hbmpUnchecked
= mii
->hbmpUnchecked
;
4043 miia
.dwItemData
= mii
->dwItemData
;
4044 miia
.cch
= mii
->cch
;
4045 if (IS_STRING_ITEM(miia
.fType
))
4046 miia
.dwTypeData
= PTR_SEG_TO_LIN(miia
.dwTypeData
);
4047 return InsertMenuItem32A( hmenu
, pos
, byposition
, &miia
);
4051 /**********************************************************************
4052 * InsertMenuItem32A (USER32.323)
4054 BOOL32 WINAPI
InsertMenuItem32A(HMENU32 hMenu
, UINT32 uItem
, BOOL32 bypos
,
4055 const MENUITEMINFO32A
*lpmii
)
4057 MENUITEM
*item
= MENU_InsertItem(hMenu
, uItem
, bypos
? MF_BYPOSITION
: 0 );
4058 return SetMenuItemInfo32_common(item
, lpmii
, FALSE
);
4062 /**********************************************************************
4063 * InsertMenuItem32W (USER32.324)
4065 BOOL32 WINAPI
InsertMenuItem32W(HMENU32 hMenu
, UINT32 uItem
, BOOL32 bypos
,
4066 const MENUITEMINFO32W
*lpmii
)
4068 MENUITEM
*item
= MENU_InsertItem(hMenu
, uItem
, bypos
? MF_BYPOSITION
: 0 );
4069 return SetMenuItemInfo32_common(item
, (const MENUITEMINFO32A
*)lpmii
, TRUE
);
4072 /**********************************************************************
4073 * CheckMenuRadioItem32 (USER32.47)
4076 BOOL32 WINAPI
CheckMenuRadioItem32(HMENU32 hMenu
,
4077 UINT32 first
, UINT32 last
, UINT32 check
,
4080 MENUITEM
*mifirst
, *milast
, *micheck
;
4081 HMENU32 mfirst
= hMenu
, mlast
= hMenu
, mcheck
= hMenu
;
4083 TRACE(menu
, "ox%x: %d-%d, check %d, bypos=%d\n",
4084 hMenu
, first
, last
, check
, bypos
);
4086 mifirst
= MENU_FindItem (&mfirst
, &first
, bypos
);
4087 milast
= MENU_FindItem (&mlast
, &last
, bypos
);
4088 micheck
= MENU_FindItem (&mcheck
, &check
, bypos
);
4090 if (mifirst
== NULL
|| milast
== NULL
|| micheck
== NULL
||
4091 mifirst
> milast
|| mfirst
!= mlast
|| mfirst
!= mcheck
||
4092 micheck
> milast
|| micheck
< mifirst
)
4095 while (mifirst
<= milast
)
4097 if (mifirst
== micheck
)
4099 mifirst
->fType
|= MFT_RADIOCHECK
;
4100 mifirst
->fState
|= MFS_CHECKED
;
4102 mifirst
->fType
&= ~MFT_RADIOCHECK
;
4103 mifirst
->fState
&= ~MFS_CHECKED
;
4111 /**********************************************************************
4112 * CheckMenuRadioItem16 (not a Windows API)
4115 BOOL16 WINAPI
CheckMenuRadioItem16(HMENU16 hMenu
,
4116 UINT16 first
, UINT16 last
, UINT16 check
,
4119 return CheckMenuRadioItem32 (hMenu
, first
, last
, check
, bypos
);
4122 /**********************************************************************
4123 * GetMenuItemRect32 (USER32.266)
4125 * ATTENTION: Here, the returned values in rect are the screen
4126 * coordinates of the item just like if the menu was
4127 * always on the upper left side of the application.
4130 BOOL32 WINAPI
GetMenuItemRect32 (HWND32 hwnd
, HMENU32 hMenu
, UINT32 uItem
,
4133 POPUPMENU
*itemMenu
;
4135 HWND32 referenceHwnd
;
4137 TRACE(menu
, "(0x%x,0x%x,%d,%p)\n", hwnd
, hMenu
, uItem
, rect
);
4139 item
= MENU_FindItem (&hMenu
, &uItem
, MF_BYPOSITION
);
4140 referenceHwnd
= hwnd
;
4144 itemMenu
= (POPUPMENU
*) USER_HEAP_LIN_ADDR(hMenu
);
4145 if (itemMenu
== NULL
)
4148 if(itemMenu
->hWnd
== NULL
)
4150 referenceHwnd
= itemMenu
->hWnd
;
4153 if ((rect
== NULL
) || (item
== NULL
))
4158 MapWindowPoints32(referenceHwnd
, 0, (LPPOINT32
)rect
, 2);
4163 /**********************************************************************
4164 * GetMenuItemRect16 (USER.665)
4167 BOOL16 WINAPI
GetMenuItemRect16 (HWND16 hwnd
, HMENU16 hMenu
, UINT16 uItem
,
4173 if (!rect
) return FALSE
;
4174 res
= GetMenuItemRect32 (hwnd
, hMenu
, uItem
, &r32
);
4175 CONV_RECT32TO16 (&r32
, rect
);
4179 /**********************************************************************
4180 * SetMenuContextHelpId16 (USER.384)
4182 BOOL16 WINAPI
SetMenuContextHelpId16( HMENU16 hMenu
, DWORD dwContextHelpId
)
4184 return SetMenuContextHelpId32( hMenu
, dwContextHelpId
);
4188 /**********************************************************************
4189 * SetMenuContextHelpId32 (USER32.488)
4191 BOOL32 WINAPI
SetMenuContextHelpId32( HMENU32 hMenu
, DWORD dwContextHelpId
)
4193 FIXME(menu
, "SetMenuContextHelpId, stub\n");
4197 /**********************************************************************
4198 * GetMenuContextHelpId16 (USER.385)
4200 DWORD WINAPI
GetMenuContextHelpId16( HMENU16 hMenu
)
4202 return GetMenuContextHelpId16( hMenu
);
4205 /**********************************************************************
4206 * GetMenuContextHelpId32 (USER32.488)
4208 DWORD WINAPI
GetMenuContextHelpId32( HMENU32 hMenu
)
4210 FIXME(menu
, "GetMenuContextHelpId, stub\n");