#define SEPARATOR_HEIGHT (5)
#define MENU_TAB_SPACE (8)
-#define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
-#define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
-#define POPUPMENU_CLASS_ATOMA MAKEINTATOMA(32768) /* PopupMenu */
-#define POPUPMENU_CLASS_ATOMW MAKEINTATOMW(32768) /* PopupMenu */
-
typedef struct
{
UINT TrackFlags;
*/
const struct builtin_class_descr POPUPMENU_builtin_class =
{
- POPUPMENU_CLASS_ATOMW, /* name */
+ WC_MENU, /* name */
CS_SAVEBITS | CS_DBLCLKS, /* style */
(WNDPROC) NULL, /* FIXME - procA */
(WNDPROC) PopupMenuWndProcW, /* FIXME - procW */
TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
- {
+ {
if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
- {
+ {
MenuInfo = &SysMenuInfo;
- }
+ }
else
- {
+ {
MenuInfo = NULL;
- }
- }
+ }
+ }
if (NULL != MenuInfo)
- {
+ {
if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
- {
+ {
return -1;
- }
- if (! ForceMenuChar)
- {
- Key = toupperW(Key);
+ }
+ if ( !ForceMenuChar )
+ {
ItemInfo = Items;
for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
- {
+ {
if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
- {
+ {
WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
do
- {
- p = strchrW(p + 2, '&');
- }
- while (NULL != p && L'&' == p[1]);
- if (NULL != p && (toupperW(p[1]) == Key))
- {
- return i;
- }
- }
- }
- }
+ {
+ p = strchrW (p + 2, '&');
+ }
+ while (p != NULL && p [1] == '&');
+ if (p && (toupperW(p[1]) == toupperW(Key))) return i;
+ }
+ }
+ }
MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self);
- if (2 == HIWORD(MenuChar))
- {
- return LOWORD(MenuChar);
- }
- if (1 == HIWORD(MenuChar))
- {
- return (UINT) (-2);
- }
+ if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
+ if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
}
-
return (UINT)(-1);
}
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.
+ * width of a menufont character to the width of an owner-drawn menu.
*/
lpitem->Rect.right += mis.itemWidth + 2 * MenuCharSize.cx;
}
if (menuBar) {
txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
- DT_SINGLELINE|DT_CALCRECT);
+ DT_SINGLELINE|DT_CALCRECT);
lpitem->Rect.right += rc.right - rc.left;
itemheight = max( max( itemheight, txtheight),
GetSystemMetrics( SM_CYMENU) - 1);
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
-
+
/* Setup colors */
if (lpitem->fState & MF_HILITE)
* Custom checkmark bitmaps are monochrome but not always 1bpp.
*/
if( !(MenuInfo->dwStyle & MNS_NOCHECK)) {
- bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked :
+ bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked :
lpitem->hbmpUnchecked;
if (bm) /* we have a custom bitmap */
{
if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount)
{
UINT u;
-
+
MenuInitRosMenuItemInfo(&ItemInfo);
for (u = 0; u < MenuInfo.MenuItemCount; u++)
}
/* store the owner for DrawItem */
+ if (!IsWindow(hwndOwner))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
MenuInfo.WndOwner = hwndOwner;
MenuSetRosMenuInfo(&MenuInfo);
if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
/* NOTE: In Windows, top menu popup is not owned. */
- MenuInfo.Wnd = CreateWindowExW( 0, POPUPMENU_CLASS_ATOMW, NULL,
+ MenuInfo.Wnd = CreateWindowExW( 0, WC_MENU, NULL,
WS_POPUP, x, y, width, height,
hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
(LPVOID) MenuInfo.Self);
MenuCleanupRosMenuItemInfo(&ItemInfo);
}
+//
+// This breaks some test results. Should handle A2U if called!
+//
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);
+#ifdef __REACTOS__
+ PWND pWnd;
+
+ pWnd = ValidateHwnd(Wnd);
+ if (pWnd)
+ {
+ if (!pWnd->fnid)
+ {
+ NtUserSetWindowFNID(Wnd, FNID_MENU);
+ }
+ }
+#endif
switch(Message)
{
top_popup = NULL;
top_popup_hmenu = NULL;
}
+#ifdef __REACTOS__
+ NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+#endif
break;
case WM_SHOWWINDOW:
break;
case MM_GETMENUHANDLE:
- case MN_GETHMENU:
+ case MN_GETHMENU:
return GetWindowLongPtrA(Wnd, 0);
default:
PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
TRACE("hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+#ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
+ PWND pWnd;
+
+ pWnd = ValidateHwnd(Wnd);
+ if (pWnd)
+ {
+ if (!pWnd->fnid)
+ {
+ NtUserSetWindowFNID(Wnd, FNID_MENU);
+ }
+ }
+#endif
switch(Message)
{
top_popup = NULL;
top_popup_hmenu = NULL;
}
+#ifdef __REACTOS__
+ NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+#endif
break;
case WM_SHOWWINDOW:
BOOL fRemove;
INT executedMenuId = -1;
MTRACKER mt;
+ HWND capture_win;
BOOL enterIdleSent = FALSE;
mt.TrackFlags = 0;
fEndMenu = !fRemove;
}
- SetCapture(mt.OwnerWnd);
- (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, mt.OwnerWnd);
+ if (wFlags & TF_ENDMENU) fEndMenu = TRUE;
+
+ /* owner may not be visible when tracking a popup, so use the menu itself */
+ capture_win = (wFlags & TPM_POPUPMENU) ? MenuInfo.Wnd : mt.OwnerWnd;
+ (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1
+ SetCapture(capture_win); // 2
- ERR("MenuTrackMenu 1\n");
while (! fEndMenu)
{
+ BOOL ErrorExit = FALSE;
PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU);
if (!menu) /* sometimes happens if I do a window manager close */
break;
}
else
{
+ /* ReactOS Check */
+ if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd))
+ {
+ ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works.
+ break;
+ }
if (!enterIdleSent)
{
HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL;
}
}
+ if (ErrorExit) break; // Gracefully dropout.
+
/* check if EndMenu() tried to cancel us, by posting this message */
if (msg.message == WM_CANCELMODE)
{
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
else mt.TrackFlags &= ~TF_SKIPREMOVE;
}
- ERR("MenuTrackMenu 2\n");
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */
static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
{
ROSMENUINFO MenuInfo;
-
+
TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu);
HideCaret(0);
+ /* 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 (MenuGetRosMenuInfo(&MenuInfo, hMenu))
+ {
+ MenuInfo.Wnd = hWnd;
+ MenuSetRosMenuInfo(&MenuInfo);
+ }
+
/* 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 );
}
}
- /* 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);
- }
-
IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
hWnd,
MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU,
MenuSelectItem( hwnd, &MenuInfo, uItem, TRUE, 0 );
- if (wParam & HTSYSMENU)
- {
- /* prevent sysmenu activation for managed windows on Alt down/up */
-// if (GetPropA( hwnd, "__wine_x11_managed" ))
- wFlags |= TF_ENDMENU; /* schedule end of menu tracking */
- }
- else
+ if (!(wParam & HTSYSMENU) || wChar == ' ')
{
if( uItem == NO_SELECTED_ITEM )
MenuMoveSelection( hwnd, &MenuInfo, ITEM_NEXT );
else
- PostMessageW( hwnd, WM_KEYDOWN, VK_DOWN, 0L );
+ PostMessageW( hwnd, WM_KEYDOWN, VK_RETURN, 0 );
}
track_menu:
HWND Wnd, LPTPMPARAMS Tpm)
{
BOOL ret = FALSE;
+ ROSMENUINFO MenuInfo;
- if (!IsMenu(Menu))
+ if (!IsMenu(Menu))
{
SetLastError( ERROR_INVALID_MENU_HANDLE );
return FALSE;
}
+ /* ReactOS Check */
+ if (!ValidateHwnd(Wnd))
+ {
+ return FALSE;
+ }
+
+ MenuGetRosMenuInfo(&MenuInfo, Menu);
+ if (IsWindow(MenuInfo.Wnd))
+ {
+ SetLastError( ERROR_POPUP_ALREADY_ACTIVE );
+ return FALSE;
+ }
+
MenuInitTracking(Wnd, Menu, TRUE, Flags);
/* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PLOADMENU_CALLBACK_ARGUMENTS Common;
- LRESULT Result;
+ LRESULT Result;
Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
-
+
Result = (LRESULT)LoadMenuW( Common->hModule,
IS_INTRESOURCE(Common->MenuName[0]) ?
MAKEINTRESOURCE(Common->MenuName[0]) :
MenuGetRosMenuInfo(&MenuInfo, hMenu);
MenuInfo.Height = 0; // make sure to recalc size
MenuSetRosMenuInfo(&MenuInfo);
- /* The wine method doesn't work and I suspect it's more effort
- then hackfix solution
+
SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
SWP_NOZORDER | SWP_FRAMECHANGED );
- return TRUE;*/
- // FIXME: hackfix
- DefWndNCPaint(hWnd,(HRGN)-1,-1);
return TRUE;
}
return TRUE;
}
-// So this one maybe one day it will be a callback!
-BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
- UINT wHilite )
-{
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO mii;
- TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
- if (!hWnd)
- {
- SetLastError(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
- if (!NtUserMenuItemInfo(hMenu, wItemID, wHilite, &mii, FALSE)) return FALSE;
- if (!NtUserMenuInfo(hMenu, &MenuInfo, FALSE)) return FALSE;
- if (MenuInfo.FocusedItem == wItemID) return TRUE;
- MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 );
- MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 );
- return TRUE;
-}
/*
* @implemented