- Move menu related functions. Support more system commands. Add a thread based menu structure.

svn path=/trunk/; revision=68621
This commit is contained in:
James Tabor 2015-08-08 00:25:04 +00:00
parent d1c5a86965
commit 085f7653ed
3 changed files with 193 additions and 120 deletions

View file

@ -620,6 +620,7 @@ IntCloneMenu(PMENU Source)
BOOL FASTCALL
IntSetMenuFlagRtoL(PMENU Menu)
{
ERR("SetMenuFlagRtoL\n");
Menu->fFlags |= MNF_RTOL;
return TRUE;
}
@ -705,6 +706,12 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
Menu->TimeToHide = lpmi->TimeToHide;
Menu->hWnd = lpmi->Wnd;
}
if ( lpmi->fMask & MIM_STYLE)
{
if (lpmi->dwStyle & MNS_AUTODISMISS) FIXME("MNS_AUTODISMISS unimplemented wine\n");
if (lpmi->dwStyle & MNS_DRAGDROP) FIXME("MNS_DRAGDROP unimplemented wine\n");
if (lpmi->dwStyle & MNS_MODELESS) FIXME("MNS_MODELESS unimplemented wine\n");
}
return TRUE;
}
@ -971,8 +978,16 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
MenuItem->fState ^= (res ^ uEnable) & (MF_GRAYED | MF_DISABLED);
/* If the close item in the system menu change update the close button */
if((MenuItem->wID == SC_CLOSE) && (res != uEnable))
if (res != uEnable)
{
switch (MenuItem->wID) // More than just close.
{
case SC_CLOSE:
case SC_MAXIMIZE:
case SC_MINIMIZE:
case SC_MOVE:
case SC_RESTORE:
case SC_SIZE:
if (MenuObject->fFlags & MNF_SYSSUBMENU && MenuObject->spwndNotify != 0)
{
RECTL rc = MenuObject->spwndNotify->rcWindow;
@ -982,6 +997,9 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
rc.bottom = 0;
co_UserRedrawWindow(MenuObject->spwndNotify, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
}
default:
break;
}
}
return res;
}
@ -1822,6 +1840,77 @@ IntSetSystemMenu(PWND Window, PMENU Menu)
return TRUE;
}
BOOL FASTCALL
IntSetMenu(
PWND Wnd,
HMENU Menu,
BOOL *Changed)
{
PMENU OldMenu, NewMenu = NULL;
if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
{
ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd));
EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
*Changed = (Wnd->IDMenu != (UINT) Menu);
if (! *Changed)
{
return TRUE;
}
if (Wnd->IDMenu)
{
OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu);
ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h);
}
else
{
OldMenu = NULL;
}
if (NULL != Menu)
{
NewMenu = IntGetMenuObject(Menu);
if (NULL == NewMenu)
{
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
if (NULL != NewMenu->hWnd)
{
/* Can't use the same menu for two windows */
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
}
Wnd->IDMenu = (UINT) Menu;
if (NULL != NewMenu)
{
NewMenu->hWnd = Wnd->head.h;
IntReleaseMenuObject(NewMenu);
}
if (NULL != OldMenu)
{
OldMenu->hWnd = NULL;
IntReleaseMenuObject(OldMenu);
}
return TRUE;
}
/* FUNCTIONS *****************************************************************/
@ -2142,6 +2231,7 @@ NtUserGetMenuBarInfo(
HMENU hMenu;
MENUBARINFO kmbi;
BOOL Ret;
PPOPUPMENU pPopupMenu;
NTSTATUS Status = STATUS_SUCCESS;
PMENU Menu = NULL;
DECLARE_RETURN(BOOL);
@ -2226,7 +2316,13 @@ NtUserGetMenuBarInfo(
kmbi.hwndMenu = NULL;
kmbi.fBarFocused = FALSE;
kmbi.fFocused = FALSE;
//kmbi.fBarFocused = top_popup_hmenu == hMenu;
pPopupMenu = ((PMENUWND)pWnd)->ppopupmenu;
if (pPopupMenu)
{
//kmbi.fBarFocused = pPopupMenu->spmenu == Menu;
}
if (idItem)
{
kmbi.fFocused = Menu->iItem == idItem-1;
@ -2238,8 +2334,8 @@ NtUserGetMenuBarInfo(
/* else
{
kmbi.fFocused = kmbi.fBarFocused;
}
*/
}*/
_SEH2_TRY
{
RtlCopyMemory(pmbi, &kmbi, sizeof(MENUBARINFO));
@ -2505,6 +2601,49 @@ CLEANUP:
}
/*
* @implemented
*/
BOOL APIENTRY
NtUserSetMenu(
HWND hWnd,
HMENU Menu,
BOOL Repaint)
{
PWND Window;
BOOL Changed;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserSetMenu\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
if (! IntSetMenu(Window, Menu, &Changed))
{
RETURN( FALSE);
}
// Not minimized and please repaint!!!
if (!(Window->style & WS_MINIMIZE) && (Repaint || Changed))
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(Window, &Ref);
co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
UserDerefObjectCo(Window);
}
RETURN( TRUE);
CLEANUP:
TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/

View file

@ -10,6 +10,55 @@
#define MF_END (0x0080)
#endif
typedef struct tagMENUSTATE
{
PPOPUPMENU pGlobalPopupMenu;
struct
{
ULONG fMenuStarted:1;
ULONG fIsSysMenu:1;
ULONG fInsideMenuLoop:1;
ULONG fButtonDown:1;
ULONG fInEndMenu:1;
ULONG fUnderline:1;
ULONG fButtonAlwaysDown:1;
ULONG fDragging:1;
ULONG fModelessMenu:1;
ULONG fInCallHandleMenuMessages:1;
ULONG fDragAndDrop:1;
ULONG fAutoDismiss:1;
ULONG fAboutToAutoDismiss:1;
ULONG fIgnoreButtonUp:1;
ULONG fMouseOffMenu:1;
ULONG fInDoDragDrop:1;
ULONG fActiveNoForeground:1;
ULONG fNotifyByPos:1;
ULONG fSetCapture:1;
ULONG iAniDropDir:5;
};
POINT ptMouseLast;
INT mnFocus;
INT cmdLast;
PTHREADINFO ptiMenuStateOwner;
DWORD dwLockCount;
struct tagMENUSTATE* pmnsPrev;
POINT ptButtonDown;
ULONG_PTR uButtonDownHitArea;
UINT uButtonDownIndex;
INT vkButtonDown;
ULONG_PTR uDraggingHitArea;
UINT uDraggingIndex;
UINT uDraggingFlags;
HDC hdcWndAni;
DWORD dwAniStartTime;
INT ixAni;
INT iyAni;
INT cxAni;
INT cyAni;
HBITMAP hbmAni;
HDC hdcAni;
} MENUSTATE, *PMENUSTATE;
typedef struct _SETMENUITEMRECT
{
UINT uItem;
@ -51,3 +100,4 @@ UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags);
BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse);
PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
BOOL FASTCALL IntMenuItemInfo(PMENU Menu, UINT Item, BOOL ByPosition, PROSMENUITEMINFO UnsafeItemInfo, BOOL SetOrGet, PUNICODE_STRING lpstr);
BOOL FASTCALL IntSetMenu(PWND Wnd,HMENU Menu,BOOL *Changed);

View file

@ -794,77 +794,6 @@ IntSetWindowProc(PWND pWnd,
return Ret;
}
static BOOL FASTCALL
IntSetMenu(
PWND Wnd,
HMENU Menu,
BOOL *Changed)
{
PMENU OldMenu, NewMenu = NULL;
if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
{
ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd));
EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
*Changed = (Wnd->IDMenu != (UINT) Menu);
if (! *Changed)
{
return TRUE;
}
if (Wnd->IDMenu)
{
OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu);
ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h);
}
else
{
OldMenu = NULL;
}
if (NULL != Menu)
{
NewMenu = IntGetMenuObject(Menu);
if (NULL == NewMenu)
{
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
if (NULL != NewMenu->hWnd)
{
/* Can't use the same menu for two windows */
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
}
Wnd->IDMenu = (UINT) Menu;
if (NULL != NewMenu)
{
NewMenu->hWnd = Wnd->head.h;
IntReleaseMenuObject(NewMenu);
}
if (NULL != OldMenu)
{
OldMenu->hWnd = NULL;
IntReleaseMenuObject(OldMenu);
}
return TRUE;
}
/* INTERNAL ******************************************************************/
@ -3939,51 +3868,6 @@ CLEANUP:
END_CLEANUP;
}
/*
* @implemented
*/
BOOL APIENTRY
NtUserSetMenu(
HWND hWnd,
HMENU Menu,
BOOL Repaint)
{
PWND Window;
BOOL Changed;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserSetMenu\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
if (! IntSetMenu(Window, Menu, &Changed))
{
RETURN( FALSE);
}
if (Changed && Repaint)
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(Window, &Ref);
co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
UserDerefObjectCo(Window);
}
RETURN( TRUE);
CLEANUP:
TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/