LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
+ WINE_DEFAULT_DEBUG_CHANNEL(menu);
+
/* internal popup menu window messages */
-#define MM_SETMENUHANDLE (WM_USER + 0)
-#define MM_GETMENUHANDLE (WM_USER + 1)
+
+#define MM_SETMENUHANDLE (WM_USER + 0)
+#define MM_GETMENUHANDLE (WM_USER + 1)
+ /* internal flags for menu tracking */
+
+ #define TF_ENDMENU 0x10000
+ #define TF_SUSPENDPOPUP 0x20000
+ #define TF_SKIPREMOVE 0x40000
+
+ #define ITEM_PREV -1
+ #define ITEM_NEXT 1
+
/* Internal MenuTrackMenu() flags */
#define TPM_INTERNAL 0xF0000000
- #define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
HeapFree(GetProcessHeap(), 0, ItemInfo);
}
-
/***********************************************************************
- * MenuLoadBitmaps
+ * MenuInitSysMenuPopup
*
- * Load the arrow bitmap. We can't do this from MenuInit since user32
- * can also be used (and thus initialized) from text-mode.
+ * Grey the appropriate items in System menu.
*/
- static void FASTCALL
- MenuLoadBitmaps(VOID)
+ void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LONG HitTest )
{
- /* Load system buttons bitmaps */
- if (NULL == BmpSysMenu)
+ BOOL gray;
+ UINT DefItem;
+ #if 0
+ MENUITEMINFOW mii;
+ #endif
+
+ gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = ((style & WS_MAXIMIZE) != 0);
+ EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+ EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+ EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = (clsStyle & CS_NOCLOSE) != 0;
+
+ /* The menu item must keep its state if it's disabled */
+ if(gray)
+ EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
+
+ /* Set default menu item */
+ if(style & WS_MINIMIZE) DefItem = SC_RESTORE;
+ else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
+ else DefItem = SC_CLOSE;
+ #if 0
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask |= MIIM_STATE;
+ if((DefItem != SC_CLOSE) && GetMenuItemInfoW(hmenu, DefItem, FALSE, &mii) &&
+ (mii.fState & (MFS_GRAYED | MFS_DISABLED))) DefItem = SC_CLOSE;
+ #endif
+ SetMenuDefaultItem(hmenu, DefItem, MF_BYCOMMAND);
+ }
+
+ /******************************************************************************
+ *
+ * UINT MenuGetStartOfNextColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+ static UINT MenuGetStartOfNextColumn(
+ PROSMENUINFO MenuInfo)
-{
+ {
- BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ i = MenuInfo->FocusedItem;
+ if ( i == NO_SELECTED_ITEM )
+ return i;
+
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
+
+ for (i++ ; i < MenuInfo->MenuItemCount; i++)
+ if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
+ return i;
+
+ return NO_SELECTED_ITEM;
-}
+ }
- }
- /***********************************************************************
- * MenuGetBitmapItemSize
+ /******************************************************************************
*
- * Get the size of a bitmap item.
- */
- static void FASTCALL
- MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
+ * UINT MenuGetStartOfPrevColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+
+ static UINT FASTCALL MenuGetStartOfPrevColumn(
+ PROSMENUINFO MenuInfo)
{
- BITMAP Bm;
- HBITMAP Bmp = lpitem->hbmpItem;
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM)
+ return NO_SELECTED_ITEM;
- Size->cx = Size->cy = 0;
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
- /* check if there is a magic menu item associated with this item */
- if (IS_MAGIC_BITMAP(Bmp))
+ /* Find the start of the column */
+ for (i = MenuInfo->FocusedItem;
+ 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+ --i)
{
- switch((INT_PTR) Bmp)
+ ; /* empty */
+ }
+
+ if (i == 0)
- {
+ {
- case (INT_PTR)HBMMENU_CALLBACK:
- {
- MEASUREITEMSTRUCT measItem;
- measItem.CtlType = ODT_MENU;
- measItem.CtlID = 0;
- measItem.itemID = lpitem->wID;
- measItem.itemWidth = lpitem->Rect.right - lpitem->Rect.left;
- measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top;
- measItem.itemData = lpitem->dwItemData;
- SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
- Size->cx = measItem.itemWidth;
- Size->cy = measItem.itemHeight;
- return;
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ return NO_SELECTED_ITEM;
- }
+ }
+
+ for (--i; 0 != i; --i)
+ if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
break;
- case (INT_PTR) HBMMENU_SYSTEM:
- if (0 != lpitem->dwItemData)
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ TRACE("ret %d.\n", i );
+
+ return i;
+ }
+
+ /***********************************************************************
+ * MenuFindSubMenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+ static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
-{
+ {
- Bmp = (HBITMAP)(ULONG_PTR) lpitem->dwItemData;
- break;
+ ROSMENUINFO menu;
+ UINT i;
+ ROSMENUITEMINFO item;
+ if (((*hmenu)==(HMENU)0xffff) ||
+ (!MenuGetRosMenuInfo(&menu, *hmenu)))
+ return NO_SELECTED_ITEM;
+
+ MenuInitRosMenuItemInfo(&item);
+ for (i = 0; i < menu.MenuItemCount; i++) {
+ if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
+ {
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
- }
+ }
- /* fall through */
- case (INT_PTR) HBMMENU_MBAR_RESTORE:
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
- case (INT_PTR) HBMMENU_MBAR_CLOSE:
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
- case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
- case (INT_PTR) HBMMENU_POPUP_CLOSE:
- case (INT_PTR) HBMMENU_POPUP_RESTORE:
- case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
- case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
- /* FIXME: Why we need to subtract these magic values? */
- /* to make them smaller than the menu bar? */
- Size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
- Size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
- return;
+ if (!(item.fType & MF_POPUP)) continue;
+ if (item.hSubMenu == hSubTarget) {
+ MenuCleanupRosMenuItemInfo(&item);
+ return i;
+ }
+ else {
+ HMENU hsubmenu = item.hSubMenu;
+ UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
+ if (pos != NO_SELECTED_ITEM) {
+ *hmenu = hsubmenu;
+ return pos;
- }
++ }
}
}
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
+ }
- if (GetObjectW(Bmp, sizeof(BITMAP), &Bm))
+ /***********************************************************************
+ * MenuLoadBitmaps
+ *
+ * Load the arrow bitmap. We can't do this from MenuInit since user32
+ * can also be used (and thus initialized) from text-mode.
+ */
+ static void FASTCALL
+ MenuLoadBitmaps(VOID)
-{
++ {
+ /* Load system buttons bitmaps */
+ if (NULL == BmpSysMenu)
{
- Size->cx = Bm.bmWidth;
- Size->cy = Bm.bmHeight;
+ BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
}
}
*
* Draw a bitmap item.
*/
- static void FASTCALL
- MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
+ static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const RECT *rect,
HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar)
{
- BITMAP Bm;
- DWORD Rop;
- HDC DcMem;
- HBITMAP Bmp;
- int w = Rect->right - Rect->left;
- int h = Rect->bottom - Rect->top;
- int BmpXoffset = 0;
- int Left, Top;
- HBITMAP hbmpToDraw = (HBITMAP) Item->hbmpItem;
- Bmp = hbmpToDraw;
+ BITMAP bm;
+ DWORD rop;
+ HDC hdcMem;
+ HBITMAP bmp;
+ int w = rect->right - rect->left;
+ int h = rect->bottom - rect->top;
+ int bmp_xoffset = 0;
+ int left, top;
+ HBITMAP hbmToDraw = lpitem->hbmpItem;
+ bmp = hbmToDraw;
- /* Check if there is a magic menu item associated with this item */
+ /* Check if there is a magic menu item associated with this item */
- if (IS_MAGIC_BITMAP(hbmpToDraw))
+ if (IS_MAGIC_BITMAP(hbmToDraw))
{
- UINT Flags = 0;
+ UINT flags = 0;
- RECT r;
+ RECT r;
- r = *Rect;
- switch ((INT_PTR)hbmpToDraw)
+ r = *rect;
+ switch ((INT_PTR)hbmToDraw)
{
- case (INT_PTR)HBMMENU_SYSTEM:
+ case (INT_PTR) HBMMENU_SYSTEM:
- if (NULL != Item->dwTypeData)
+ if (lpitem->dwTypeData)
- {
+ {
- Bmp = (HBITMAP)Item->dwTypeData;
- if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- return;
+ bmp = (HBITMAP)lpitem->dwTypeData;
+ if (!GetObjectW( bmp, sizeof(bm), &bm )) return;
- }
+ }
- }
else
- {
+ {
if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
- Bmp = BmpSysMenu;
- if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- return;
- }
+ bmp = BmpSysMenu;
+ if (! GetObjectW(bmp, sizeof(bm), &bm)) return;
/* only use right half of the bitmap */
- BmpXoffset = Bm.bmWidth / 2;
- Bm.bmWidth -= BmpXoffset;
+ bmp_xoffset = bm.bmWidth / 2;
+ bm.bmWidth -= bmp_xoffset;
- }
+ }
goto got_bitmap;
- case (INT_PTR)HBMMENU_MBAR_RESTORE:
+ case (INT_PTR) HBMMENU_MBAR_RESTORE:
- Flags = DFCS_CAPTIONRESTORE;
+ flags = DFCS_CAPTIONRESTORE;
break;
- case (INT_PTR)HBMMENU_MBAR_MINIMIZE:
+ case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
r.right += 1;
- Flags = DFCS_CAPTIONMIN;
+ flags = DFCS_CAPTIONMIN;
break;
- case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D:
+ case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
r.right += 1;
- Flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
+ flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
break;
- case (INT_PTR)HBMMENU_MBAR_CLOSE:
+ case (INT_PTR) HBMMENU_MBAR_CLOSE:
- Flags = DFCS_CAPTIONCLOSE;
+ flags = DFCS_CAPTIONCLOSE;
break;
- case (INT_PTR)HBMMENU_MBAR_CLOSE_D:
+ case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
- Flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
+ flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
break;
- case (INT_PTR)HBMMENU_CALLBACK:
+ case (INT_PTR) HBMMENU_CALLBACK:
{
DRAWITEMSTRUCT drawItem;
POINT origorg;
return;
}
InflateRect(&r, -1, -1);
- if (0 != (Item->fState & MF_HILITE))
+ if (0 != (lpitem->fState & MF_HILITE))
- {
+ {
- Flags |= DFCS_PUSHED;
+ flags |= DFCS_PUSHED;
- }
+ }
- DrawFrameControl(Dc, &r, DFC_CAPTION, Flags);
+ DrawFrameControl(hdc, &r, DFC_CAPTION, flags);
return;
}
- if (NULL == Bmp || ! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- return;
- }
+ if (!bmp || !GetObjectW( bmp, sizeof(bm), &bm )) return;
- got_bitmap:
- DcMem = CreateCompatibleDC(Dc);
- SelectObject(DcMem, Bmp);
+ got_bitmap:
+ hdcMem = CreateCompatibleDC( hdc );
+ SelectObject( hdcMem, bmp );
- /* handle fontsize > bitmap_height */
- Top = (Bm.bmHeight < h) ? Rect->top + (h - Bm.bmHeight) / 2 : Rect->top;
- Left = Rect->left;
- Rop= ((Item->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmpToDraw)) ? NOTSRCCOPY : SRCCOPY;
- if ((Item->fState & MF_HILITE) && Item->hbmpItem)
- {
- SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
- }
- BitBlt(Dc, Left, Top, w, h, DcMem, BmpXoffset, 0, Rop);
- DeleteDC(DcMem);
+ /* handle fontsize > bitmap_height */
+ top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top;
+ left=rect->left;
+ rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmToDraw)) ? NOTSRCCOPY : SRCCOPY;
+ if ((lpitem->fState & MF_HILITE) && lpitem->hbmpItem)
+ SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+ BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop );
+ DeleteDC( hdcMem );
+ }
+
+ /***********************************************************************
+ * MenuCalcItemSize
+ *
+ * Calculate the size of the menu item and store it in lpitem->rect.
+ */
+ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMENUINFO MenuInfo, HWND hwndOwner,
+ INT orgX, INT orgY, BOOL menuBar)
-{
++ {
+ WCHAR *p;
+ UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+ INT itemheight = 0;
+
+ TRACE("dc=%x owner=%x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
+
+ MenuCharSize.cx = GdiGetCharDimensions( hdc, NULL, &MenuCharSize.cy );
+
+ SetRect( &lpitem->Rect, orgX, orgY, orgX, orgY );
+
+ if (lpitem->fType & MF_OWNERDRAW)
+ {
+ MEASUREITEMSTRUCT mis;
+ mis.CtlType = ODT_MENU;
+ mis.CtlID = 0;
+ mis.itemID = lpitem->wID;
+ mis.itemData = lpitem->dwItemData;
+ mis.itemHeight = HIWORD( GetDialogBaseUnits());
+ mis.itemWidth = 0;
+ SendMessageW( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
+ /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average
+ * width of a menufont character to the width of an owner-drawn menu.
+ */
+ lpitem->Rect.right += mis.itemWidth + 2 * MenuCharSize.cx;
+
+ if (menuBar) {
+ /* under at least win95 you seem to be given a standard
+ height for the menu and the height value is ignored */
+ lpitem->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
+ } else
+ lpitem->Rect.bottom += mis.itemHeight;
+
+ TRACE("id=%04lx size=%dx%d\n",
+ lpitem->wID, mis.itemWidth, mis.itemHeight);
- return;
++ return;
+ }
+
+ if (lpitem->fType & MF_SEPARATOR)
+ {
+ lpitem->Rect.bottom += SEPARATOR_HEIGHT;
+ if( !menuBar)
+ lpitem->Rect.right += check_bitmap_width + MenuCharSize.cx;
+ return;
+ }
+
+ lpitem->dxTab = 0;
+
+ if (lpitem->hbmpItem)
+ {
+ SIZE size;
+
+ if (!menuBar) {
+ MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+ /* Keep the size of the bitmap in callback mode to be able
+ * to draw it correctly */
+ lpitem->Rect.right = lpitem->Rect.left + size.cx;
+ if (MenuInfo->maxBmpSize.cx < abs(size.cx) + MENU_ITEM_HBMP_SPACE ||
+ MenuInfo->maxBmpSize.cy < abs(size.cy))
+ {
+ MenuInfo->maxBmpSize.cx = abs(size.cx) + MENU_ITEM_HBMP_SPACE;
+ MenuInfo->maxBmpSize.cy = abs(size.cy);
- }
++ }
+ MenuSetRosMenuInfo(MenuInfo);
+ itemheight = size.cy + 2;
+
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ lpitem->Rect.right += 2 * check_bitmap_width;
+ lpitem->Rect.right += 4 + MenuCharSize.cx;
+ lpitem->dxTab = lpitem->Rect.right;
+ lpitem->Rect.right += check_bitmap_width;
+ } else /* hbmpItem & MenuBar */ {
+ MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+ lpitem->Rect.right += size.cx;
+ if( lpitem->lpstr) lpitem->Rect.right += 2;
+ itemheight = size.cy;
+
+ /* Special case: Minimize button doesn't have a space behind it. */
+ if (lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
+ lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
+ lpitem->Rect.right -= 1;
- }
++}
+ }
+ else if (!menuBar) {
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ lpitem->Rect.right += check_bitmap_width;
+ lpitem->Rect.right += 4 + MenuCharSize.cx;
+ lpitem->dxTab = lpitem->Rect.right;
+ lpitem->Rect.right += check_bitmap_width;
+ }
+
+ /* it must be a text item - unless it's the system menu */
+ if (!(lpitem->fType & MF_SYSMENU) && lpitem->lpstr) {
+ HFONT hfontOld = NULL;
+ RECT rc = lpitem->Rect;
+ LONG txtheight, txtwidth;
+
+ if ( lpitem->fState & MFS_DEFAULT ) {
+ hfontOld = SelectObject( hdc, hMenuFontBold );
+ }
+ if (menuBar) {
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->Rect.right += rc.right - rc.left;
+ itemheight = max( max( itemheight, txtheight),
+ GetSystemMetrics( SM_CYMENU) - 1);
+ lpitem->Rect.right += 2 * MenuCharSize.cx;
+ } else {
+ if ((p = strchrW( lpitem->dwTypeData, '\t' )) != NULL) {
+ RECT tmprc = rc;
+ LONG tmpheight;
+ int n = (int)( p - lpitem->dwTypeData);
+ /* Item contains a tab (only meaningful in popup menus) */
+ /* get text size before the tab */
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, n, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ p += 1; /* advance past the Tab */
+ /* get text size after the tab */
+ tmpheight = DrawTextW( hdc, p, -1, &tmprc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->dxTab += txtwidth;
+ txtheight = max( txtheight, tmpheight);
+ txtwidth += MenuCharSize.cx + /* space for the tab */
+ tmprc.right - tmprc.left; /* space for the short cut */
+ } else {
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ lpitem->dxTab += txtwidth;
+ }
+ lpitem->Rect.right += 2 + txtwidth;
+ itemheight = max( itemheight,
+ max( txtheight + 2, MenuCharSize.cy + 4));
+ }
+ if (hfontOld) SelectObject (hdc, hfontOld);
+ } else if( menuBar) {
+ itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
+ }
+ lpitem->Rect.bottom += itemheight;
+ TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->Rect.left, lpitem->Rect.top, lpitem->Rect.right, lpitem->Rect.bottom);
+ }
+
+ /***********************************************************************
+ * MenuPopupMenuCalcSize
+ *
+ * Calculate the size of a popup menu.
+ */
+ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
+ {
+ ROSMENUITEMINFO lpitem;
+ HDC hdc;
+ int start, i;
+ int orgX, orgY, maxX, maxTab, maxTabWidth;
+
+ MenuInfo->Width = MenuInfo->Height = 0;
+ if (MenuInfo->MenuItemCount == 0)
+ {
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
+ }
+
+ hdc = GetDC(NULL);
+ SelectObject( hdc, hMenuFont );
+
+ start = 0;
+ maxX = 2 + 1;
+
+ MenuInfo->maxBmpSize.cx = 0;
+ MenuInfo->maxBmpSize.cy = 0;
+
+ MenuInitRosMenuItemInfo(&lpitem);
+ while (start < MenuInfo->MenuItemCount)
+ {
+ orgX = maxX;
+ orgY = 2;
+
+ maxTab = maxTabWidth = 0;
+
+ /* Parse items until column break or end of menu */
+ for (i = start; i < MenuInfo->MenuItemCount; i++)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+ {
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
+ }
+ if (i != start &&
+ (lpitem.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+ MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE);
+ if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+ {
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
+ }
+ // Not sure here,, The patch from wine removes this.
+ // if ((lpitem.fType & MF_MENUBARBREAK) != 0)
+ // {
+ // OrgX++;
+ // }
+ maxX = max(maxX, lpitem.Rect.right);
+ orgY = lpitem.Rect.bottom;
+ if ((lpitem.lpstr) && lpitem.dxTab )
+ {
+ maxTab = max( maxTab, lpitem.dxTab );
+ maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab);
+ }
+ }
+
+ /* Finish the column (set all items to the largest width found) */
+ maxX = max( maxX, maxTab + maxTabWidth );
+ while (start < i)
+ {
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem))
+ {
+ lpitem.Rect.right = maxX;
+ if ((lpitem.lpstr) && 0 != lpitem.dxTab)
+ {
+ lpitem.dxTab = maxTab;
+ }
+ MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem);
+ }
+ start++;
+ }
+ MenuInfo->Height = max(MenuInfo->Height, orgY);
+ }
+
+ MenuInfo->Width = maxX;
+
+ /* space for 3d border */
+ MenuInfo->Height += 2;
+ MenuInfo->Width += 2;
+
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ ReleaseDC( 0, hdc );
+ }
+
+ /***********************************************************************
+ * MenuMenuBarCalcSize
+ *
+ * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
+ * height is off by 1 pixel which causes lengthy window relocations when
+ * active document window is maximized/restored.
+ *
+ * Calculate the size of the menu bar.
+ */
+ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect,
+ PROSMENUINFO MenuInfo, HWND hwndOwner )
+ {
+ ROSMENUITEMINFO ItemInfo;
+ int start, i, orgX, orgY, maxY, helpPos;
+
+ if ((lprect == NULL) || (MenuInfo == NULL)) return;
+ if (MenuInfo->MenuItemCount == 0) return;
+ TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+ MenuInfo->Width = lprect->right - lprect->left;
+ MenuInfo->Height = 0;
+ maxY = lprect->top + 1;
+ start = 0;
+ helpPos = -1;
+
+ MenuInfo->maxBmpSize.cx = 0;
+ MenuInfo->maxBmpSize.cy = 0;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+ while (start < MenuInfo->MenuItemCount)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ orgX = lprect->left;
+ orgY = maxY;
+
+ /* Parse items until line break or end of menu */
+ for (i = start; i < MenuInfo->MenuItemCount; i++)
+ {
+ if ((helpPos == -1) && (ItemInfo.fType & MF_RIGHTJUSTIFY)) helpPos = i;
+ if ((i != start) &&
+ (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+ TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY);
+ MenuCalcItemSize(hdc, &ItemInfo, MenuInfo, hwndOwner, orgX, orgY, TRUE);
+ if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+
+ if (ItemInfo.Rect.right > lprect->right)
+ {
+ if (i != start) break;
+ else ItemInfo.Rect.right = lprect->right;
+ }
+ maxY = max( maxY, ItemInfo.Rect.bottom );
+ orgX = ItemInfo.Rect.right;
+ if (i + 1 < MenuInfo->MenuItemCount)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ }
+ }
+
+ /* FIXME: Is this really needed? */ /*NO! it is not needed, why make the
+ HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */
+ #if 0
+ /* Finish the line (set all items to the largest height found) */
+ while (start < i)
+ {
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+ {
+ ItemInfo.Rect.bottom = maxY;
+ MenuSetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo);
+ }
+ start++;
+ }
+ #else
+ start = i; /* This works! */
+ #endif
+ }
+
+ lprect->bottom = maxY;
+ MenuInfo->Height = lprect->bottom - lprect->top;
+ MenuSetRosMenuInfo(MenuInfo);
+
+ if (helpPos != -1)
+ {
+ /* Flush right all items between the MF_RIGHTJUSTIFY and */
+ /* the last item (if several lines, only move the last line) */
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ orgY = ItemInfo.Rect.top;
+ orgX = lprect->right;
+ for (i = MenuInfo->MenuItemCount - 1; helpPos <= i; i--)
+ {
+ if (i < helpPos)
+ {
+ break; /* done */
+ }
+ if (ItemInfo.Rect.top != orgY)
+ {
+ break; /* Other line */
+ }
+ if (orgX <= ItemInfo.Rect.right)
+ {
+ break; /* Too far right already */
+ }
+ ItemInfo.Rect.left += orgX - ItemInfo.Rect.right;
+ ItemInfo.Rect.right = orgX;
+ orgX = ItemInfo.Rect.left;
+ MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
+ if (helpPos + 1 <= i &&
+ ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ }
+ }
+
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
}
/***********************************************************************
*
* Draw a single menu item.
*/
- static void FASTCALL
- MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
- PROSMENUITEMINFO Item, UINT Height, BOOL MenuBar, UINT Action)
+ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC hdc,
+ PROSMENUITEMINFO lpitem, UINT Height, BOOL menuBar, UINT odaction)
{
- RECT Rect;
+ RECT rect;
- PWCHAR Text;
- BOOL flat_menu = FALSE;
- int bkgnd;
- PWND Wnd = ValidateHwnd(hWnd);
+ PWCHAR Text;
+ BOOL flat_menu = FALSE;
+ int bkgnd;
+ PWND Wnd = ValidateHwnd(hWnd);
- if (!Wnd)
+ if (!Wnd)
return;
- if (0 != (Item->fType & MF_SYSMENU))
+ if (lpitem->fType & MF_SYSMENU)
{
- if ( (Wnd->style & WS_MINIMIZE))
+ if ( (Wnd->style & WS_MINIMIZE))
{
- UserGetInsideRectNC(Wnd, &Rect);
- UserDrawSysMenuButton(hWnd, Dc, &Rect,
- Item->fState & (MF_HILITE | MF_MOUSESELECT));
+ UserGetInsideRectNC(Wnd, &rect);
+ UserDrawSysMenuButton(hWnd, hdc, &rect,
+ lpitem->fState & (MF_HILITE | MF_MOUSESELECT));
- }
- return;
+ }
+ return;
}
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
- bkgnd = (MenuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
+ bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
-
- /* Setup colors */
+
+ /* Setup colors */
- if (0 != (Item->fState & MF_HILITE))
+ if (lpitem->fState & MF_HILITE)
{
- if (MenuBar && !flat_menu)
- {
- SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
- SetBkColor(Dc, GetSysColor(COLOR_MENU));
- }
+ if(menuBar && !flat_menu) {
+ SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
+ SetBkColor(hdc, GetSysColor(COLOR_MENU));
+ } else {
+ if (lpitem->fState & MF_GRAYED)
+ SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
- else
+ else
- {
- if (0 != (Item->fState & MF_GRAYED))
- {
- SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
+ SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
- }
- }
- else
+ }
- else
- {
- SetTextColor(Dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
- SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
- }
- }
+ else
{
- if (0 != (Item->fState & MF_GRAYED))
- {
- SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
- }
+ if (lpitem->fState & MF_GRAYED)
+ SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
- else
+ else
- {
- SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
+ SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
+ SetBkColor( hdc, GetSysColor( bkgnd ) );
- }
+ }
- SetBkColor(Dc, GetSysColor(bkgnd));
- }
- Rect = Item->Rect;
+ rect = lpitem->Rect;
- if (Item->fType & MF_OWNERDRAW)
+ if (lpitem->fType & MF_OWNERDRAW)
{
- /*
- ** Experimentation under Windows reveals that an owner-drawn
- ** menu is given the rectangle which includes the space it requested
- ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
- ** and a popup-menu arrow. This is the value of lpitem->rect.
- ** Windows will leave all drawing to the application except for
- ** the popup-menu arrow. Windows always draws that itself, after
- ** the menu owner has finished drawing.
- */
- DRAWITEMSTRUCT dis;
-
- dis.CtlType = ODT_MENU;
- dis.CtlID = 0;
+ /*
+ ** Experimentation under Windows reveals that an owner-drawn
+ ** menu is given the rectangle which includes the space it requested
+ ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
+ ** and a popup-menu arrow. This is the value of lpitem->rect.
+ ** Windows will leave all drawing to the application except for
+ ** the popup-menu arrow. Windows always draws that itself, after
+ ** the menu owner has finished drawing.
+ */
+ DRAWITEMSTRUCT dis;
+
+ dis.CtlType = ODT_MENU;
+ dis.CtlID = 0;
- dis.itemID = Item->wID;
- dis.itemData = (DWORD)Item->dwItemData;
+ dis.itemID = lpitem->wID;
+ dis.itemData = (DWORD)lpitem->dwItemData;
- dis.itemState = 0;
+ dis.itemState = 0;
- if (0 != (Item->fState & MF_CHECKED))
- {
- dis.itemState |= ODS_CHECKED;
- }
- if (0 != (Item->fState & MF_GRAYED))
- {
- dis.itemState |= ODS_GRAYED | ODS_DISABLED;
- }
- if (0 != (Item->fState & MF_HILITE))
- {
- dis.itemState |= ODS_SELECTED;
- }
- dis.itemAction = Action; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
+ if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
+ if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED | ODS_DISABLED;
+ if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
+ dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
- dis.hwndItem = (HWND) MenuInfo->Self;
+ dis.hwndItem = (HWND) MenuInfo->Self;
- dis.hDC = Dc;
- dis.rcItem = Rect;
+ dis.hDC = hdc;
+ dis.rcItem = rect;
- TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
- "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hWnd,
- dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
- dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
- dis.rcItem.bottom);
- SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
- /* Draw the popup-menu arrow */
+ TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
+ "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hWnd,
+ dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
+ dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
+ dis.rcItem.bottom);
+ SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
+ /* Draw the popup-menu arrow */
- if (0 != (Item->fType & MF_POPUP))
+ if (lpitem->fType & MF_POPUP)
- {
- RECT rectTemp;
+ {
+ RECT rectTemp;
- CopyRect(&rectTemp, &Rect);
+ CopyRect(&rectTemp, &rect);
- rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
+ rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+ DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
- }
- return;
+ }
+ return;
}
- TRACE("rect={%ld,%ld,%ld,%ld}\n", Item->Rect.left, Item->Rect.top,
- Item->Rect.right, Item->Rect.bottom);
-
- if (MenuBar && 0 != (Item->fType & MF_SEPARATOR))
- {
- return;
- }
+ if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
- if (Item->fState & MF_HILITE)
+ if (lpitem->fState & MF_HILITE)
+ {
+ if (flat_menu)
{
- InflateRect (&Rect, -1, -1);
- FillRect(Dc, &Rect, GetSysColorBrush(COLOR_MENUHILIGHT));
- InflateRect (&Rect, 1, 1);
- FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- if (flat_menu)
- {
+ InflateRect (&rect, -1, -1);
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
+ InflateRect (&rect, 1, 1);
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- }
- else
- {
+ }
+ else
+ {
- if (MenuBar)
- {
- DrawEdge(Dc, &Rect, BDR_SUNKENOUTER, BF_RECT);
- }
+ if(menuBar)
+ DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
- else
+ else
- {
- FillRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- }
+ }
}
- }
- else
+ else
- {
- FillRect(Dc, &Rect, GetSysColorBrush(bkgnd));
- }
+ FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
- SetBkMode(Dc, TRANSPARENT);
+ SetBkMode( hdc, TRANSPARENT );
- /* vertical separator */
+ /* vertical separator */
- if (! MenuBar && 0 != (Item->fType & MF_MENUBARBREAK))
+ if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
- {
- HPEN oldPen;
+ {
+ HPEN oldPen;
- RECT rc = Rect;
+ RECT rc = rect;
+
- rc.left -= 3;
- rc.top = 3;
- rc.bottom = Height - 3;
- if (flat_menu)
- {
+ rc.left -= 3;
+ rc.top = 3;
+ rc.bottom = Height - 3;
+ if (flat_menu)
+ {
- oldPen = SelectObject( Dc, GetStockObject(DC_PEN) );
- SetDCPenColor(Dc, GetSysColor(COLOR_BTNSHADOW));
- MoveToEx( Dc, rc.left, rc.top, NULL );
- LineTo( Dc, rc.left, rc.bottom );
- SelectObject( Dc, oldPen );
+ oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+ SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.left, rc.bottom );
+ SelectObject( hdc, oldPen );
- }
- else
- DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
}
- DrawEdge(Dc, &rc, EDGE_ETCHED, BF_LEFT);
+ else
++ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+ }
- /* horizontal separator */
+ /* horizontal separator */
- if (0 != (Item->fType & MF_SEPARATOR))
+ if (lpitem->fType & MF_SEPARATOR)
- {
- HPEN oldPen;
+ {
+ HPEN oldPen;
- RECT rc = Rect;
+ RECT rc = rect;
+
- rc.left++;
- rc.right--;
- rc.top += SEPARATOR_HEIGHT / 2;
- if (flat_menu)
- {
+ rc.left++;
+ rc.right--;
+ rc.top += SEPARATOR_HEIGHT / 2;
+ if (flat_menu)
+ {
- oldPen = SelectObject( Dc, GetStockObject(DC_PEN) );
- SetDCPenColor(Dc, GetSysColor(COLOR_BTNSHADOW));
- MoveToEx( Dc, rc.left, rc.top, NULL );
- LineTo( Dc, rc.right, rc.top );
- SelectObject( Dc, oldPen );
+ oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+ SetDCPenColor( hdc, GetSysColor(COLOR_BTNSHADOW));
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.right, rc.top );
+ SelectObject( hdc, oldPen );
- }
- else
- DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
- return;
}
- DrawEdge(Dc, &rc, EDGE_ETCHED, BF_TOP);
+ else
++ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
+ return;
+ }
#if 0
- /* helper lines for debugging */
- /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
+ /* helper lines for debugging */
+ /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
- FrameRect(Dc, &Rect, GetStockObject(BLACK_BRUSH));
- SelectObject(Dc, GetStockObject(DC_PEN));
- SetDCPenColor(Dc, GetSysColor(COLOR_WINDOWFRAME));
- MoveToEx(Dc, Rect.left, (Rect.top + Rect.bottom) / 2, NULL);
- LineTo(Dc, Rect.right, (Rect.top + Rect.bottom) / 2);
+ FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
+ SelectObject(hdc, GetStockObject(DC_PEN));
+ SetDCPenColor(hdc, GetSysColor(COLOR_WINDOWFRAME));
+ MoveToEx(hdc, rect.left, (rect.top + rect.bottom) / 2, NULL);
+ LineTo(hdc, rect.right, (rect.top + rect.bottom) / 2);
#endif
- if (! MenuBar)
+ if (!menuBar)
- {
+ {
- INT y = Rect.top + Rect.bottom;
- RECT Rc = Rect;
- UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
- UINT CheckBitmapHeight = GetSystemMetrics(SM_CYMENUCHECK);
+ HBITMAP bm;
+ INT y = rect.top + rect.bottom;
+ RECT rc = rect;
- int checked = FALSE;
+ int checked = FALSE;
+ UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+ UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
- /* Draw the check mark
- *
- * FIXME:
- * Custom checkmark bitmaps are monochrome but not always 1bpp.
- */
+ /* Draw the check mark
+ *
+ * FIXME:
+ * Custom checkmark bitmaps are monochrome but not always 1bpp.
+ */
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK)) {
+ bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked :
+ lpitem->hbmpUnchecked;
+ if (bm) /* we have a custom bitmap */
- {
+ {
- HBITMAP bm = 0 != (Item->fState & MF_CHECKED) ? Item->hbmpChecked : Item->hbmpUnchecked;
- if (NULL != bm) /* we have a custom bitmap */
- {
- HDC DcMem = CreateCompatibleDC(Dc);
- SelectObject(DcMem, bm);
- BitBlt(Dc, Rc.left, (y - CheckBitmapHeight) / 2,
- CheckBitmapWidth, CheckBitmapHeight,
- DcMem, 0, 0, SRCCOPY);
- DeleteDC(DcMem);
+ HDC hdcMem = CreateCompatibleDC( hdc );
+
+ SelectObject( hdcMem, bm );
+ BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
+ check_bitmap_width, check_bitmap_height,
+ hdcMem, 0, 0, SRCCOPY );
+ DeleteDC( hdcMem );
- checked = TRUE;
- }
+ checked = TRUE;
+ }
- else if (0 != (Item->fState & MF_CHECKED)) /* standard bitmaps */
+ else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
- {
+ {
- RECT rectTemp;
- CopyRect(&rectTemp, &Rect);
- rectTemp.right = rectTemp.left + GetSystemMetrics(SM_CXMENUCHECK);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU,
- 0 != (Item->fType & MFT_RADIOCHECK) ?
+ RECT r;
+ CopyRect(&r, &rect);
+ r.right = r.left + GetSystemMetrics(SM_CXMENUCHECK);
+ DrawFrameControl( hdc, &r, DFC_MENU,
+ (lpitem->fType & MFT_RADIOCHECK) ?
DFCS_MENUBULLET : DFCS_MENUCHECK);
- checked = TRUE;
- }
+ checked = TRUE;
}
- if (Item->hbmpItem)
+ }
- {
- RECT bmpRect;
+ if ( lpitem->hbmpItem )
- CopyRect(&bmpRect, &Rect);
+ {
+ RECT bmpRect;
- if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK))
+ CopyRect(&bmpRect, &rect);
- bmpRect.left += CheckBitmapWidth + 2;
+ if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK))
- if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
- {
- bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx;
+ bmpRect.left += check_bitmap_width + 2;
- MenuDrawBitmapItem(Dc, Item, &bmpRect, MenuInfo->Self, WndOwner, Action, MenuBar);
+ if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
+ {
+ bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx;
- }
- }
- /* Draw the popup-menu arrow */
+ MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo->Self, WndOwner, odaction, menuBar);
- if (0 != (Item->fType & MF_POPUP))
+ }
+ }
+ /* Draw the popup-menu arrow */
- {
- RECT rectTemp;
+ if (lpitem->fType & MF_POPUP)
- CopyRect(&rectTemp, &Rect);
+ {
+ RECT rectTemp;
- rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
+ CopyRect(&rectTemp, &rect);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+ rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
- }
+ DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
- Rect.left += 4;
+ }
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ rect.left += 4;
- Rect.left += CheckBitmapWidth;
- Rect.right -= CheckBitmapWidth;
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
- }
+ rect.left += check_bitmap_width;
+ rect.right -= check_bitmap_width;
- else if (Item->hbmpItem) /* Draw the bitmap */
- {
- MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
+ }
- }
+ else if( lpitem->hbmpItem)
+ { /* Draw the bitmap */
+ MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo->Self, WndOwner, odaction, menuBar);
+ }
- /* No bitmap - process text if present */
- if (Item->Text)
+ /* process text if present */
+ if (lpitem->lpstr)
- {
- register int i = 0;
+ {
+ register int i = 0;
- HFONT FontOld = NULL;
+ HFONT hfontOld = 0;
- UINT uFormat = MenuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
+ UINT uFormat = menuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
- : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+ : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
- if(MenuInfo->dwStyle & MNS_CHECKORBMP)
+ if(MenuInfo->dwStyle & MNS_CHECKORBMP)
- Rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK));
+ rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK));
- else
+ else
- Rect.left += MenuInfo->maxBmpSize.cx;
+ rect.left += MenuInfo->maxBmpSize.cx;
- if (0 != (Item->fState & MFS_DEFAULT))
+ if ( lpitem->fState & MFS_DEFAULT )
{
- FontOld = SelectObject(Dc, hMenuFontBold);
+ hfontOld = SelectObject(hdc, hMenuFontBold);
}
- if (MenuBar)
- {
- Rect.left += MENU_BAR_ITEMS_SPACE / 2;
- Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+ if (menuBar) {
+ rect.left += MENU_BAR_ITEMS_SPACE / 2;
+ rect.right -= MENU_BAR_ITEMS_SPACE / 2;
}
- Text = (PWCHAR) Item->dwTypeData;
+ Text = (PWCHAR) lpitem->dwTypeData;
- if(Text)
- {
- for (i = 0; L'\0' != Text[i]; i++)
+ if(Text)
+ {
+ for (i = 0; L'\0' != Text[i]; i++)
- {
- if (L'\t' == Text[i] || L'\b' == Text[i])
- {
+ if (Text[i] == L'\t' || Text[i] == L'\b')
- break;
- }
+ break;
+ }
- }
- }
- if (0 != (Item->fState & MF_GRAYED))
+ if(lpitem->fState & MF_GRAYED)
- {
+ {
- if (0 == (Item->fState & MF_HILITE))
+ if (!(lpitem->fState & MF_HILITE) )
- {
+ {
- ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
- SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
- DrawTextW(Dc, Text, i, &Rect, uFormat);
- --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
+ ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+ SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+ DrawTextW( hdc, Text, i, &rect, uFormat );
+ --rect.left; --rect.top; --rect.right; --rect.bottom;
- }
+ }
- SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
+ SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
}
- DrawTextW(Dc, Text, i, &Rect, uFormat);
+ DrawTextW( hdc, Text, i, &rect, uFormat);
- /* paint the shortcut text */
+ /* paint the shortcut text */
- if (! MenuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
+ if (!menuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
{
- if (L'\t' == Text[i])
+ if (L'\t' == Text[i])
{
- Rect.left = Item->XTab;
+ rect.left = lpitem->dxTab;
- uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+ uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
- else
+ else
{
- Rect.right = Item->XTab;
+ rect.right = lpitem->dxTab;
- uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
+ uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
- if (0 != (Item->fState & MF_GRAYED))
+ if (lpitem->fState & MF_GRAYED)
{
- if (0 == (Item->fState & MF_HILITE))
+ if (!(lpitem->fState & MF_HILITE) )
{
- ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
- SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
- DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
- --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
+ ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+ SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+ DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat);
+ --rect.left; --rect.top; --rect.right; --rect.bottom;
}
- SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
+ SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
- }
+ }
- DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
+ DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
}
- if (NULL != FontOld)
- {
- SelectObject(Dc, FontOld);
+ if (hfontOld)
+ SelectObject (hdc, hfontOld);
- }
-}
+ }
+ }
- }
/***********************************************************************
* MenuDrawPopupMenu
*
* Paint a popup menu.
*/
- static void FASTCALL
- MenuDrawPopupMenu(HWND Wnd, HDC Dc, HMENU Menu)
+ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu )
{
- HBRUSH PrevBrush = NULL;
- HPEN PrevPen;
- RECT Rect;
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- UINT u;
+ HBRUSH hPrevBrush = 0;
+ RECT rect;
- TRACE("wnd=%x dc=%x menu=%x\n", Wnd, Dc, Menu);
+ TRACE("wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu);
- GetClientRect(Wnd, &Rect);
+ GetClientRect( hwnd, &rect );
- if (NULL != (PrevBrush = SelectObject(Dc, GetSysColorBrush(COLOR_MENU)))
- && NULL != SelectObject(Dc, hMenuFont))
+ if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
+ && (SelectObject( hdc, hMenuFont)))
{
- Rectangle(Dc, Rect.left, Rect.top, Rect.right, Rect.bottom);
+ HPEN hPrevPen;
+
+ Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
- PrevPen = SelectObject(Dc, GetStockObject(NULL_PEN));
- if (NULL != PrevPen)
+ hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
+ if ( hPrevPen )
{
- BOOL flat_menu = FALSE;
+ BOOL flat_menu = FALSE;
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
- SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
- if (flat_menu)
+ SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
+ if (flat_menu)
- FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_BTNSHADOW));
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_BTNSHADOW));
- else
+ else
- DrawEdge(Dc, &Rect, EDGE_RAISED, BF_RECT);
+ DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
- /* draw menu items */
+ /* draw menu items */
-
- if (MenuGetRosMenuInfo(&MenuInfo, Menu) && 0 != MenuInfo.MenuItemCount)
+ if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount)
{
- MenuInitRosMenuItemInfo(&ItemInfo);
+ UINT u;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
- for (u = 0; u < MenuInfo.MenuItemCount; u++)
+ for (u = 0; u < MenuInfo.MenuItemCount; u++)
{
- if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
+ if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
{
- MenuDrawMenuItem(Wnd, &MenuInfo, MenuInfo.WndOwner, Dc, &ItemInfo,
+ MenuDrawMenuItem(hwnd, &MenuInfo, MenuInfo.WndOwner, hdc, &ItemInfo,
- MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
+ MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
}
}
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ }
- }
- else
- {
- SelectObject(Dc, PrevBrush);
+ } else
+ {
+ SelectObject( hdc, hPrevBrush );
- }
+ }
}
}
- LRESULT WINAPI
- PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
+ /***********************************************************************
+ * MenuDrawMenuBar
+ *
+ * Paint a menu bar. Returns the height of the menu bar.
+ * called from [windows/nonclient.c]
+ */
+ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
+ BOOL suppress_draw)
{
- TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+ ROSMENUINFO lppop;
+ HFONT hfontOld = 0;
+ HMENU hMenu = GetMenu(hwnd);
- switch(Message)
+ if (! MenuGetRosMenuInfo(&lppop, hMenu) || lprect == NULL)
{
- case WM_CREATE:
- {
- CREATESTRUCTA *cs = (CREATESTRUCTA *) lParam;
- SetWindowLongPtrA(Wnd, 0, (LONG_PTR)cs->lpCreateParams);
- return 0;
- }
+ return GetSystemMetrics(SM_CYMENU);
+ }
- case WM_MOUSEACTIVATE: /* We don't want to be activated */
- return MA_NOACTIVATE;
+ if (suppress_draw)
+ {
+ hfontOld = SelectObject(hDC, hMenuFont);
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(Wnd, &ps);
- MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrA(Wnd, 0));
- EndPaint(Wnd, &ps);
- return 0;
- }
+ MenuMenuBarCalcSize(hDC, lprect, &lppop, hwnd);
- case WM_PRINTCLIENT:
- {
- MenuDrawPopupMenu( Wnd, (HDC)wParam,
- (HMENU)GetWindowLongPtrW( Wnd, 0 ) );
- return 0;
- }
+ lprect->bottom = lprect->top + lppop.Height;
- case WM_ERASEBKGND:
- return 1;
+ if (hfontOld) SelectObject( hDC, hfontOld);
+ return lppop.Height;
+ }
- else
++ else
+ return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
+ }
- case WM_DESTROY:
- /* zero out global pointer in case resident popup window was destroyed. */
- if (Wnd == TopPopup)
+ /***********************************************************************
+ * MenuShowPopup
+ *
+ * Display a popup menu.
+ */
+ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT flags,
+ INT x, INT y, INT xanchor, INT yanchor )
-{
+ {
- TopPopup = NULL;
- }
- break;
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
+ UINT width, height;
+ POINT pt;
+ HMONITOR monitor;
+ MONITORINFO info;
- case WM_SHOWWINDOW:
- if (0 != wParam)
- {
- if (0 == GetWindowLongPtrA(Wnd, 0))
- {
- OutputDebugStringA("no menu to display\n");
- }
- }
- else
- {
- SetWindowLongPtrA(Wnd, 0, 0);
- }
- break;
+ TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
+ hwndOwner, hmenu, id, x, y, xanchor, yanchor);
+
+ if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) return FALSE;
+ if (MenuInfo.FocusedItem != NO_SELECTED_ITEM)
+ {
+ MenuInitRosMenuItemInfo(&ItemInfo);
+ if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
+ MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo);
- }
++ }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ MenuInfo.FocusedItem = NO_SELECTED_ITEM;
+ }
+
+ /* store the owner for DrawItem */
+ MenuInfo.WndOwner = hwndOwner;
+ MenuSetRosMenuInfo(&MenuInfo);
+
+ MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
+
+ /* adjust popup menu pos so that it fits within the desktop */
+
+ width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER);
+ height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER);
+
+ /* FIXME: should use item rect */
+ pt.x = x;
+ pt.y = y;
+ monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
+ info.cbSize = sizeof(info);
+ GetMonitorInfoW( monitor, &info );
+
+ if( flags & TPM_RIGHTALIGN ) x -= width;
+ if( flags & TPM_CENTERALIGN ) x -= width / 2;
+
+ if( flags & TPM_BOTTOMALIGN ) y -= height;
+ if( flags & TPM_VCENTERALIGN ) y -= height / 2;
+
+ if( x + width > info.rcWork.right)
+ {
+ if( xanchor && x >= width - xanchor )
+ x -= width - xanchor;
+
+ if( x + width > info.rcWork.right)
+ x = info.rcWork.right - width;
- }
++}
+ if( x < info.rcWork.left ) x = info.rcWork.left;
+
+ if( y + height > info.rcWork.bottom)
- {
++{
+ if( yanchor && y >= height + yanchor )
+ y -= height + yanchor;
+
+ if( y + height > info.rcWork.bottom)
+ y = info.rcWork.bottom - height;
+ }
+ if( y < info.rcWork.top ) y = info.rcWork.top;
+
+ /* NOTE: In Windows, top menu popup is not owned. */
+ MenuInfo.Wnd = CreateWindowExW( 0, POPUPMENU_CLASS_ATOMW, NULL,
+ WS_POPUP, x, y, width, height,
+ hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+ (LPVOID) MenuInfo.Self);
+ if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
+ if (!top_popup) {
+ top_popup = MenuInfo.Wnd;
+ top_popup_hmenu = hmenu;
+ }
+
+ /* Display the window */
+
+ SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ UpdateWindow( MenuInfo.Wnd );
+ return TRUE;
+ }
+
+
+ /***********************************************************************
+ * MenuSelectItem
+ */
+ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIndex,
+ BOOL sendMenuSelect, HMENU topmenu)
+ {
+ ROSMENUITEMINFO ItemInfo;
+ ROSMENUINFO TopMenuInfo;
+ HDC hdc;
+
+ TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
+
+ if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return;
+ if (hmenu->FocusedItem == wIndex) return;
+ if (hmenu->Flags & MF_POPUP) hdc = GetDC(hmenu->Wnd);
+ else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW);
+ if (!top_popup) {
+ top_popup = hmenu->Wnd;
+ top_popup_hmenu = hmenu->Self;
+ }
+
+ SelectObject( hdc, hMenuFont );
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+
+ /* Clear previous highlighted item */
+ if (hmenu->FocusedItem != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
+ MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
+ }
+ MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo,
+ hmenu->Height, ! (hmenu->Flags & MF_POPUP),
+ ODA_SELECT);
+ }
+
+ /* Highlight new item (if any) */
+ hmenu->FocusedItem = wIndex;
+ MenuSetRosMenuInfo(hmenu);
+ if (hmenu->FocusedItem != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo))
+ {
+ if (!(ItemInfo.fType & MF_SEPARATOR))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState |= MF_HILITE;
+ MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
+ MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc,
+ &ItemInfo, hmenu->Height, ! (hmenu->Flags & MF_POPUP),
+ ODA_SELECT);
+ }
+ if (sendMenuSelect)
+ {
+ SendMessageW(hwndOwner, WM_MENUSELECT,
+ MAKELONG(ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID,
+ ItemInfo.fType | ItemInfo.fState | MF_MOUSESELECT |
+ (hmenu->Flags & MF_SYSMENU)), (LPARAM) hmenu->Self);
+ }
+ }
+ }
+ else if (sendMenuSelect) {
+ if(topmenu) {
+ int pos;
+ pos = MenuFindSubMenu(&topmenu, hmenu->Self);
+ if (pos != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu)
+ && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo))
+ {
+ SendMessageW(hwndOwner, WM_MENUSELECT,
+ MAKELONG(Pos, ItemInfo.fType | ItemInfo.fState
+ | MF_MOUSESELECT
+ | (TopMenuInfo.Flags & MF_SYSMENU)),
+ (LPARAM) topmenu);
+ }
+ }
+ }
+ }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ ReleaseDC(hmenu->Wnd, hdc);
+ }
+
+ /***********************************************************************
+ * MenuMoveSelection
+ *
+ * Moves currently selected item according to the Offset parameter.
+ * If there is no selection then it should select the last item if
+ * Offset is ITEM_PREV or the first item if Offset is ITEM_NEXT.
+ */
+ static void FASTCALL
+ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset)
+ {
+ INT i;
+ ROSMENUITEMINFO ItemInfo;
+ INT OrigPos;
+
+ TRACE("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset);
+
+ /* Prevent looping */
+ if (0 == MenuInfo->MenuItemCount || 0 == Offset)
+ return;
+ else if (Offset < -1)
+ Offset = -1;
+ else if (Offset > 1)
+ Offset = 1;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+
+ OrigPos = MenuInfo->FocusedItem;
+ if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */
+ {
+ OrigPos = 0;
+ i = -1;
+ }
+ else
+ {
+ i = MenuInfo->FocusedItem;
+ }
+
+ do
+ {
+ /* Step */
+ i += Offset;
+ /* Clip and wrap around */
+ if (i < 0)
+ {
+ i = MenuInfo->MenuItemCount - 1;
+ }
+ else if (i >= MenuInfo->MenuItemCount)
+ {
+ i = 0;
+ }
+ /* If this is a good candidate; */
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
+ 0 == (ItemInfo.fType & MF_SEPARATOR))
+ {
+ MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ } while (i != OrigPos);
+
+ /* Not found */
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ }
+
+ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
+ {
+ TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+
+ switch(Message)
+ {
+ case WM_CREATE:
+ {
+ CREATESTRUCTA *cs = (CREATESTRUCTA *) lParam;
- SetWindowLongPtrA(Wnd, 0, (LONG) cs->lpCreateParams);
++ SetWindowLongPtrA(Wnd, 0, (LONG_PTR)cs->lpCreateParams);
+ return 0;
+ }
+
+ case WM_MOUSEACTIVATE: /* We don't want to be activated */
+ return MA_NOACTIVATE;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ BeginPaint(Wnd, &ps);
+ MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrA(Wnd, 0));
+ EndPaint(Wnd, &ps);
+ return 0;
+ }
+
+ case WM_PRINTCLIENT:
+ {
+ MenuDrawPopupMenu( Wnd, (HDC)wParam,
+ (HMENU)GetWindowLongPtrW( Wnd, 0 ) );
+ return 0;
+ }
+
+ case WM_ERASEBKGND:
+ return 1;
+
+ case WM_DESTROY:
+ /* zero out global pointer in case resident popup window was destroyed. */
+ if (Wnd == top_popup)
+ {
+ top_popup = NULL;
+ top_popup_hmenu = NULL;
+ }
+ break;
+
+ case WM_SHOWWINDOW:
+ if (0 != wParam)
+ {
+ if (0 == GetWindowLongPtrA(Wnd, 0))
+ {
+ OutputDebugStringA("no menu to display\n");
+ }
+ }
+ else
+ {
+ SetWindowLongPtrA(Wnd, 0, 0);
+ }
+ break;
case MM_SETMENUHANDLE:
SetWindowLongPtrA(Wnd, 0, wParam);
*/
static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
{
- WORD flags, id = 0;
- HMENU hSubMenu;
- LPCSTR str;
- BOOL end = FALSE;
+ WORD flags, id = 0;
+ HMENU hSubMenu;
+ LPCSTR str;
+ BOOL end = FALSE;
- do
- {
- flags = GET_WORD(res);
+ do
+ {
+ flags = GET_WORD(res);
- /* remove MF_END flag before passing it to AppendMenu()! */
- end = (flags & MF_END);
- if(end) flags ^= MF_END;
+ /* remove MF_END flag before passing it to AppendMenu()! */
+ end = (flags & MF_END);
+ if(end) flags ^= MF_END;
- res += sizeof(WORD);
- if(!(flags & MF_POPUP))
- {
- id = GET_WORD(res);
- res += sizeof(WORD);
- }
- str = res;
- if(!unicode)
- res += strlen(str) + 1;
- else
- res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
- if (flags & MF_POPUP)
- {
- hSubMenu = CreatePopupMenu();
- if(!hSubMenu) return NULL;
- if(!(res = MENU_ParseResource(res, hSubMenu, unicode)))
- return NULL;
- if(!unicode)
- AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
- else
- AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
- }
- else /* Not a popup */
- {
- if(!unicode)
- {
+ res += sizeof(WORD);
+ if(!(flags & MF_POPUP))
+ {
+ id = GET_WORD(res);
+ res += sizeof(WORD);
+ }
+ str = res;
+ if(!unicode)
+ res += strlen(str) + 1;
+ else
+ res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
+ if (flags & MF_POPUP)
+ {
+ hSubMenu = CreatePopupMenu();
+ if(!hSubMenu) return NULL;
+ if(!(res = MENU_ParseResource(res, hSubMenu, unicode)))
+ return NULL;
+ if(!unicode)
+ AppendMenuA(hMenu, flags, (UINT_PTR)hSubMenu, str);
+ else
+ AppendMenuW(hMenu, flags, (UINT_PTR)hSubMenu, (LPCWSTR)str);
+ }
+ else /* Not a popup */
+ {
+ if(!unicode)
+ {
- if (*str == 0)
- flags = MF_SEPARATOR;
+ if (*str == 0)
+ flags = MF_SEPARATOR;
- }
- else
- {
- if (*(LPCWSTR)str == 0)
- flags = MF_SEPARATOR;
- }
+ }
+ else
+ {
+ if (*(LPCWSTR)str == 0)
+ flags = MF_SEPARATOR;
+ }
- if (flags & MF_SEPARATOR)
- {
- if (!(flags & (MF_GRAYED | MF_DISABLED)))
- flags |= MF_GRAYED | MF_DISABLED;
- }
+ if (flags & MF_SEPARATOR)
+ {
+ if (!(flags & (MF_GRAYED | MF_DISABLED)))
+ flags |= MF_GRAYED | MF_DISABLED;
+ }
- if(!unicode)
- AppendMenuA(hMenu, flags, id, *str ? str : NULL);
- else
- AppendMenuW(hMenu, flags, id,
+ if(!unicode)
+ AppendMenuA(hMenu, flags, id, *str ? str : NULL);
+ else
+ AppendMenuW(hMenu, flags, id,
*(LPCWSTR)str ? (LPCWSTR)str : NULL);
- }
- } while(!end);
- return res;
+ }
+ } while(!end);
-
+ return res;
}
TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect);
- if (NULL != MenuInfo && NULL != TopPopup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
+ if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
- {
+ {
MenuInitRosMenuItemInfo(&ItemInfo);
ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE;
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)
ItemInfo.fMask |= MIIM_STATE;
MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
- {
+ {
- MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE);
+ MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags);
MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL);
DestroyWindow(SubMenuInfo.Wnd);
SubMenuInfo.Wnd = NULL;
MenuSetRosMenuInfo(&SubMenuInfo);
- }
- }
+
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu,
+ MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) );
+ }
+ }
}
/***********************************************************************
*
* Handle a VK_RIGHT key event in a menu.
*/
- static void FASTCALL
- MenuKeyRight(MTRACKER *Mt, UINT Flags)
+ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
{
- HMENU MenuTmp;
+ HMENU hmenutmp;
- ROSMENUINFO MenuInfo;
- ROSMENUINFO CurrentMenuInfo;
- UINT NextCol;
+ ROSMENUINFO MenuInfo;
+ ROSMENUINFO CurrentMenuInfo;
+ UINT NextCol;
- TRACE("MenuKeyRight called, cur %p, top %p.\n",
+ TRACE("MenuKeyRight called, cur %p, top %p.\n",
Mt->CurrentMenu, Mt->TopMenu);
- if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu))
- {
- return;
- }
- if (0 != (MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu))
+ if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return;
+ if ((MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu))
{
/* If already displaying a popup, try to display sub-popup */
}
/* if subpopup was displayed then we are done */
- if (MenuTmp != Mt->CurrentMenu)
- {
- return;
+ if (hmenutmp != Mt->CurrentMenu) return;
- }
+ }
- }
if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
{
*
* Menu tracking code.
*/
- static INT FASTCALL
- MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
- HWND Wnd, const RECT *Rect )
+ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
+ HWND hwnd, const RECT *lprect )
{
- MSG Msg;
+ MSG msg;
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- BOOL fRemove;
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
+ BOOL fRemove;
- INT ExecutedMenuId = -1;
- MTRACKER Mt;
- BOOL EnterIdleSent = FALSE;
-
- Mt.TrackFlags = 0;
- Mt.CurrentMenu = Menu;
- Mt.TopMenu = Menu;
- Mt.OwnerWnd = Wnd;
- Mt.Pt.x = x;
- Mt.Pt.y = y;
-
- TRACE("Menu=%x Flags=0x%08x (%d,%d) Wnd=%x (%ld,%ld)-(%ld,%ld)\n",
- Menu, Flags, x, y, Wnd, Rect ? Rect->left : 0, Rect ? Rect->top : 0,
- Rect ? Rect->right : 0, Rect ? Rect->bottom : 0);
-
- if (!IsMenu(Menu))
+ INT executedMenuId = -1;
+ MTRACKER mt;
+ BOOL enterIdleSent = FALSE;
+
+ mt.TrackFlags = 0;
+ mt.CurrentMenu = hmenu;
+ mt.TopMenu = hmenu;
+ mt.OwnerWnd = hwnd;
+ mt.Pt.x = x;
+ mt.Pt.y = y;
+
+ TRACE("hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
+ hmenu, wFlags, x, y, hwnd, lprect ? lprect->left : 0, lprect ? lprect->top : 0,
+ lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
+
+ if (!IsMenu(hmenu))
- {
+ {
+ WARN("Invalid menu handle %p\n", hmenu);
- SetLastError( ERROR_INVALID_MENU_HANDLE );
- return FALSE;
- }
+ SetLastError( ERROR_INVALID_MENU_HANDLE );
+ return FALSE;
+ }
- fEndMenu = FALSE;
+ fEndMenu = FALSE;
- if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
+ if (! MenuGetRosMenuInfo(&MenuInfo, hmenu))
{
- return FALSE;
+ return FALSE;
}
- if (0 != (Flags & TPM_BUTTONDOWN))
+ if (wFlags & TPM_BUTTONDOWN)
{
- /* Get the result in order to start the tracking or not */
+ /* Get the result in order to start the tracking or not */
- fRemove = MenuButtonDown(&Mt, Menu, Flags);
+ fRemove = MenuButtonDown( &mt, hmenu, wFlags );
- fEndMenu = !fRemove;
+ fEndMenu = ! fRemove;
}
- SetCapture(Mt.OwnerWnd);
- (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt.OwnerWnd);
+ SetCapture(mt.OwnerWnd);
+ (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, mt.OwnerWnd);
- ERR("MenuTrackMenu 1\n");
- while (! fEndMenu)
+ ERR("MenuTrackMenu 1\n");
+ while (! fEndMenu)
{
- PVOID menu = ValidateHandle(Mt.CurrentMenu, VALIDATE_TYPE_MENU);
+ PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU);
- if (!menu) /* sometimes happens if I do a window manager close */
- break;
+ if (!menu) /* sometimes happens if I do a window manager close */
+ break;
- /* we have to keep the message in the queue until it's
- * clear that menu loop is not over yet. */
+ /* we have to keep the message in the queue until it's
+ * clear that menu loop is not over yet. */
- for (;;)
+ for (;;)
{
- if (PeekMessageW(&Msg, 0, 0, 0, PM_NOREMOVE))
+ if (PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ))
{
- if (! CallMsgFilterW(&Msg, MSGF_MENU))
- {
- break;
- }
+ if (!CallMsgFilterW( &msg, MSGF_MENU )) break;
- /* remove the message from the queue */
+ /* remove the message from the queue */
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE );
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
}
- else
+ else
{
- if (! EnterIdleSent)
+ if (!enterIdleSent)
{
- HWND Win = (0 != (Flags & TPM_ENTERIDLEEX)
- && 0 != (MenuInfo.Flags & MF_POPUP)) ? MenuInfo.Wnd : NULL;
- EnterIdleSent = TRUE;
- SendMessageW(Mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) Win);
+ HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL;
+ enterIdleSent = TRUE;
+ SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
}
- WaitMessage();
+ WaitMessage();
}
}
- /* check if EndMenu() tried to cancel us, by posting this message */
+ /* check if EndMenu() tried to cancel us, by posting this message */
- if (WM_CANCELMODE == Msg.message)
+ if (msg.message == WM_CANCELMODE)
{
- /* we are now out of the loop */
- fEndMenu = TRUE;
+ /* we are now out of the loop */
+ fEndMenu = TRUE;
- /* remove the message from the queue */
+ /* remove the message from the queue */
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE);
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
- /* break out of internal loop, ala ESCAPE */
- break;
+ /* break out of internal loop, ala ESCAPE */
+ break;
}
- TranslateMessage(&Msg);
- Mt.Pt = Msg.pt;
+ TranslateMessage( &msg );
+ mt.Pt = msg.pt;
- if (Msg.hwnd == MenuInfo.Wnd || WM_TIMER != Msg.message)
- {
- EnterIdleSent = FALSE;
- }
+ if ( (msg.hwnd == MenuInfo.Wnd) || (msg.message!=WM_TIMER) )
+ enterIdleSent=FALSE;
- fRemove = FALSE;
+ fRemove = FALSE;
- if (WM_MOUSEFIRST <= Msg.message && Msg.message <= WM_MOUSELAST)
+ if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
{
- /*
- * Use the mouse coordinates in lParam instead of those in the MSG
- * struct to properly handle synthetic messages. They are already
- * in screen coordinates.
- */
+ /*
+ * Use the mouse coordinates in lParam instead of those in the MSG
+ * struct to properly handle synthetic messages. They are already
+ * in screen coordinates.
+ */
- Mt.Pt.x = (short) LOWORD(Msg.lParam);
- Mt.Pt.y = (short) HIWORD(Msg.lParam);
+ mt.Pt.x = (short)LOWORD(msg.lParam);
+ mt.Pt.y = (short)HIWORD(msg.lParam);
- /* Find a menu for this mouse event */
+ /* Find a menu for this mouse event */
- Menu = MenuPtMenu(Mt.TopMenu, Mt.Pt);
+ hmenu = MenuPtMenu(mt.TopMenu, mt.Pt);
- switch(Msg.message)
+ switch(msg.message)
{
- /* no WM_NC... messages in captured state */
+ /* no WM_NC... messages in captured state */
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
- if (0 == (Flags & TPM_RIGHTBUTTON))
- {
- break;
- }
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
- /* fall through */
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- /* If the message belongs to the menu, removes it from the queue */
- /* Else, end menu tracking */
+ /* fall through */
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ /* If the message belongs to the menu, removes it from the queue */
+ /* Else, end menu tracking */
- fRemove = MenuButtonDown(&Mt, Menu, Flags);
+ fRemove = MenuButtonDown(&mt, hmenu, wFlags);
- fEndMenu = !fRemove;
- break;
+ fEndMenu = ! fRemove;
+ break;
- case WM_RBUTTONUP:
+ case WM_RBUTTONUP:
- if (0 == (Flags & TPM_RIGHTBUTTON))
- {
- break;
- }
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
- /* fall through */
- case WM_LBUTTONUP:
- /* Check if a menu was selected by the mouse */
+ /* fall through */
+ case WM_LBUTTONUP:
+ /* Check if a menu was selected by the mouse */
- if (NULL != Menu)
+ if (hmenu)
- {
+ {
- ExecutedMenuId = MenuButtonUp(&Mt, Menu, Flags);
+ executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+ TRACE("executedMenuId %d\n", executedMenuId);
- /* End the loop if ExecutedMenuId is an item ID */
- /* or if the job was done (ExecutedMenuId = 0). */
- fEndMenu = fRemove = (-1 != ExecutedMenuId);
+ /* End the loop if executedMenuId is an item ID */
+ /* or if the job was done (executedMenuId = 0). */
+ fEndMenu = fRemove = (executedMenuId != -1);
- }
+ }
- else
- {
/* No menu was selected by the mouse */
/* if the function was called by TrackPopupMenu, continue
with the menu tracking. If not, stop it */
- fEndMenu = (0 != (Flags & TPM_POPUPMENU) ? FALSE : TRUE);
- }
+ else
+ fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
+
- break;
+ break;
- case WM_MOUSEMOVE:
+ case WM_MOUSEMOVE:
- if (Menu)
- {
- fEndMenu |= ! MenuMouseMove(&Mt, Menu, Flags);
- }
- break;
+ /* the selected menu item must be changed every time */
+ /* the mouse moves. */
- } /* switch(Msg.message) - mouse */
+ if (hmenu)
+ fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags );
+
+ } /* switch(msg.message) - mouse */
- }
+ }
- else if (WM_KEYFIRST <= Msg.message && Msg.message <= WM_KEYLAST)
+ else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
- {
- fRemove = TRUE; /* Keyboard messages are always removed */
+ {
+ fRemove = TRUE; /* Keyboard messages are always removed */
- switch(Msg.message)
+ switch(msg.message)
{
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
+ case WM_KEYDOWN:
- switch(Msg.wParam)
+ case WM_SYSKEYDOWN:
+ switch(msg.wParam)
- {
+ {
case VK_MENU:
- fEndMenu = TRUE;
- break;
+ case VK_F10:
+ fEndMenu = TRUE;
+ break;
+
case VK_HOME:
case VK_END:
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM,
- FALSE, 0 );
- MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
- VK_HOME == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo,
+ NO_SELECTED_ITEM, FALSE, 0 );
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
}
- break;
+ break;
case VK_UP:
case VK_DOWN: /* If on menu bar, pull-down the menu */
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- if (0 == (MenuInfo.Flags & MF_POPUP))
+ if (!(MenuInfo.Flags & MF_POPUP))
{
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
- {
- Mt.CurrentMenu = MenuShowSubPopup(Mt.OwnerWnd, &MenuInfo,
- TRUE, Flags);
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
+ mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
- }
- else /* otherwise try to move selection */
+ }
- }
+ else /* otherwise try to move selection */
- {
- MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
- VK_DOWN == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
- }
- break;
+ }
- }
+ break;
case VK_LEFT:
- MenuKeyLeft(&Mt, Flags);
+ MenuKeyLeft( &mt, wFlags );
- break;
+ break;
case VK_RIGHT:
- MenuKeyRight(&Mt, Flags);
+ MenuKeyRight( &mt, wFlags );
- break;
+ break;
case VK_ESCAPE:
- fEndMenu = MenuKeyEscape(&Mt, Flags);
+ fEndMenu = MenuKeyEscape(&mt, wFlags);
- break;
+ break;
case VK_F1:
- {
+ {
HELPINFO hi;
hi.cbSize = sizeof(HELPINFO);
hi.iContextType = HELPINFO_MENUITEM;
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
- {
+ {
- if (NO_SELECTED_ITEM == MenuInfo.FocusedItem)
- {
+ if (MenuInfo.FocusedItem == NO_SELECTED_ITEM)
hi.iCtrlId = 0;
- }
else
- {
+ {
MenuInitRosMenuItemInfo(&ItemInfo);
if (MenuGetRosMenuItemInfo(MenuInfo.Self,
MenuInfo.FocusedItem,
&ItemInfo))
- {
+ {
hi.iCtrlId = ItemInfo.wID;
- }
+ }
else
- {
+ {
hi.iCtrlId = 0;
- }
+ }
MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
- }
+ }
+ }
- hi.hItemHandle = Menu;
+ hi.hItemHandle = hmenu;
- hi.dwContextId = MenuInfo.dwContextHelpID;
+ hi.dwContextId = MenuInfo.dwContextHelpID;
- hi.MousePos = Msg.pt;
- SendMessageW(Wnd, WM_HELP, 0, (LPARAM) &hi);
+ hi.MousePos = msg.pt;
+ SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
break;
- }
+ }
default:
- break;
- }
+ break;
+ }
break; /* WM_KEYDOWN */
- case WM_CHAR:
- case WM_SYSCHAR:
+ case WM_CHAR:
+ case WM_SYSCHAR:
{
- UINT Pos;
+ UINT pos;
- if (! MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
- {
- break;
- }
- if (L'\r' == Msg.wParam || L' ' == Msg.wParam)
+ if (! MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) break;
+ if (msg.wParam == L'\r' || msg.wParam == L' ')
{
- ExecutedMenuId = MenuExecFocusedItem(&Mt, &MenuInfo, Flags);
- fEndMenu = (ExecutedMenuId != -2);
+ executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
+ fEndMenu = (executedMenuId != -2);
- break;
+ break;
}
- /* Hack to avoid control chars. */
- /* We will find a better way real soon... */
+ /* Hack to avoid control chars. */
+ /* We will find a better way real soon... */
- if (Msg.wParam < 32)
- {
- break;
- }
+ if (msg.wParam < 32) break;
- Pos = MenuFindItemByKey(Mt.OwnerWnd, &MenuInfo,
- LOWORD(Msg.wParam), FALSE);
- if ((UINT) -2 == Pos)
- {
- fEndMenu = TRUE;
- }
- else if ((UINT) -1 == Pos)
- {
- MessageBeep(0);
- }
+ pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo,
+ LOWORD(msg.wParam), FALSE);
+ if (pos == (UINT)-2) fEndMenu = TRUE;
+ else if (pos == (UINT)-1) MessageBeep(0);
- else
+ else
{
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, Pos, TRUE, 0);
- ExecutedMenuId = MenuExecFocusedItem(&Mt, &MenuInfo, Flags);
- fEndMenu = (-2 != ExecutedMenuId);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos,
+ TRUE, 0);
+ executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
+ fEndMenu = (executedMenuId != -2);
}
- }
- break;
+ }
+ break;
} /* switch(msg.message) - kbd */
}
- else
+ else
{
- PeekMessageW( &Msg, 0, Msg.message, Msg.message, PM_REMOVE );
- DispatchMessageW(&Msg);
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
+ DispatchMessageW( &msg );
- continue;
+ continue;
}
- if (! fEndMenu)
- {
- fRemove = TRUE;
- }
+ if (!fEndMenu) fRemove = TRUE;
- /* finally remove message from the queue */
+ /* finally remove message from the queue */
- if (fRemove && 0 == (Mt.TrackFlags & TF_SKIPREMOVE))
- {
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE);
- }
- else
- {
- Mt.TrackFlags &= ~TF_SKIPREMOVE;
+ if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) )
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
+ else mt.TrackFlags &= ~TF_SKIPREMOVE;
- }
- ERR("MenuTrackMenu 2\n");
+ }
- }
+ ERR("MenuTrackMenu 2\n");
- (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
- SetCapture(NULL); /* release the capture */
+ (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
+ SetCapture(NULL); /* release the capture */
- /* If dropdown is still painted and the close box is clicked on
- then the menu will be destroyed as part of the DispatchMessage above.
+ /* If dropdown is still painted and the close box is clicked on
+ then the menu will be destroyed as part of the DispatchMessage above.
- This will then invalidate the menu handle in Mt.hTopMenu. We should
+ This will then invalidate the menu handle in mt.hTopMenu. We should
- check for this first. */
+ check for this first. */
- if (IsMenu(Mt.TopMenu))
+ if( IsMenu( mt.TopMenu ) )
{
- if (IsWindow(Mt.OwnerWnd))
+ if (IsWindow(mt.OwnerWnd))
{
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
{
- MenuHideSubPopups(Mt.OwnerWnd, &MenuInfo, FALSE);
+ MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags);
- if (0 != (MenuInfo.Flags & MF_POPUP))
+ if (MenuInfo.Flags & MF_POPUP)
{
- DestroyWindow(MenuInfo.Wnd);
- MenuInfo.Wnd = NULL;
+ DestroyWindow(MenuInfo.Wnd);
+ MenuInfo.Wnd = NULL;
- if (!(MenuInfo.Flags & TPM_NONOTIFY))
+ if (!(MenuInfo.Flags & TPM_NONOTIFY))
- SendMessageW( Mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)Mt.TopMenu,
+ SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu,
MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) );
}
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, NULL);
+ MenuSelectItem( mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
}
- SendMessageW(Mt.OwnerWnd, WM_MENUSELECT, MAKELONG(0, 0xffff), 0);
+ SendMessageW( mt.OwnerWnd, WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0 );
}
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
- {
- /* Reset the variable for hiding menu */
+ /* Reset the variable for hiding menu */
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
+ {
- MenuInfo.TimeToHide = FALSE;
- MenuSetRosMenuInfo(&MenuInfo);
+ MenuInfo.TimeToHide = FALSE;
+ MenuSetRosMenuInfo(&MenuInfo);
}
}
- /* The return value is only used by TrackPopupMenu */
+ /* The return value is only used by TrackPopupMenu */
- if (!(Flags & TPM_RETURNCMD)) return TRUE;
- if (ExecutedMenuId < 0) ExecutedMenuId = 0;
- return ExecutedMenuId;
+ if (!(wFlags & TPM_RETURNCMD)) return TRUE;
+ if (executedMenuId == -1) executedMenuId = 0;
+ return executedMenuId;
}
+ /***********************************************************************
+ * MenuInitTracking
+ */
+ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
+ {
+ ROSMENUINFO MenuInfo;
+
+ TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu);
+
+ HideCaret(0);
+
+ /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
+
+ SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION );
+
+ MenuGetRosMenuInfo(&MenuInfo, hMenu);
+
+ if (!(wFlags & TPM_NONOTIFY))
+ {
+ SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 );
+ /* If an app changed/recreated menu bar entries in WM_INITMENU
+ * menu sizes will be recalculated once the menu created/shown.
+ */
+
+ if (!MenuInfo.Height)
+ {
+ /* app changed/recreated menu bar entries in WM_INITMENU
+ Recalculate menu sizes else clicks will not work */
+ SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+
+ }
+ }
+
+ /* This makes the menus of applications built with Delphi work.
+ * It also enables menus to be displayed in more than one window,
+ * but there are some bugs left that need to be fixed in this case.
+ */
+ if(MenuInfo.Self == hMenu)
+ {
+ MenuInfo.Wnd = hWnd;
+ MenuSetRosMenuInfo(&MenuInfo);
+ }
+
+ return TRUE;
+ }
/***********************************************************************
* MenuExitTracking
*/
- static BOOL FASTCALL
- MenuExitTracking(HWND Wnd)
+ static BOOL FASTCALL MenuExitTracking(HWND hWnd)
{
- TRACE("hwnd=%p\n", Wnd);
+ TRACE("hwnd=%p\n", hWnd);
- SendMessageW(Wnd, WM_EXITMENULOOP, 0, 0);
+ SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
- ShowCaret(0);
+ ShowCaret(0);
+ top_popup = 0;
+ top_popup_hmenu = NULL;
- return TRUE;
+ return TRUE;
}
-
- VOID
- MenuTrackMouseMenuBar(HWND Wnd, ULONG Ht, POINT Pt)
+ /***********************************************************************
+ * MenuTrackMouseMenuBar
+ *
+ * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
+ */
+ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
{
- HMENU Menu = (HTSYSMENU == Ht) ? NtUserGetSystemMenu(Wnd, FALSE) : GetMenu(Wnd);
- UINT Flags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+ HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd);
+ UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
- TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", Wnd, Ht, Pt.x, Pt.y);
+ TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
- if (IsMenu(Menu))
+ if (IsMenu(hMenu))
{
- /* map point to parent client coordinates */
+ /* map point to parent client coordinates */
- HWND Parent = GetAncestor(Wnd, GA_PARENT );
+ HWND Parent = GetAncestor(hWnd, GA_PARENT );
- if (Parent != GetDesktopWindow())
+ if (Parent != GetDesktopWindow())
{
- ScreenToClient(Parent, &Pt);
+ ScreenToClient(Parent, &pt);
}
- MenuInitTracking(Wnd, Menu, FALSE, Flags);
- MenuTrackMenu(Menu, Flags, Pt.x, Pt.y, Wnd, NULL);
- MenuExitTracking(Wnd);
+ MenuInitTracking(hWnd, hMenu, FALSE, wFlags);
+ MenuTrackMenu(hMenu, wFlags, pt.x, pt.y, hWnd, NULL);
+ MenuExitTracking(hWnd);
}
}
guii.cbSize = sizeof(GUITHREADINFO);
if(GetGUIThreadInfo(GetCurrentThreadId(), &guii) && guii.hwndMenuOwner)
{
- PostMessageW(guii.hwndMenuOwner, WM_CANCELMODE, 0, 0);
+ if (!fEndMenu &&
+ top_popup &&
+ guii.hwndMenuOwner != top_popup )
+ {
+ ERR("Capture GUI pti hWnd does not match top_popup!\n");
- }
++ }
+ }
+
+ /* if we are in the menu code, and it is active */
+ if (!fEndMenu && top_popup)
+ {
+ /* terminate the menu handling code */
+ fEndMenu = TRUE;
+
+ /* needs to be posted to wakeup the internal menu handler */
+ /* which will now terminate the menu, in the event that */
+ /* the main window was minimized, or lost focus, so we */
+ /* don't end up with an orphaned menu */
+ PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
}
return TRUE;
}