diff --git a/reactos/win32ss/user/user32/windows/menu.c b/reactos/win32ss/user/user32/windows/menu.c index 0e3fe4f9f35..cc36e5b5b26 100644 --- a/reactos/win32ss/user/user32/windows/menu.c +++ b/reactos/win32ss/user/user32/windows/menu.c @@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu); #define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */ #define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */ +/* top and bottom margins for popup menus */ +#define MENU_TOP_MARGIN 3 +#define MENU_BOTTOM_MARGIN 2 #define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR) @@ -1303,7 +1306,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd HBITMAP bm; INT y = rect.top + rect.bottom; RECT rc = rect; - int checked = FALSE; + BOOL checked = FALSE; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); /* Draw the check mark @@ -1551,6 +1554,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl POINT pt; HMONITOR monitor; MONITORINFO info; + DWORD ex_style = 0; 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); @@ -1592,6 +1596,11 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl info.cbSize = sizeof(info); GetMonitorInfoW( monitor, &info ); + if (flags & TPM_LAYOUTRTL) + { + ex_style = WS_EX_LAYOUTRTL; + flags ^= TPM_RIGHTALIGN; + } if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_CENTERALIGN ) x -= width / 2; @@ -1619,7 +1628,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl if( y < info.rcMonitor.top ) y = info.rcMonitor.top; /* NOTE: In Windows, top menu popup is not owned. */ - MenuInfo.Wnd = CreateWindowExW( 0, WC_MENU, NULL, + MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL, WS_POPUP, x, y, width, height, hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), (LPVOID) MenuInfo.Self); @@ -1697,9 +1706,9 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn } if (sendMenuSelect) { - WPARAM wParam = MAKELONG( ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID, - ItemInfo.fType | ItemInfo.fState | - (hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); + WPARAM wParam = MAKEWPARAM( ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID, + ItemInfo.fType | ItemInfo.fState | + (hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) hmenu->Self); } @@ -1714,8 +1723,8 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu) && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo)) { - WPARAM wParam = MAKELONG( Pos, ItemInfo.fType | ItemInfo.fState | - (TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); + WPARAM wParam = MAKEWPARAM( Pos, ItemInfo.fType | ItemInfo.fState | + (TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) topmenu); } @@ -1999,11 +2008,11 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) * * NOTE: flags is equivalent to the mtOption field */ -static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) +static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu) { WORD flags, id = 0; HMENU hSubMenu; - LPCSTR str; + LPCWSTR str; BOOL end = FALSE; do @@ -2020,46 +2029,19 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) id = GET_WORD(res); res += sizeof(WORD); } - str = res; - if(!unicode) - res += strlen(str) + 1; - else - res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR); + str = (LPCWSTR)res; + res += (strlenW(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); + if(!(res = MENU_ParseResource(res, hSubMenu))) return NULL; + AppendMenuW(hMenu, flags, (UINT_PTR)hSubMenu, (LPCWSTR)str); } else /* Not a popup */ { - if(!unicode) - { - if (*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(!unicode) - AppendMenuA(hMenu, flags, id, *str ? str : NULL); - else - AppendMenuW(hMenu, flags, id, - *(LPCWSTR)str ? (LPCWSTR)str : NULL); + AppendMenuW(hMenu, flags, id, *(LPCWSTR)str ? (LPCWSTR)str : NULL); } } while(!end); return res; @@ -2075,10 +2057,10 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) { WORD resinfo; - MENUITEMINFOW mii; - do { + MENUITEMINFOW mii; + mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE; mii.fType = GET_DWORD(res); @@ -2119,13 +2101,12 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) } mii.fMask |= MIIM_SUBMENU; mii.fType |= MF_POPUP; - mii.wID = (UINT)mii.hSubMenu; } - else if (!mii.dwTypeData[0]) + else if (!mii.dwTypeData[0] && !(mii.fType & MF_SEPARATOR)) + { mii.fType |= MF_SEPARATOR; - - if (!InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii)) - ERR("InsertMenuItemW failed\n"); + } + InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii); } while (!(resinfo & MF_END)); return res; } @@ -2332,7 +2313,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl if (0 == (Flags & TPM_NONOTIFY)) { SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu, - MAKELONG(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); + MAKELPARAM(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); } if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) @@ -2377,38 +2358,47 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl { MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE), GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU); - + if (Flags & TPM_LAYOUTRTL) Rect.left; NcGetSysPopupPos(MenuInfo->Wnd, &Rect); Rect.top = Rect.bottom; Rect.right = GetSystemMetrics(SM_CXSIZE); Rect.bottom = GetSystemMetrics(SM_CYSIZE); } else - { + { GetWindowRect(MenuInfo->Wnd, &Rect); if (0 != (MenuInfo->Flags & MNF_POPUP)) - { - Rect.left += ItemInfo.Rect.right - GetSystemMetrics(SM_CXBORDER); - Rect.top += ItemInfo.Rect.top - 3; + { + if(Flags & TPM_LAYOUTRTL) + Rect.left += GetSystemMetrics(SM_CXBORDER); + else + Rect.left += ItemInfo.Rect.right- GetSystemMetrics(SM_CXBORDER); + Rect.top += ItemInfo.Rect.top - MENU_TOP_MARGIN;//3; Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER); - Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - 3 - 2 - - GetSystemMetrics(SM_CYBORDER); - } + Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/ + - GetSystemMetrics(SM_CYBORDER); + } else - { - Rect.left += ItemInfo.Rect.left; + { + if(Flags & TPM_LAYOUTRTL) + Rect.left += Rect.right - ItemInfo.Rect.left; + else + Rect.left += ItemInfo.Rect.left; Rect.top += ItemInfo.Rect.bottom; Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left; Rect.bottom = ItemInfo.Rect.bottom - ItemInfo.Rect.top; - } - } + } + } + + /* use default alignment for submenus */ + Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags, Rect.left, Rect.top, Rect.right, Rect.bottom ); if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) - { + { MenuMoveSelection(WndOwner, &SubMenuInfo, ITEM_NEXT); - } + } Ret = ItemInfo.hSubMenu; MenuCleanupRosMenuItemInfo(&ItemInfo); @@ -2985,20 +2975,20 @@ MenuSuspendPopup(MTRACKER* Mt, UINT uMsg) switch( uMsg ) { - case WM_KEYDOWN: - PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); - if( msg.message == WM_KEYUP || msg.message == WM_PAINT ) - { - PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE); - PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); - if( msg.message == WM_KEYDOWN && - (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT)) - { - Mt->TrackFlags |= TF_SUSPENDPOPUP; - return TRUE; - } - } - break; + case WM_KEYDOWN: + PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); + if( msg.message == WM_KEYUP || msg.message == WM_PAINT ) + { + PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE); + PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); + if( msg.message == WM_KEYDOWN && + (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT)) + { + Mt->TrackFlags |= TF_SUSPENDPOPUP; + return TRUE; + } + } + break; } /* failures go through this */ Mt->TrackFlags &= ~TF_SUSPENDPOPUP; @@ -3622,6 +3612,7 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt) TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y); + if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) wFlags |= TPM_LAYOUTRTL; if (IsMenu(hMenu)) { /* map point to parent client coordinates */ @@ -3723,6 +3714,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, /* ReactOS Check */ if (!ValidateHwnd(Wnd)) { + /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */ return FALSE; } @@ -4823,7 +4815,7 @@ LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate) offset = GET_WORD(p); p += sizeof(WORD) + offset; if (!(hMenu = CreateMenu())) return 0; - if (!MENU_ParseResource(p, hMenu, TRUE)) + if (!MENU_ParseResource(p, hMenu)) { DestroyMenu(hMenu); return 0;