4 static char RCSId
[] = "$Id$";
5 static char Copyright
[] = "Copyright Martin Ayotte, 1993";
6 static char Copyright2
[] = "Copyright Alexandre Julliard, 1994";
9 * Note: the style MF_MOUSESELECT is used to mark popup items that
10 * have been selected, i.e. their popup menu is currently displayed.
11 * This is probably not the meaning this style has in MS-Windows.
21 #include "sysmetrics.h"
22 #include "prototypes.h"
29 /* #define DEBUG_MENU /* */
30 /* #undef DEBUG_MENU /* */
31 /* #define DEBUG_MENUCALC /* */
32 /* #undef DEBUG_MENUCALC /* */
33 /* #define DEBUG_MENUSHORTCUT /* */
34 /* #undef DEBUG_MENUSHORTCUT /* */
36 /* Dimension of the menu bitmaps */
37 static WORD check_bitmap_width
= 0, check_bitmap_height
= 0;
38 static WORD arrow_bitmap_width
= 0, arrow_bitmap_height
= 0;
40 /* Flag set by EndMenu() to force an exit from menu tracking */
41 static BOOL fEndMenuCalled
= FALSE
;
43 /* Space between 2 menu bar items */
44 #define MENU_BAR_ITEMS_SPACE 16
46 /* Minimum width of a tab character */
47 #define MENU_TAB_SPACE 8
49 /* Height of a separator item */
50 #define SEPARATOR_HEIGHT 5
52 /* Values for menu->FocusedItem */
53 /* (other values give the position of the focused item) */
54 #define NO_SELECTED_ITEM 0xffff
55 #define SYSMENU_SELECTED 0xfffe /* Only valid on menu-bars */
57 #define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \
58 MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR)))
61 extern void NC_DrawSysButton(HWND hwnd
, HDC hdc
, BOOL down
); /* nonclient.c */
62 extern void CURSOR_SetWinCursor( HWND hwnd
, HCURSOR hcursor
); /* cursor.c */
63 extern BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
64 int xsrc
, int ysrc
, int width
, int height
,
65 int rop
); /* graphics.c */
67 extern HINSTANCE hSysRes
;
69 static HMENU hSysMenu
= 0;
70 static HBITMAP hStdCheck
= 0;
71 static HBITMAP hStdMnArrow
= 0;
74 WORD
* ParseMenuResource(WORD
*first_item
, int level
, HMENU hMenu
);
77 /***********************************************************************
80 * Menus initialisation.
88 if (!(hStdCheck
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECK
) )))
90 GetObject( hStdCheck
, sizeof(BITMAP
), (LPSTR
)&bm
);
91 check_bitmap_width
= bm
.bmWidth
;
92 check_bitmap_height
= bm
.bmHeight
;
93 if (!(hStdMnArrow
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_MNARROW
) )))
95 GetObject( hStdMnArrow
, sizeof(BITMAP
), (LPSTR
)&bm
);
96 arrow_bitmap_width
= bm
.bmWidth
;
97 arrow_bitmap_height
= bm
.bmHeight
;
99 /* Load system menu */
101 if (!(hSysMenu
= LoadMenu( hSysRes
, "SYSMENU" )))
103 fprintf(stderr
,"SysMenu not found in system resources !\n");
111 /***********************************************************************
114 * Check whether the window owning the menu bar has a system menu.
116 static BOOL
MENU_HasSysMenu( POPUPMENU
*menu
)
120 if (menu
->wFlags
& MF_POPUP
) return FALSE
;
121 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
))) return FALSE
;
122 return (wndPtr
->dwStyle
& WS_SYSMENU
) != 0;
126 /***********************************************************************
129 * Check whether the point (in screen coords) is in the system menu
130 * of the window owning the given menu.
132 static BOOL
MENU_IsInSysMenu( POPUPMENU
*menu
, POINT pt
)
136 if (menu
->wFlags
& MF_POPUP
) return FALSE
;
137 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
))) return FALSE
;
138 if (!(wndPtr
->dwStyle
& WS_SYSMENU
)) return FALSE
;
139 if ((pt
.x
< wndPtr
->rectClient
.left
) ||
140 (pt
.x
>= wndPtr
->rectClient
.left
+SYSMETRICS_CXSIZE
+SYSMETRICS_CXBORDER
))
142 if ((pt
.y
>= wndPtr
->rectClient
.top
- menu
->Height
) ||
143 (pt
.y
< wndPtr
->rectClient
.top
- menu
->Height
-
144 SYSMETRICS_CYSIZE
- SYSMETRICS_CYBORDER
)) return FALSE
;
149 /***********************************************************************
152 * Find a menu item. Return a pointer on the item, and modifies *hmenu
153 * in case the item was in a sub-menu.
155 static MENUITEM
*MENU_FindItem( HMENU
*hmenu
, WORD
*nPos
, WORD wFlags
)
161 if (!(menu
= (POPUPMENU
*) USER_HEAP_ADDR(*hmenu
))) return NULL
;
162 item
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
163 if (wFlags
& MF_BYPOSITION
)
165 if (*nPos
>= menu
->nItems
) return NULL
;
170 for (i
= 0; i
< menu
->nItems
; i
++, item
++)
172 if (item
->item_id
== *nPos
)
177 else if (item
->item_flags
& MF_POPUP
)
179 HMENU hsubmenu
= (HMENU
)item
->item_id
;
180 MENUITEM
*subitem
= MENU_FindItem( &hsubmenu
, nPos
, wFlags
);
193 /***********************************************************************
194 * MENU_FindItemByCoords
196 * Find the item at the specified coordinates (screen coords).
198 static MENUITEM
*MENU_FindItemByCoords( POPUPMENU
*menu
, int x
, int y
, WORD
*pos
)
204 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
))) return NULL
;
205 x
-= wndPtr
->rectWindow
.left
;
206 y
-= wndPtr
->rectWindow
.top
;
207 item
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
208 for (i
= 0; i
< menu
->nItems
; i
++, item
++)
210 if ((x
>= item
->rect
.left
) && (x
< item
->rect
.right
) &&
211 (y
>= item
->rect
.top
) && (y
< item
->rect
.bottom
))
221 /***********************************************************************
224 * Find the menu item selected by a key press.
225 * Return item id, -1 if none, -2 if we should close the menu.
227 static WORD
MENU_FindItemByKey( HWND hwndOwner
, HMENU hmenu
, WORD key
)
234 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
235 lpitem
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
237 for (i
= 0; i
< menu
->nItems
; i
++, lpitem
++)
239 if (IS_STRING_ITEM(lpitem
->item_flags
))
241 char *p
= strchr( lpitem
->item_text
, '&' );
242 if (p
&& (p
[1] != '&') && (toupper(p
[1]) == key
)) return i
;
245 menuchar
= SendMessage( hwndOwner
, WM_MENUCHAR
, key
,
246 MAKELONG( menu
->wFlags
, hmenu
) );
247 if (HIWORD(menuchar
) == 2) return LOWORD(menuchar
);
248 if (HIWORD(menuchar
) == 1) return -2;
253 /***********************************************************************
256 * Calculate the size of the menu item and store it in lpitem->rect.
258 static void MENU_CalcItemSize( HDC hdc
, LPMENUITEM lpitem
, HWND hwndOwner
,
259 int orgX
, int orgY
, BOOL menuBar
)
264 SetRect( &lpitem
->rect
, orgX
, orgY
, orgX
, orgY
);
267 if (lpitem
->item_flags
& MF_SEPARATOR
)
269 lpitem
->rect
.bottom
+= SEPARATOR_HEIGHT
;
275 lpitem
->rect
.right
+= 2 * check_bitmap_width
;
276 if (lpitem
->item_flags
& MF_POPUP
)
277 lpitem
->rect
.right
+= arrow_bitmap_width
;
280 if (lpitem
->item_flags
& MF_BITMAP
)
283 GetObject( (HBITMAP
)lpitem
->hText
, sizeof(BITMAP
), (LPSTR
)&bm
);
284 lpitem
->rect
.right
+= bm
.bmWidth
;
285 lpitem
->rect
.bottom
+= bm
.bmHeight
;
289 /* If we get here, then it is a text item */
291 dwSize
= GetTextExtent( hdc
, lpitem
->item_text
, strlen(lpitem
->item_text
));
292 lpitem
->rect
.right
+= LOWORD(dwSize
);
293 lpitem
->rect
.bottom
+= max( HIWORD(dwSize
), SYSMETRICS_CYMENU
);
295 if (menuBar
) lpitem
->rect
.right
+= MENU_BAR_ITEMS_SPACE
;
296 else if ((p
= strchr( lpitem
->item_text
, '\t' )) != NULL
)
298 /* Item contains a tab (only meaningful in popup menus) */
299 lpitem
->xTab
= check_bitmap_width
+ MENU_TAB_SPACE
+
300 LOWORD( GetTextExtent( hdc
, lpitem
->item_text
,
301 (int)(p
- lpitem
->item_text
) ));
302 lpitem
->rect
.right
+= MENU_TAB_SPACE
;
306 if (strchr( lpitem
->item_text
, '\b' ))
307 lpitem
->rect
.right
+= MENU_TAB_SPACE
;
308 lpitem
->xTab
= lpitem
->rect
.right
- check_bitmap_width
309 - arrow_bitmap_width
;
314 /***********************************************************************
315 * MENU_PopupMenuCalcSize
317 * Calculate the size of a popup menu.
319 static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop
, HWND hwndOwner
)
321 LPMENUITEM items
, lpitem
;
324 int orgX
, orgY
, maxX
, maxTab
, maxTabWidth
;
326 lppop
->Width
= lppop
->Height
= 0;
327 if (lppop
->nItems
== 0) return;
328 items
= (MENUITEM
*)USER_HEAP_ADDR( lppop
->hItems
);
331 while (start
< lppop
->nItems
)
333 lpitem
= &items
[start
];
336 maxTab
= maxTabWidth
= 0;
338 /* Parse items until column break or end of menu */
339 for (i
= start
; i
< lppop
->nItems
; i
++, lpitem
++)
342 (lpitem
->item_flags
& (MF_MENUBREAK
| MF_MENUBARBREAK
))) break;
343 MENU_CalcItemSize( hdc
, lpitem
, hwndOwner
, orgX
, orgY
, FALSE
);
344 maxX
= max( maxX
, lpitem
->rect
.right
);
345 orgY
= lpitem
->rect
.bottom
;
348 maxTab
= max( maxTab
, lpitem
->xTab
);
349 maxTabWidth
= max(maxTabWidth
,lpitem
->rect
.right
-lpitem
->xTab
);
353 /* Finish the column (set all items to the largest width found) */
354 maxX
= max( maxX
, maxTab
+ maxTabWidth
);
355 for (lpitem
= &items
[start
]; start
< i
; start
++, lpitem
++)
357 lpitem
->rect
.right
= maxX
;
358 if (lpitem
->xTab
) lpitem
->xTab
= maxTab
;
360 lppop
->Height
= max( lppop
->Height
, orgY
);
368 /***********************************************************************
369 * MENU_MenuBarCalcSize
371 * Calculate the size of the menu bar.
373 static void MENU_MenuBarCalcSize( HDC hdc
, LPRECT lprect
, LPPOPUPMENU lppop
,
376 LPMENUITEM lpitem
, items
;
377 int start
, i
, orgX
, orgY
, maxY
, helpPos
;
379 if ((lprect
== NULL
) || (lppop
== NULL
)) return;
380 if (lppop
->nItems
== 0) return;
381 dprintf_menucalc(stddeb
,"MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n",
382 lprect
->left
, lprect
->top
, lprect
->right
, lprect
->bottom
);
383 items
= (MENUITEM
*)USER_HEAP_ADDR( lppop
->hItems
);
384 lppop
->Width
= lprect
->right
- lprect
->left
;
389 while (start
< lppop
->nItems
)
391 lpitem
= &items
[start
];
395 /* Parse items until line break or end of menu */
396 for (i
= start
; i
< lppop
->nItems
; i
++, lpitem
++)
398 if ((helpPos
== -1) && (lpitem
->item_flags
& MF_HELP
)) helpPos
= i
;
400 (lpitem
->item_flags
& (MF_MENUBREAK
| MF_MENUBARBREAK
))) break;
401 MENU_CalcItemSize( hdc
, lpitem
, hwndOwner
, orgX
, orgY
, TRUE
);
402 if (lpitem
->rect
.right
> lprect
->right
)
404 if (i
!= start
) break;
405 else lpitem
->rect
.right
= lprect
->right
;
407 maxY
= max( maxY
, lpitem
->rect
.bottom
);
408 orgX
= lpitem
->rect
.right
;
411 /* Finish the line (set all items to the largest height found) */
412 while (start
< i
) items
[start
++].rect
.bottom
= maxY
;
415 lprect
->bottom
= maxY
;
416 lppop
->Height
= lprect
->bottom
- lprect
->top
;
418 /* Flush right all items between the MF_HELP and the last item */
419 /* (if several lines, only move the last line) */
422 lpitem
= &items
[lppop
->nItems
-1];
423 orgY
= lpitem
->rect
.top
;
424 orgX
= lprect
->right
;
425 for (i
= lppop
->nItems
- 1; i
>= helpPos
; i
--, lpitem
--)
427 if (lpitem
->rect
.top
!= orgY
) break; /* Other line */
428 if (lpitem
->rect
.right
>= orgX
) break; /* Too far right already */
429 lpitem
->rect
.left
+= orgX
- lpitem
->rect
.right
;
430 lpitem
->rect
.right
= orgX
;
431 orgX
= lpitem
->rect
.left
;
437 /***********************************************************************
440 * Draw a single menu item.
442 static void MENU_DrawMenuItem( HDC hdc
, LPMENUITEM lpitem
,
443 WORD height
, BOOL menuBar
)
447 if (menuBar
&& (lpitem
->item_flags
& MF_SEPARATOR
)) return;
450 /* Draw the background */
452 if (lpitem
->item_flags
& MF_HILITE
)
453 FillRect( hdc
, &rect
, sysColorObjects
.hbrushHighlight
);
454 else FillRect( hdc
, &rect
, sysColorObjects
.hbrushMenu
);
455 SetBkMode( hdc
, TRANSPARENT
);
457 /* Draw the separator bar (if any) */
459 if (!menuBar
&& (lpitem
->item_flags
& MF_MENUBARBREAK
))
461 SelectObject( hdc
, sysColorObjects
.hpenWindowFrame
);
462 MoveTo( hdc
, rect
.left
, 0 );
463 LineTo( hdc
, rect
.left
, height
);
465 if (lpitem
->item_flags
& MF_SEPARATOR
)
467 SelectObject( hdc
, sysColorObjects
.hpenWindowFrame
);
468 MoveTo( hdc
, rect
.left
, rect
.top
+ SEPARATOR_HEIGHT
/2 );
469 LineTo( hdc
, rect
.right
, rect
.top
+ SEPARATOR_HEIGHT
/2 );
475 if (lpitem
->item_flags
& MF_HILITE
)
477 if (lpitem
->item_flags
& MF_GRAYED
)
478 SetTextColor( hdc
, GetSysColor( COLOR_GRAYTEXT
) );
480 SetTextColor( hdc
, GetSysColor( COLOR_HIGHLIGHTTEXT
) );
481 SetBkColor( hdc
, GetSysColor( COLOR_HIGHLIGHT
) );
485 if (lpitem
->item_flags
& MF_GRAYED
)
486 SetTextColor( hdc
, GetSysColor( COLOR_GRAYTEXT
) );
488 SetTextColor( hdc
, GetSysColor( COLOR_MENUTEXT
) );
489 SetBkColor( hdc
, GetSysColor( COLOR_MENU
) );
494 /* Draw the check mark */
496 if (lpitem
->item_flags
& MF_CHECKED
)
498 GRAPH_DrawBitmap(hdc
, lpitem
->hCheckBit
? lpitem
->hCheckBit
:
499 hStdCheck
, rect
.left
,
500 (rect
.top
+rect
.bottom
-check_bitmap_height
) / 2,
501 0, 0, check_bitmap_width
, check_bitmap_height
,
504 else if (lpitem
->hUnCheckBit
!= 0) /* Not checked */
506 GRAPH_DrawBitmap(hdc
, lpitem
->hUnCheckBit
, rect
.left
,
507 (rect
.top
+rect
.bottom
-check_bitmap_height
) / 2,
508 0, 0, check_bitmap_width
, check_bitmap_height
,
512 /* Draw the popup-menu arrow */
514 if (lpitem
->item_flags
& MF_POPUP
)
516 GRAPH_DrawBitmap( hdc
, hStdMnArrow
,
517 rect
.right
-arrow_bitmap_width
-1,
518 (rect
.top
+rect
.bottom
-arrow_bitmap_height
) / 2,
519 0, 0, arrow_bitmap_width
, arrow_bitmap_height
,
523 rect
.left
+= check_bitmap_width
;
524 rect
.right
-= arrow_bitmap_width
;
527 /* Draw the item text or bitmap */
529 if (lpitem
->item_flags
& MF_BITMAP
)
531 GRAPH_DrawBitmap( hdc
, (HBITMAP
)lpitem
->hText
, rect
.left
, rect
.top
,
532 0, 0, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
,
536 /* No bitmap - process text if present */
537 else if ((lpitem
->item_text
) != ((char *) NULL
))
543 rect
.left
+= MENU_BAR_ITEMS_SPACE
/ 2;
544 rect
.right
-= MENU_BAR_ITEMS_SPACE
/ 2;
545 i
= strlen( lpitem
->item_text
);
549 for (i
= 0; lpitem
->item_text
[i
]; i
++)
550 if ((lpitem
->item_text
[i
] == '\t') ||
551 (lpitem
->item_text
[i
] == '\b')) break;
554 DrawText( hdc
, lpitem
->item_text
, i
, &rect
,
555 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
557 if (lpitem
->item_text
[i
]) /* There's a tab or flush-right char */
559 if (lpitem
->item_text
[i
] == '\t')
561 rect
.left
= lpitem
->xTab
;
562 DrawText( hdc
, lpitem
->item_text
+ i
+ 1, -1, &rect
,
563 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
565 else DrawText( hdc
, lpitem
->item_text
+ i
+ 1, -1, &rect
,
566 DT_RIGHT
| DT_VCENTER
| DT_SINGLELINE
);
572 /***********************************************************************
575 * Paint a popup menu.
577 static void MENU_DrawPopupMenu( HWND hwnd
, HDC hdc
, HMENU hmenu
)
584 GetClientRect( hwnd
, &rect
);
585 FillRect( hdc
, &rect
, sysColorObjects
.hbrushMenu
);
586 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
587 if (!menu
|| !menu
->nItems
) return;
588 item
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
589 for (i
= menu
->nItems
; i
> 0; i
--, item
++)
590 MENU_DrawMenuItem( hdc
, item
, menu
->Height
, FALSE
);
594 /***********************************************************************
597 * Paint a menu bar. Returns the height of the menu bar.
599 WORD
MENU_DrawMenuBar(HDC hDC
, LPRECT lprect
, HWND hwnd
, BOOL suppress_draw
)
604 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
606 lppop
= (LPPOPUPMENU
) USER_HEAP_ADDR( wndPtr
->wIDmenu
);
607 if (lppop
== NULL
|| lprect
== NULL
) return SYSMETRICS_CYMENU
;
608 dprintf_menu(stddeb
,"MENU_DrawMenuBar(%04X, %08X, %08X); !\n",
610 if (lppop
->Height
== 0) MENU_MenuBarCalcSize(hDC
, lprect
, lppop
, hwnd
);
611 lprect
->bottom
= lprect
->top
+ lppop
->Height
;
612 if (suppress_draw
) return lppop
->Height
;
614 FillRect(hDC
, lprect
, sysColorObjects
.hbrushMenu
);
615 SelectObject( hDC
, sysColorObjects
.hpenWindowFrame
);
616 MoveTo( hDC
, lprect
->left
, lprect
->bottom
);
617 LineTo( hDC
, lprect
->right
, lprect
->bottom
);
619 if (lppop
->nItems
== 0) return SYSMETRICS_CYMENU
;
620 lpitem
= (MENUITEM
*) USER_HEAP_ADDR( lppop
->hItems
);
621 for (i
= 0; i
< lppop
->nItems
; i
++, lpitem
++)
623 MENU_DrawMenuItem( hDC
, lpitem
, lppop
->Height
, TRUE
);
625 return lppop
->Height
;
629 /***********************************************************************
632 * Display a popup menu.
634 static BOOL
MENU_ShowPopup(HWND hwndOwner
, HMENU hmenu
, WORD id
, int x
, int y
)
638 if (!(menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
))) return FALSE
;
639 if (menu
->FocusedItem
!= NO_SELECTED_ITEM
)
641 MENUITEM
*item
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
642 item
[menu
->FocusedItem
].item_flags
&= ~(MF_HILITE
| MF_MOUSESELECT
);
643 menu
->FocusedItem
= NO_SELECTED_ITEM
;
645 SendMessage( hwndOwner
, WM_INITMENUPOPUP
, hmenu
,
646 MAKELONG( id
, (menu
->wFlags
& MF_POPUP
) ? 1 : 0 ));
647 MENU_PopupMenuCalcSize( menu
, hwndOwner
);
650 WND
*wndPtr
= WIN_FindWndPtr( hwndOwner
);
651 if (!wndPtr
) return FALSE
;
652 menu
->hWnd
= CreateWindow( POPUPMENU_CLASS_NAME
, "",
653 WS_POPUP
| WS_BORDER
, x
, y
,
654 menu
->Width
+ 2*SYSMETRICS_CXBORDER
,
655 menu
->Height
+ 2*SYSMETRICS_CYBORDER
,
656 0, 0, wndPtr
->hInstance
,
657 (LPSTR
)(DWORD
)hmenu
);
658 if (!menu
->hWnd
) return FALSE
;
660 else SetWindowPos( menu
->hWnd
, 0, x
, y
,
661 menu
->Width
+ 2*SYSMETRICS_CXBORDER
,
662 menu
->Height
+ 2*SYSMETRICS_CYBORDER
,
663 SWP_NOACTIVATE
| SWP_NOZORDER
);
665 /* Display the window */
667 SetWindowPos( menu
->hWnd
, HWND_TOP
, 0, 0, 0, 0,
668 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
669 UpdateWindow( menu
->hWnd
);
674 /***********************************************************************
677 static void MENU_SelectItem( HMENU hmenu
, WORD wIndex
)
683 lppop
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
684 if (!lppop
->nItems
) return;
685 items
= (MENUITEM
*) USER_HEAP_ADDR( lppop
->hItems
);
686 if ((wIndex
!= NO_SELECTED_ITEM
) &&
687 (wIndex
!= SYSMENU_SELECTED
) &&
688 (items
[wIndex
].item_flags
& MF_SEPARATOR
))
689 wIndex
= NO_SELECTED_ITEM
;
690 if (lppop
->FocusedItem
== wIndex
) return;
691 if (lppop
->wFlags
& MF_POPUP
) hdc
= GetDC( lppop
->hWnd
);
692 else hdc
= GetDCEx( lppop
->hWnd
, 0, DCX_CACHE
| DCX_WINDOW
);
694 /* Clear previous highlighted item */
695 if (lppop
->FocusedItem
!= NO_SELECTED_ITEM
)
697 if (lppop
->FocusedItem
== SYSMENU_SELECTED
)
698 NC_DrawSysButton( lppop
->hWnd
, hdc
, FALSE
);
701 items
[lppop
->FocusedItem
].item_flags
&=~(MF_HILITE
|MF_MOUSESELECT
);
702 MENU_DrawMenuItem( hdc
, &items
[lppop
->FocusedItem
], lppop
->Height
,
703 !(lppop
->wFlags
& MF_POPUP
) );
707 /* Highlight new item (if any) */
708 lppop
->FocusedItem
= wIndex
;
709 if (lppop
->FocusedItem
!= NO_SELECTED_ITEM
)
711 if (lppop
->FocusedItem
== SYSMENU_SELECTED
)
712 NC_DrawSysButton( lppop
->hWnd
, hdc
, TRUE
);
715 items
[lppop
->FocusedItem
].item_flags
|= MF_HILITE
;
716 MENU_DrawMenuItem( hdc
, &items
[lppop
->FocusedItem
], lppop
->Height
,
717 !(lppop
->wFlags
& MF_POPUP
) );
718 SendMessage(lppop
->hWnd
, WM_MENUSELECT
,
719 items
[lppop
->FocusedItem
].item_id
,
720 MAKELONG( hmenu
, items
[lppop
->FocusedItem
].item_flags
));
723 ReleaseDC( lppop
->hWnd
, hdc
);
727 /***********************************************************************
728 * MENU_SelectNextItem
730 static void MENU_SelectNextItem( HMENU hmenu
)
736 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
737 if (!menu
->nItems
) return;
738 items
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
739 if ((menu
->FocusedItem
!= NO_SELECTED_ITEM
) &&
740 (menu
->FocusedItem
!= SYSMENU_SELECTED
))
742 for (i
= menu
->FocusedItem
+1; i
< menu
->nItems
; i
++)
744 if (!(items
[i
].item_flags
& MF_SEPARATOR
))
746 MENU_SelectItem( hmenu
, i
);
750 if (MENU_HasSysMenu( menu
))
752 MENU_SelectItem( hmenu
, SYSMENU_SELECTED
);
756 for (i
= 0; i
< menu
->nItems
; i
++)
758 if (!(items
[i
].item_flags
& MF_SEPARATOR
))
760 MENU_SelectItem( hmenu
, i
);
764 if (MENU_HasSysMenu( menu
)) MENU_SelectItem( hmenu
, SYSMENU_SELECTED
);
768 /***********************************************************************
769 * MENU_SelectPrevItem
771 static void MENU_SelectPrevItem( HMENU hmenu
)
777 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
778 if (!menu
->nItems
) return;
779 items
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
780 if ((menu
->FocusedItem
!= NO_SELECTED_ITEM
) &&
781 (menu
->FocusedItem
!= SYSMENU_SELECTED
))
783 for (i
= menu
->FocusedItem
- 1; i
>= 0; i
--)
785 if (!(items
[i
].item_flags
& MF_SEPARATOR
))
787 MENU_SelectItem( hmenu
, i
);
791 if (MENU_HasSysMenu( menu
))
793 MENU_SelectItem( hmenu
, SYSMENU_SELECTED
);
797 for (i
= menu
->nItems
- 1; i
> 0; i
--)
799 if (!(items
[i
].item_flags
& MF_SEPARATOR
))
801 MENU_SelectItem( hmenu
, i
);
805 if (MENU_HasSysMenu( menu
)) MENU_SelectItem( hmenu
, SYSMENU_SELECTED
);
809 /***********************************************************************
812 * Return the handle of the selected sub-popup menu (if any).
814 static HMENU
MENU_GetSubPopup( HMENU hmenu
)
819 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
820 if (menu
->FocusedItem
== NO_SELECTED_ITEM
) return 0;
821 else if (menu
->FocusedItem
== SYSMENU_SELECTED
)
822 return GetSystemMenu( menu
->hWnd
, FALSE
);
824 item
= ((MENUITEM
*)USER_HEAP_ADDR( menu
->hItems
)) + menu
->FocusedItem
;
825 if (!(item
->item_flags
& MF_POPUP
) || !(item
->item_flags
& MF_MOUSESELECT
))
827 return item
->item_id
;
831 /***********************************************************************
834 * Hide the sub-popup menus of this menu.
836 static void MENU_HideSubPopups( HMENU hmenu
)
839 POPUPMENU
*menu
, *submenu
;
842 if (!(menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
))) return;
843 if (menu
->FocusedItem
== NO_SELECTED_ITEM
) return;
844 if (menu
->FocusedItem
== SYSMENU_SELECTED
)
846 hsubmenu
= GetSystemMenu( menu
->hWnd
, FALSE
);
850 item
= ((MENUITEM
*)USER_HEAP_ADDR(menu
->hItems
)) + menu
->FocusedItem
;
851 if (!(item
->item_flags
& MF_POPUP
) ||
852 !(item
->item_flags
& MF_MOUSESELECT
)) return;
853 item
->item_flags
&= ~MF_MOUSESELECT
;
854 hsubmenu
= item
->item_id
;
856 submenu
= (POPUPMENU
*) USER_HEAP_ADDR( hsubmenu
);
857 MENU_HideSubPopups( hsubmenu
);
858 if (submenu
->hWnd
) ShowWindow( submenu
->hWnd
, SW_HIDE
);
859 MENU_SelectItem( hsubmenu
, NO_SELECTED_ITEM
);
863 /***********************************************************************
866 * Display the sub-menu of the selected item of this menu.
867 * Return the handle of the submenu, or hmenu if no submenu to display.
869 static HMENU
MENU_ShowSubPopup( HWND hwndOwner
, HMENU hmenu
, BOOL selectFirst
)
875 if (!(menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
))) return hmenu
;
876 if (!(wndPtr
= WIN_FindWndPtr( menu
->hWnd
))) return hmenu
;
877 if (menu
->FocusedItem
== NO_SELECTED_ITEM
) return hmenu
;
878 if (menu
->FocusedItem
== SYSMENU_SELECTED
)
880 MENU_ShowPopup(hwndOwner
, wndPtr
->hSysMenu
, 0, wndPtr
->rectClient
.left
,
881 wndPtr
->rectClient
.top
- menu
->Height
- 2*SYSMETRICS_CYBORDER
);
882 if (selectFirst
) MENU_SelectNextItem( wndPtr
->hSysMenu
);
883 return wndPtr
->hSysMenu
;
885 item
= ((MENUITEM
*)USER_HEAP_ADDR( menu
->hItems
)) + menu
->FocusedItem
;
886 if (!(item
->item_flags
& MF_POPUP
) ||
887 (item
->item_flags
& (MF_GRAYED
| MF_DISABLED
))) return hmenu
;
888 item
->item_flags
|= MF_MOUSESELECT
;
889 if (menu
->wFlags
& MF_POPUP
)
891 MENU_ShowPopup( hwndOwner
, (HMENU
)item
->item_id
, menu
->FocusedItem
,
892 wndPtr
->rectWindow
.left
+ item
->rect
.right
-arrow_bitmap_width
,
893 wndPtr
->rectWindow
.top
+ item
->rect
.top
);
897 MENU_ShowPopup( hwndOwner
, (HMENU
)item
->item_id
, menu
->FocusedItem
,
898 wndPtr
->rectWindow
.left
+ item
->rect
.left
,
899 wndPtr
->rectWindow
.top
+ item
->rect
.bottom
);
901 if (selectFirst
) MENU_SelectNextItem( (HMENU
)item
->item_id
);
902 return (HMENU
)item
->item_id
;
906 /***********************************************************************
907 * MENU_FindMenuByCoords
909 * Find the menu containing a given point (in screen coords).
911 static HMENU
MENU_FindMenuByCoords( HMENU hmenu
, POINT pt
)
916 if (!(hwnd
= WindowFromPoint( pt
))) return 0;
919 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
920 if (menu
->hWnd
== hwnd
)
922 if (!(menu
->wFlags
& MF_POPUP
))
924 /* Make sure it's in the menu bar (or in system menu) */
925 WND
*wndPtr
= WIN_FindWndPtr( menu
->hWnd
);
926 if ((pt
.x
< wndPtr
->rectClient
.left
) ||
927 (pt
.x
>= wndPtr
->rectClient
.right
) ||
928 (pt
.y
>= wndPtr
->rectClient
.top
)) return 0;
929 if (pt
.y
< wndPtr
->rectClient
.top
- menu
->Height
)
931 if (!MENU_IsInSysMenu( menu
, pt
)) return 0;
933 /* else it's in the menu bar */
937 hmenu
= MENU_GetSubPopup( hmenu
);
943 /***********************************************************************
944 * MENU_ExecFocusedItem
946 * Execute a menu item (for instance when user pressed Enter).
947 * Return TRUE if we can go on with menu tracking.
949 static BOOL
MENU_ExecFocusedItem( HWND hwndOwner
, HMENU hmenu
,
950 HMENU
*hmenuCurrent
)
953 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
954 if (!menu
|| !menu
->nItems
|| (menu
->FocusedItem
== NO_SELECTED_ITEM
) ||
955 (menu
->FocusedItem
== SYSMENU_SELECTED
)) return TRUE
;
956 item
= ((MENUITEM
*)USER_HEAP_ADDR( menu
->hItems
)) + menu
->FocusedItem
;
957 if (!(item
->item_flags
& MF_POPUP
))
959 if (!(item
->item_flags
& (MF_GRAYED
| MF_DISABLED
)))
961 PostMessage( hwndOwner
, (menu
->wFlags
& MF_SYSMENU
) ?
962 WM_SYSCOMMAND
: WM_COMMAND
, item
->item_id
, 0 );
969 *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, TRUE
);
975 /***********************************************************************
978 * Handle a button-down event in a menu. Point is in screen coords.
979 * hmenuCurrent is the top-most visible popup.
980 * Return TRUE if we can go on with menu tracking.
982 static BOOL
MENU_ButtonDown( HWND hwndOwner
, HMENU hmenu
, HMENU
*hmenuCurrent
,
989 if (!hmenu
) return FALSE
; /* Outside all menus */
990 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
991 item
= MENU_FindItemByCoords( menu
, pt
.x
, pt
.y
, &id
);
992 if (!item
) /* Maybe in system menu */
994 if (!MENU_IsInSysMenu( menu
, pt
)) return FALSE
;
995 id
= SYSMENU_SELECTED
;
998 if (menu
->FocusedItem
== id
)
1000 if (id
== SYSMENU_SELECTED
) return FALSE
;
1001 if (item
->item_flags
& MF_POPUP
)
1003 if (item
->item_flags
& MF_MOUSESELECT
)
1005 if (menu
->wFlags
& MF_POPUP
)
1007 MENU_HideSubPopups( hmenu
);
1008 *hmenuCurrent
= hmenu
;
1012 else *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, FALSE
);
1017 MENU_HideSubPopups( hmenu
);
1018 MENU_SelectItem( hmenu
, id
);
1019 *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, FALSE
);
1025 /***********************************************************************
1028 * Handle a button-up event in a menu. Point is in screen coords.
1029 * hmenuCurrent is the top-most visible popup.
1030 * Return TRUE if we can go on with menu tracking.
1032 static BOOL
MENU_ButtonUp( HWND hwndOwner
, HMENU hmenu
, HMENU
*hmenuCurrent
,
1040 if (!hmenu
) return FALSE
; /* Outside all menus */
1041 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
1042 item
= MENU_FindItemByCoords( menu
, pt
.x
, pt
.y
, &id
);
1043 if (!item
) /* Maybe in system menu */
1045 if (!MENU_IsInSysMenu( menu
, pt
)) return FALSE
;
1046 id
= SYSMENU_SELECTED
;
1047 hsubmenu
= GetSystemMenu( menu
->hWnd
, FALSE
);
1050 if (menu
->FocusedItem
!= id
) return FALSE
;
1052 if (id
!= SYSMENU_SELECTED
)
1054 if (!(item
->item_flags
& MF_POPUP
))
1056 return MENU_ExecFocusedItem( hwndOwner
, hmenu
, hmenuCurrent
);
1058 hsubmenu
= item
->item_id
;
1060 /* Select first item of sub-popup */
1061 MENU_SelectItem( hsubmenu
, NO_SELECTED_ITEM
);
1062 MENU_SelectNextItem( hsubmenu
);
1067 /***********************************************************************
1070 * Handle a motion event in a menu. Point is in screen coords.
1071 * hmenuCurrent is the top-most visible popup.
1072 * Return TRUE if we can go on with menu tracking.
1074 static BOOL
MENU_MouseMove( HWND hwndOwner
, HMENU hmenu
, HMENU
*hmenuCurrent
,
1079 WORD id
= NO_SELECTED_ITEM
;
1083 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
1084 item
= MENU_FindItemByCoords( menu
, pt
.x
, pt
.y
, &id
);
1085 if (!item
) /* Maybe in system menu */
1087 if (!MENU_IsInSysMenu( menu
, pt
))
1088 id
= NO_SELECTED_ITEM
; /* Outside all items */
1089 else id
= SYSMENU_SELECTED
;
1092 if (id
== NO_SELECTED_ITEM
)
1094 MENU_SelectItem( *hmenuCurrent
, NO_SELECTED_ITEM
);
1096 else if (menu
->FocusedItem
!= id
)
1098 MENU_HideSubPopups( hmenu
);
1099 MENU_SelectItem( hmenu
, id
);
1100 *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, FALSE
);
1106 /***********************************************************************
1109 * Handle a VK_LEFT key event in a menu.
1110 * hmenuCurrent is the top-most visible popup.
1112 static void MENU_KeyLeft( HWND hwndOwner
, HMENU hmenu
, HMENU
*hmenuCurrent
)
1115 HMENU hmenutmp
, hmenuprev
;
1117 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
1118 hmenuprev
= hmenutmp
= hmenu
;
1119 while (hmenutmp
!= *hmenuCurrent
)
1121 hmenutmp
= MENU_GetSubPopup( hmenuprev
);
1122 if (hmenutmp
!= *hmenuCurrent
) hmenuprev
= hmenutmp
;
1124 MENU_HideSubPopups( hmenuprev
);
1126 if ((hmenuprev
== hmenu
) && !(menu
->wFlags
& MF_POPUP
))
1128 /* Select previous item on the menu bar */
1129 MENU_SelectPrevItem( hmenu
);
1130 if (*hmenuCurrent
!= hmenu
)
1132 /* A popup menu was displayed -> display the next one */
1133 *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, TRUE
);
1136 else *hmenuCurrent
= hmenuprev
;
1140 /***********************************************************************
1143 * Handle a VK_RIGHT key event in a menu.
1144 * hmenuCurrent is the top-most visible popup.
1146 static void MENU_KeyRight( HWND hwndOwner
, HMENU hmenu
, HMENU
*hmenuCurrent
)
1151 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
1153 if ((menu
->wFlags
& MF_POPUP
) || (*hmenuCurrent
!= hmenu
))
1155 /* If already displaying a popup, try to display sub-popup */
1156 hmenutmp
= MENU_ShowSubPopup( hwndOwner
, *hmenuCurrent
, TRUE
);
1157 if (hmenutmp
!= *hmenuCurrent
) /* Sub-popup displayed */
1159 *hmenuCurrent
= hmenutmp
;
1164 /* If on menu-bar, go to next item */
1165 if (!(menu
->wFlags
& MF_POPUP
))
1167 MENU_HideSubPopups( hmenu
);
1168 MENU_SelectNextItem( hmenu
);
1169 if (*hmenuCurrent
!= hmenu
)
1171 /* A popup menu was displayed -> display the next one */
1172 *hmenuCurrent
= MENU_ShowSubPopup( hwndOwner
, hmenu
, TRUE
);
1175 else if (*hmenuCurrent
!= hmenu
) /* Hide last level popup */
1178 hmenuprev
= hmenutmp
= hmenu
;
1179 while (hmenutmp
!= *hmenuCurrent
)
1181 hmenutmp
= MENU_GetSubPopup( hmenuprev
);
1182 if (hmenutmp
!= *hmenuCurrent
) hmenuprev
= hmenutmp
;
1184 MENU_HideSubPopups( hmenuprev
);
1185 *hmenuCurrent
= hmenuprev
;
1190 /***********************************************************************
1193 * Menu tracking code.
1194 * If 'x' and 'y' are not 0, we simulate a button-down event at (x,y)
1195 * before beginning tracking. This is to help menu-bar tracking.
1197 static BOOL
MENU_TrackMenu( HMENU hmenu
, WORD wFlags
, int x
, int y
,
1198 HWND hwnd
, LPRECT lprect
)
1202 HMENU hmenuCurrent
= hmenu
;
1203 BOOL fClosed
= FALSE
;
1206 fEndMenuCalled
= FALSE
;
1207 if (!(menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
))) return FALSE
;
1210 POINT pt
= { x
, y
};
1211 MENU_ButtonDown( hwnd
, hmenu
, &hmenuCurrent
, pt
);
1217 if (!MSG_InternalGetMessage( &msg
, 0, hwnd
, MSGF_MENU
, 0, TRUE
))
1220 if ((msg
.message
>= WM_MOUSEFIRST
) && (msg
.message
<= WM_MOUSELAST
))
1222 /* Find the sub-popup for this mouse event (if any) */
1223 HMENU hsubmenu
= MENU_FindMenuByCoords( hmenu
, msg
.pt
);
1227 case WM_RBUTTONDOWN
:
1228 case WM_NCRBUTTONDOWN
:
1229 if (!(wFlags
& TPM_RIGHTBUTTON
)) break;
1231 case WM_LBUTTONDOWN
:
1232 case WM_NCLBUTTONDOWN
:
1233 fClosed
= !MENU_ButtonDown( hwnd
, hsubmenu
,
1234 &hmenuCurrent
, msg
.pt
);
1238 case WM_NCRBUTTONUP
:
1239 if (!(wFlags
& TPM_RIGHTBUTTON
)) break;
1242 case WM_NCLBUTTONUP
:
1243 /* If outside all menus but inside lprect, ignore it */
1244 if (!hsubmenu
&& lprect
&& PtInRect( lprect
, msg
.pt
)) break;
1245 fClosed
= !MENU_ButtonUp( hwnd
, hsubmenu
,
1246 &hmenuCurrent
, msg
.pt
);
1250 case WM_NCMOUSEMOVE
:
1251 if ((msg
.wParam
& MK_LBUTTON
) ||
1252 ((wFlags
& TPM_RIGHTBUTTON
) && (msg
.wParam
& MK_RBUTTON
)))
1254 fClosed
= !MENU_MouseMove( hwnd
, hsubmenu
,
1255 &hmenuCurrent
, msg
.pt
);
1260 else if ((msg
.message
>= WM_KEYFIRST
) && (msg
.message
<= WM_KEYLAST
))
1268 MENU_SelectItem( hmenuCurrent
, NO_SELECTED_ITEM
);
1269 MENU_SelectNextItem( hmenuCurrent
);
1273 MENU_SelectItem( hmenuCurrent
, NO_SELECTED_ITEM
);
1274 MENU_SelectPrevItem( hmenuCurrent
);
1278 MENU_SelectPrevItem( hmenuCurrent
);
1282 /* If on menu bar, pull-down the menu */
1283 if (!(menu
->wFlags
& MF_POPUP
) && (hmenuCurrent
== hmenu
))
1284 hmenuCurrent
= MENU_ShowSubPopup( hwnd
, hmenu
, TRUE
);
1286 MENU_SelectNextItem( hmenuCurrent
);
1290 MENU_KeyLeft( hwnd
, hmenu
, &hmenuCurrent
);
1294 MENU_KeyRight( hwnd
, hmenu
, &hmenuCurrent
);
1299 fClosed
= !MENU_ExecFocusedItem( hwnd
, hmenuCurrent
,
1310 break; /* WM_KEYDOWN */
1320 break; /* WM_SYSKEYDOWN */
1324 /* Hack to avoid control chars. */
1325 /* We will find a better way real soon... */
1326 if ((msg
.wParam
<= 32) || (msg
.wParam
>= 127)) break;
1327 pos
= MENU_FindItemByKey( hwnd
, hmenuCurrent
, msg
.wParam
);
1328 if (pos
== (WORD
)-2) fClosed
= TRUE
;
1329 else if (pos
== (WORD
)-1) MessageBeep(0);
1332 MENU_SelectItem( hmenuCurrent
, pos
);
1333 fClosed
= !MENU_ExecFocusedItem( hwnd
, hmenuCurrent
,
1338 break; /* WM_CHAR */
1339 } /* switch(msg.message) */
1343 DispatchMessage( &msg
);
1345 if (fEndMenuCalled
) fClosed
= TRUE
;
1347 if (!fClosed
) /* Remove the message from the queue */
1348 PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
);
1351 MENU_HideSubPopups( hmenu
);
1352 if (menu
->wFlags
& MF_POPUP
) ShowWindow( menu
->hWnd
, SW_HIDE
);
1353 MENU_SelectItem( hmenu
, NO_SELECTED_ITEM
);
1354 fEndMenuCalled
= FALSE
;
1359 /***********************************************************************
1360 * MENU_TrackMouseMenuBar
1362 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
1364 void MENU_TrackMouseMenuBar( HWND hwnd
, POINT pt
)
1366 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1367 SendMessage( hwnd
, WM_ENTERMENULOOP
, 0, 0 );
1368 MENU_TrackMenu( (HMENU
)wndPtr
->wIDmenu
, TPM_LEFTALIGN
| TPM_LEFTBUTTON
,
1369 pt
.x
, pt
.y
, hwnd
, NULL
);
1370 SendMessage( hwnd
, WM_EXITMENULOOP
, 0, 0 );
1374 /***********************************************************************
1375 * MENU_TrackKbdMenuBar
1377 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
1379 void MENU_TrackKbdMenuBar( HWND hwnd
, WORD wParam
)
1381 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1382 SendMessage( hwnd
, WM_ENTERMENULOOP
, 0, 0 );
1383 /* Select first selectable item */
1384 MENU_SelectItem( wndPtr
->wIDmenu
, NO_SELECTED_ITEM
);
1385 MENU_SelectNextItem( (HMENU
)wndPtr
->wIDmenu
);
1386 MENU_TrackMenu( (HMENU
)wndPtr
->wIDmenu
, TPM_LEFTALIGN
| TPM_LEFTBUTTON
,
1388 SendMessage( hwnd
, WM_EXITMENULOOP
, 0, 0 );
1392 /**********************************************************************
1393 * TrackPopupMenu [USER.416]
1395 BOOL
TrackPopupMenu( HMENU hMenu
, WORD wFlags
, short x
, short y
,
1396 short nReserved
, HWND hWnd
, LPRECT lpRect
)
1398 if (!MENU_ShowPopup( hWnd
, hMenu
, 0, x
, y
)) return FALSE
;
1399 return MENU_TrackMenu( hMenu
, wFlags
, 0, 0, hWnd
, lpRect
);
1403 /***********************************************************************
1406 LONG
PopupMenuWndProc( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
1412 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)lParam
;
1413 HMENU hmenu
= (HMENU
) ((int)createStruct
->lpCreateParams
& 0xffff);
1414 SetWindowWord( hwnd
, 0, hmenu
);
1418 case WM_MOUSEACTIVATE
: /* We don't want to be activated */
1419 return MA_NOACTIVATE
;
1424 BeginPaint( hwnd
, &ps
);
1425 MENU_DrawPopupMenu( hwnd
, ps
.hdc
,
1426 (HMENU
)GetWindowWord( hwnd
, 0 ) );
1427 EndPaint( hwnd
, &ps
);
1432 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
1438 /***********************************************************************
1439 * MENU_GetMenuBarHeight
1441 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
1443 WORD
MENU_GetMenuBarHeight( HWND hwnd
, WORD menubarWidth
, int orgX
, int orgY
)
1450 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
1451 if (!(lppop
= (LPPOPUPMENU
)USER_HEAP_ADDR( wndPtr
->wIDmenu
))) return 0;
1452 hdc
= GetDC( hwnd
);
1453 SetRect( &rectBar
, orgX
, orgY
, orgX
+menubarWidth
, orgY
+SYSMETRICS_CYMENU
);
1454 MENU_MenuBarCalcSize( hdc
, &rectBar
, lppop
, hwnd
);
1455 ReleaseDC( hwnd
, hdc
);
1456 return lppop
->Height
;
1460 /**********************************************************************
1461 * ChangeMenu [USER.153]
1463 BOOL
ChangeMenu(HMENU hMenu
, WORD nPos
, LPSTR lpNewItem
,
1464 WORD wItemID
, WORD wFlags
)
1466 if (wFlags
& MF_APPEND
)
1467 return AppendMenu(hMenu
, wFlags
, wItemID
, lpNewItem
);
1468 if (wFlags
& MF_DELETE
)
1469 return DeleteMenu(hMenu
, wItemID
, wFlags
);
1470 if (wFlags
& MF_INSERT
)
1471 return InsertMenu(hMenu
, nPos
, wFlags
, wItemID
, lpNewItem
);
1472 if (wFlags
& MF_CHANGE
)
1473 return ModifyMenu(hMenu
, nPos
, wFlags
, wItemID
, lpNewItem
);
1474 if (wFlags
& MF_REMOVE
)
1475 return RemoveMenu(hMenu
, wItemID
, wFlags
);
1480 /**********************************************************************
1481 * CheckMenuItem [USER.154]
1483 BOOL
CheckMenuItem(HMENU hMenu
, WORD wItemID
, WORD wFlags
)
1486 dprintf_menu(stddeb
,"CheckMenuItem (%04X, %04X, %04X) !\n",
1487 hMenu
, wItemID
, wFlags
);
1488 if (!(lpitem
= MENU_FindItem(&hMenu
, &wItemID
, wFlags
))) return FALSE
;
1489 if (wFlags
& MF_CHECKED
) lpitem
->item_flags
|= MF_CHECKED
;
1490 else lpitem
->item_flags
&= ~MF_CHECKED
;
1495 /**********************************************************************
1496 * EnableMenuItem [USER.155]
1498 BOOL
EnableMenuItem(HMENU hMenu
, WORD wItemID
, WORD wFlags
)
1501 dprintf_menu(stddeb
,"EnableMenuItem (%04X, %04X, %04X) !\n",
1502 hMenu
, wItemID
, wFlags
);
1503 if (!(lpitem
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
))) return FALSE
;
1505 /* We can't have MF_GRAYED and MF_DISABLED together */
1506 if (wFlags
& MF_GRAYED
)
1508 lpitem
->item_flags
= (lpitem
->item_flags
& ~MF_DISABLED
) | MF_GRAYED
;
1510 else if (wFlags
& MF_DISABLED
)
1512 lpitem
->item_flags
= (lpitem
->item_flags
& ~MF_GRAYED
) | MF_DISABLED
;
1514 else /* MF_ENABLED */
1516 lpitem
->item_flags
&= ~(MF_GRAYED
| MF_DISABLED
);
1522 /**********************************************************************
1523 * GetMenuString [USER.161]
1525 int GetMenuString(HMENU hMenu
, WORD wItemID
,
1526 LPSTR str
, short nMaxSiz
, WORD wFlags
)
1530 dprintf_menu(stddeb
,"GetMenuString(%04X, %04X, %08X, %d, %04X);\n",
1531 hMenu
, wItemID
, str
, nMaxSiz
, wFlags
);
1532 if (str
== NULL
) return FALSE
;
1533 lpitem
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
);
1534 if (lpitem
!= NULL
) {
1535 if (lpitem
->item_text
!= NULL
) {
1536 maxsiz
= min(nMaxSiz
- 1, strlen(lpitem
->item_text
));
1537 strncpy(str
, lpitem
->item_text
, maxsiz
+ 1);
1541 dprintf_menu(stddeb
,"GetMenuString // Found !\n");
1548 /**********************************************************************
1549 * HiliteMenuItem [USER.162]
1551 BOOL
HiliteMenuItem(HWND hWnd
, HMENU hMenu
, WORD wItemID
, WORD wHilite
)
1555 dprintf_menu(stddeb
,"HiliteMenuItem(%04X, %04X, %04X, %04X);\n",
1556 hWnd
, hMenu
, wItemID
, wHilite
);
1557 if (!(lpitem
= MENU_FindItem( &hMenu
, &wItemID
, wHilite
))) return FALSE
;
1558 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return FALSE
;
1559 if (menu
->FocusedItem
== wItemID
) return TRUE
;
1560 MENU_HideSubPopups( hMenu
);
1561 MENU_SelectItem( hMenu
, wItemID
);
1566 /**********************************************************************
1567 * GetMenuState [USER.250]
1569 WORD
GetMenuState(HMENU hMenu
, WORD wItemID
, WORD wFlags
)
1572 dprintf_menu(stddeb
,"GetMenuState(%04X, %04X, %04X);\n",
1573 hMenu
, wItemID
, wFlags
);
1574 if (!(lpitem
= MENU_FindItem( &hMenu
, &wItemID
, wFlags
))) return -1;
1575 if (lpitem
->item_flags
& MF_POPUP
)
1577 POPUPMENU
*menu
= (POPUPMENU
*) USER_HEAP_ADDR( lpitem
->item_id
);
1578 if (!menu
) return -1;
1579 else return (menu
->nItems
<< 8) | (menu
->wFlags
& 0xff);
1581 else return lpitem
->item_flags
;
1585 /**********************************************************************
1586 * GetMenuItemCount [USER.263]
1588 WORD
GetMenuItemCount(HMENU hMenu
)
1591 dprintf_menu(stddeb
,"GetMenuItemCount(%04X);\n", hMenu
);
1592 menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
);
1593 if (menu
== NULL
) return (WORD
)-1;
1594 dprintf_menu(stddeb
,"GetMenuItemCount(%04X) return %d \n",
1595 hMenu
, menu
->nItems
);
1596 return menu
->nItems
;
1600 /**********************************************************************
1601 * GetMenuItemID [USER.264]
1603 WORD
GetMenuItemID(HMENU hMenu
, int nPos
)
1608 dprintf_menu(stddeb
,"GetMenuItemID(%04X, %d);\n", hMenu
, nPos
);
1609 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return -1;
1610 if ((nPos
< 0) || (nPos
>= menu
->nItems
)) return -1;
1611 item
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
1612 if (item
[nPos
].item_flags
& MF_POPUP
) return -1;
1613 return item
[nPos
].item_id
;
1617 /**********************************************************************
1618 * InsertMenu [USER.410]
1620 BOOL
InsertMenu(HMENU hMenu
, WORD nPos
, WORD wFlags
, WORD wItemID
, LPSTR lpNewItem
)
1623 MENUITEM
*lpitem
, *newItems
;
1626 if (IS_STRING_ITEM(wFlags
))
1627 dprintf_menu(stddeb
,"InsertMenu (%04X, %04X, %04X, '%s') !\n",
1628 hMenu
, wFlags
, wItemID
, lpNewItem
);
1630 dprintf_menu(stddeb
,"InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1631 hMenu
, nPos
, wFlags
, wItemID
, lpNewItem
);
1633 /* Find where to insert new item */
1635 if ((wFlags
& MF_BYPOSITION
) && (nPos
== (WORD
)-1))
1637 /* Special case: append to menu */
1638 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return FALSE
;
1639 nPos
= menu
->nItems
;
1643 if (!MENU_FindItem( &hMenu
, &nPos
, wFlags
)) return FALSE
;
1644 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return FALSE
;
1647 /* Create new items array */
1649 hNewItems
= USER_HEAP_ALLOC( GMEM_MOVEABLE
,
1650 sizeof(MENUITEM
) * (menu
->nItems
+1) );
1651 if (!hNewItems
) return FALSE
;
1652 newItems
= (MENUITEM
*) USER_HEAP_ADDR( hNewItems
);
1653 if (menu
->nItems
> 0)
1655 /* Copy the old array into the new */
1656 MENUITEM
*oldItems
= (MENUITEM
*) USER_HEAP_ADDR( menu
->hItems
);
1657 if (nPos
> 0) memcpy( newItems
, oldItems
, nPos
* sizeof(MENUITEM
) );
1658 if (nPos
< menu
->nItems
) memcpy( &newItems
[nPos
+1], &oldItems
[nPos
],
1659 (menu
->nItems
-nPos
)*sizeof(MENUITEM
) );
1661 USER_HEAP_FREE( menu
->hItems
);
1663 menu
->hItems
= hNewItems
;
1666 /* Store the new item data */
1668 lpitem
= &newItems
[nPos
];
1669 lpitem
->item_flags
= wFlags
& ~(MF_HILITE
| MF_MOUSESELECT
);
1670 lpitem
->item_id
= wItemID
;
1672 if (IS_STRING_ITEM(wFlags
))
1674 /* Item beginning with a backspace is a help item */
1675 if (lpNewItem
[0] == '\b')
1677 lpitem
->item_flags
|= MF_HELP
;
1680 lpitem
->hText
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, strlen(lpNewItem
)+1 );
1681 lpitem
->item_text
= (char *)USER_HEAP_ADDR( lpitem
->hText
);
1682 strcpy( lpitem
->item_text
, lpNewItem
);
1684 else if (wFlags
& MF_BITMAP
) lpitem
->hText
= LOWORD((DWORD
)lpNewItem
);
1685 else lpitem
->item_text
= lpNewItem
;
1687 if (wFlags
& MF_POPUP
) /* Set the MF_POPUP flag on the popup-menu */
1688 ((POPUPMENU
*)USER_HEAP_ADDR(wItemID
))->wFlags
|= MF_POPUP
;
1690 SetRectEmpty( &lpitem
->rect
);
1691 lpitem
->hCheckBit
= hStdCheck
;
1692 lpitem
->hUnCheckBit
= 0;
1697 /**********************************************************************
1698 * AppendMenu [USER.411]
1700 BOOL
AppendMenu(HMENU hMenu
, WORD wFlags
, WORD wItemID
, LPSTR lpNewItem
)
1702 return InsertMenu( hMenu
, -1, wFlags
| MF_BYPOSITION
, wItemID
, lpNewItem
);
1706 /**********************************************************************
1707 * RemoveMenu [USER.412]
1709 BOOL
RemoveMenu(HMENU hMenu
, WORD nPos
, WORD wFlags
)
1713 dprintf_menu(stddeb
,"RemoveMenu (%04X, %04X, %04X) !\n",
1714 hMenu
, nPos
, wFlags
);
1715 if (!(lpitem
= MENU_FindItem( &hMenu
, &nPos
, wFlags
))) return FALSE
;
1716 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return FALSE
;
1720 if (IS_STRING_ITEM(lpitem
->item_flags
)) USER_HEAP_FREE( lpitem
->hText
);
1721 if (--menu
->nItems
== 0)
1723 USER_HEAP_FREE( menu
->hItems
);
1728 while(nPos
< menu
->nItems
)
1730 *lpitem
= *(lpitem
+1);
1734 menu
->hItems
= USER_HEAP_REALLOC( menu
->hItems
,
1735 menu
->nItems
* sizeof(MENUITEM
),
1742 /**********************************************************************
1743 * DeleteMenu [USER.413]
1745 BOOL
DeleteMenu(HMENU hMenu
, WORD nPos
, WORD wFlags
)
1747 MENUITEM
*item
= MENU_FindItem( &hMenu
, &nPos
, wFlags
);
1748 if (!item
) return FALSE
;
1749 if (item
->item_flags
& MF_POPUP
) DestroyMenu( item
->item_id
);
1750 /* nPos is now the position of the item */
1751 RemoveMenu( hMenu
, nPos
, wFlags
| MF_BYPOSITION
);
1756 /**********************************************************************
1757 * ModifyMenu [USER.414]
1759 BOOL
ModifyMenu(HMENU hMenu
, WORD nPos
, WORD wFlags
, WORD wItemID
, LPSTR lpNewItem
)
1762 if (IS_STRING_ITEM(wFlags
))
1763 dprintf_menu(stddeb
,"ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
1764 hMenu
, nPos
, wFlags
, wItemID
, lpNewItem
);
1766 dprintf_menu(stddeb
,"ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1767 hMenu
, nPos
, wFlags
, wItemID
, lpNewItem
);
1768 if (!(lpitem
= MENU_FindItem( &hMenu
, &nPos
, wFlags
))) return FALSE
;
1770 if (IS_STRING_ITEM(lpitem
->item_flags
)) USER_HEAP_FREE( lpitem
->hText
);
1771 lpitem
->item_flags
= wFlags
& ~(MF_HILITE
| MF_MOUSESELECT
);
1772 lpitem
->item_id
= wItemID
;
1774 if (IS_STRING_ITEM(wFlags
))
1776 lpitem
->hText
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, strlen(lpNewItem
)+1 );
1777 lpitem
->item_text
= (char *)USER_HEAP_ADDR( lpitem
->hText
);
1778 strcpy( lpitem
->item_text
, lpNewItem
);
1780 else if (wFlags
& MF_BITMAP
) lpitem
->hText
= LOWORD((DWORD
)lpNewItem
);
1781 else lpitem
->item_text
= lpNewItem
;
1782 SetRectEmpty( &lpitem
->rect
);
1787 /**********************************************************************
1788 * CreatePopupMenu [USER.415]
1790 HMENU
CreatePopupMenu()
1795 if (!(hmenu
= CreateMenu())) return 0;
1796 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hmenu
);
1797 menu
->wFlags
|= MF_POPUP
;
1802 /**********************************************************************
1803 * GetMenuCheckMarkDimensions [USER.417]
1805 DWORD
GetMenuCheckMarkDimensions()
1807 return MAKELONG( check_bitmap_width
, check_bitmap_height
);
1811 /**********************************************************************
1812 * SetMenuItemBitmaps [USER.418]
1814 BOOL
SetMenuItemBitmaps(HMENU hMenu
, WORD nPos
, WORD wFlags
,
1815 HBITMAP hNewCheck
, HBITMAP hNewUnCheck
)
1818 dprintf_menu(stddeb
,"SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
1819 hMenu
, nPos
, wFlags
, hNewCheck
, hNewUnCheck
);
1820 if (!(lpitem
= MENU_FindItem( &hMenu
, &nPos
, wFlags
))) return FALSE
;
1822 if (!hNewCheck
&& !hNewUnCheck
)
1824 /* If both are NULL, restore default bitmaps */
1825 lpitem
->hCheckBit
= hStdCheck
;
1826 lpitem
->hUnCheckBit
= 0;
1827 lpitem
->item_flags
&= ~MF_USECHECKBITMAPS
;
1829 else /* Install new bitmaps */
1831 lpitem
->hCheckBit
= hNewCheck
;
1832 lpitem
->hUnCheckBit
= hNewUnCheck
;
1833 lpitem
->item_flags
|= MF_USECHECKBITMAPS
;
1839 /**********************************************************************
1840 * CreateMenu [USER.151]
1846 dprintf_menu(stddeb
,"CreateMenu !\n");
1847 if (!(hMenu
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(POPUPMENU
) )))
1849 menu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
);
1852 menu
->wMagic
= MENU_MAGIC
;
1859 menu
->FocusedItem
= NO_SELECTED_ITEM
;
1860 dprintf_menu(stddeb
,"CreateMenu // return %04X\n", hMenu
);
1865 /**********************************************************************
1866 * DestroyMenu [USER.152]
1868 BOOL
DestroyMenu(HMENU hMenu
)
1871 dprintf_menu(stddeb
,"DestroyMenu (%04X) !\n", hMenu
);
1872 if (hMenu
== 0) return FALSE
;
1873 lppop
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
);
1874 if (lppop
== NULL
) return FALSE
;
1875 if (lppop
->hWnd
) DestroyWindow (lppop
->hWnd
);
1880 MENUITEM
*item
= (MENUITEM
*) USER_HEAP_ADDR( lppop
->hItems
);
1881 for (i
= lppop
->nItems
; i
> 0; i
--, item
++)
1883 if (item
->item_flags
& MF_POPUP
)
1884 DestroyMenu( item
->item_id
);
1886 USER_HEAP_FREE( lppop
->hItems
);
1888 USER_HEAP_FREE( hMenu
);
1889 dprintf_menu(stddeb
,"DestroyMenu (%04X) // End !\n", hMenu
);
1893 /**********************************************************************
1894 * GetSystemMenu [USER.156]
1896 HMENU
GetSystemMenu(HWND hWnd
, BOOL bRevert
)
1899 wndPtr
= WIN_FindWndPtr(hWnd
);
1901 return wndPtr
->hSysMenu
;
1904 DestroyMenu(wndPtr
->hSysMenu
);
1905 wndPtr
->hSysMenu
= CopySysMenu();
1907 return wndPtr
->hSysMenu
;
1910 /**********************************************************************
1911 * SetSystemMenu [USER.280]
1913 BOOL
SetSystemMenu(HWND hWnd
, HMENU newHmenu
)
1917 if ((wndPtr
= WIN_FindWndPtr(hWnd
)) != NULL
)
1918 wndPtr
->hSysMenu
= newHmenu
;
1922 /**********************************************************************
1923 * GetMenu [USER.157]
1925 HMENU
GetMenu(HWND hWnd
)
1927 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
1928 if (wndPtr
== NULL
) return 0;
1929 return wndPtr
->wIDmenu
;
1933 /**********************************************************************
1934 * SetMenu [USER.158]
1936 BOOL
SetMenu(HWND hWnd
, HMENU hMenu
)
1939 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
1940 if (wndPtr
== NULL
) {
1941 fprintf(stderr
,"SetMenu(%04X, %04X) // Bad window handle !\n",
1945 dprintf_menu(stddeb
,"SetMenu(%04X, %04X);\n", hWnd
, hMenu
);
1946 if (GetCapture() == hWnd
) ReleaseCapture();
1947 wndPtr
->wIDmenu
= hMenu
;
1950 lpmenu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
);
1951 if (lpmenu
== NULL
) {
1952 fprintf(stderr
,"SetMenu(%04X, %04X) // Bad menu handle !\n",
1956 lpmenu
->hWnd
= hWnd
;
1957 lpmenu
->wFlags
&= ~MF_POPUP
; /* Can't be a popup */
1958 lpmenu
->Height
= 0; /* Make sure we recalculate the size */
1960 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1961 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1967 /**********************************************************************
1968 * GetSubMenu [USER.159]
1970 HMENU
GetSubMenu(HMENU hMenu
, short nPos
)
1974 dprintf_menu(stddeb
,"GetSubMenu (%04X, %04X) !\n", hMenu
, nPos
);
1975 if (!(lppop
= (LPPOPUPMENU
) USER_HEAP_ADDR(hMenu
))) return 0;
1976 if ((WORD
)nPos
>= lppop
->nItems
) return 0;
1977 lpitem
= (MENUITEM
*) USER_HEAP_ADDR( lppop
->hItems
);
1978 if (!(lpitem
[nPos
].item_flags
& MF_POPUP
)) return 0;
1979 return lpitem
[nPos
].item_id
;
1983 /**********************************************************************
1984 * DrawMenuBar [USER.160]
1986 void DrawMenuBar(HWND hWnd
)
1990 dprintf_menu(stddeb
,"DrawMenuBar (%04X)\n", hWnd
);
1991 wndPtr
= WIN_FindWndPtr(hWnd
);
1992 if (wndPtr
!= NULL
&& (wndPtr
->dwStyle
& WS_CHILD
) == 0 &&
1993 wndPtr
->wIDmenu
!= 0) {
1994 dprintf_menu(stddeb
,"DrawMenuBar wIDmenu=%04X \n",
1996 lppop
= (LPPOPUPMENU
) USER_HEAP_ADDR(wndPtr
->wIDmenu
);
1997 if (lppop
== NULL
) return;
1999 lppop
->Height
= 0; /* Make sure we call MENU_MenuBarCalcSize */
2000 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
2001 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
2006 /***********************************************************************
2007 * EndMenu (USER.187)
2011 /* Note: this won't work when we have multiple tasks... */
2012 fEndMenuCalled
= TRUE
;
2016 /***********************************************************************
2017 * LookupMenuHandle (USER.217)
2019 HMENU
LookupMenuHandle( HMENU hmenu
, INT id
)
2021 if (!MENU_FindItem( &hmenu
, &id
, MF_BYCOMMAND
)) return 0;
2026 /**********************************************************************
2027 * LoadMenuIndirect [USER.220]
2029 HMENU
LoadMenuIndirect(LPSTR menu_template
)
2032 MENU_HEADER
*menu_desc
;
2033 dprintf_menu(stddeb
,"LoadMenuIndirect: menu_template '%08X'\n",
2035 hMenu
= CreateMenu();
2036 menu_desc
= (MENU_HEADER
*)menu_template
;
2037 ParseMenuResource((WORD
*)(menu_desc
+ 1), 0, hMenu
);
2042 /**********************************************************************
2043 * CopySysMenu (Internal)
2048 LPPOPUPMENU sysmenu
, menu
;
2052 sysmenu
= (LPPOPUPMENU
) USER_HEAP_ADDR(hSysMenu
);
2053 if (!(hMenu
= CreatePopupMenu())) return 0;
2054 menu
= (POPUPMENU
*) USER_HEAP_ADDR( hMenu
);
2055 menu
->wFlags
|= MF_SYSMENU
;
2056 item
= (MENUITEM
*) USER_HEAP_ADDR( sysmenu
->hItems
);
2057 for (i
= 0; i
< sysmenu
->nItems
; i
++, item
++)
2059 AppendMenu( hMenu
, item
->item_flags
, item
->item_id
, item
->item_text
);
2062 dprintf_menu(stddeb
,"CopySysMenu hMenu=%04X !\n", hMenu
);
2067 /**********************************************************************
2068 * ParseMenuResource (from Resource or Template)
2070 WORD
* ParseMenuResource(WORD
*first_item
, int level
, HMENU hMenu
)
2078 next_item
= first_item
;
2083 if (*item
& MF_POPUP
) {
2084 MENU_POPUPITEM
*popup_item
= (MENU_POPUPITEM
*) item
;
2085 next_item
= (WORD
*) (popup_item
->item_text
+
2086 strlen(popup_item
->item_text
) + 1);
2087 hSubMenu
= CreatePopupMenu();
2088 next_item
= ParseMenuResource(next_item
, level
, hSubMenu
);
2089 AppendMenu(hMenu
, popup_item
->item_flags
,
2090 hSubMenu
, popup_item
->item_text
);
2093 MENUITEMTEMPLATE
*normal_item
= (MENUITEMTEMPLATE
*) item
;
2094 next_item
= (WORD
*) (normal_item
->item_text
+
2095 strlen(normal_item
->item_text
) + 1);
2096 if (strlen(normal_item
->item_text
) == 0 && normal_item
->item_id
== 0)
2097 normal_item
->item_flags
|= MF_SEPARATOR
;
2098 AppendMenu(hMenu
, normal_item
->item_flags
,
2099 normal_item
->item_id
, normal_item
->item_text
);
2102 while (!(*item
& MF_END
));
2107 /**********************************************************************
2110 BOOL
IsMenu( HMENU hmenu
)
2113 if (!(menu
= (LPPOPUPMENU
) USER_HEAP_ADDR( hmenu
))) return FALSE
;
2114 return (menu
->wMagic
== MENU_MAGIC
);