* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: menu.c,v 1.61 2004/04/02 19:14:44 weiden Exp $
+/* $Id$
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/menu.c
/* INCLUDES ******************************************************************/
-#define __NTAPP__
-
-#include <windows.h>
#include <user32.h>
-#include <string.h>
-#include <draw.h>
-#include <window.h>
-#include <strpool.h>
-#include <ntos/rtl.h>
-
-#include <user32/callback.h>
-#include "user32/regcontrol.h"
-#include "../controls/controls.h"
-
#define NDEBUG
#include <debug.h>
(0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
#define IS_MAGIC_ITEM(Bmp) ((int) Bmp <12)
-
+
#define MENU_BAR_ITEMS_SPACE (12)
#define SEPARATOR_HEIGHT (5)
#define MENU_TAB_SPACE (8)
const struct builtin_class_descr POPUPMENU_builtin_class =
{
POPUPMENU_CLASS_ATOMW, /* name */
- CS_GLOBALCLASS | CS_SAVEBITS | CS_DBLCLKS, /* style */
+ CS_SAVEBITS | CS_DBLCLKS, /* style */
(WNDPROC) PopupMenuWndProcW, /* FIXME - procW */
(WNDPROC) NULL, /* FIXME - procA */
sizeof(MENUINFO *), /* extra */
- (LPCWSTR) IDC_ARROW, /* cursor */
- (HBRUSH)(COLOR_MENU + 1) /* brush */
+ (LPCWSTR) IDC_ARROW, /* cursor */
+ (HBRUSH)(COLOR_MENU + 1) /* brush */
};
/* INTERNAL FUNCTIONS ********************************************************/
-/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
- * Of course I didnt copy the ASM code because we want this to be portable
+/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
+ * Of course I didnt copy the ASM code because we want this to be portable
* and it needs to go away.
*/
{
MenuInfo->cbSize = sizeof(ROSMENUINFO);
MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-
+
return NtUserMenuInfo(Menu, MenuInfo, FALSE);
}
{
MenuInfo->cbSize = sizeof(ROSMENUINFO);
MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-
+
return NtUserMenuInfo(MenuInfo->Self, MenuInfo, TRUE);
}
*
* Get full information about a menu item
*/
-#define INITIAL_STRING_SIZE 32 /* in WCHARs */
static BOOL FASTCALL
MenuGetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
{
- UNICODE_STRING Text;
-
- if (MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType) && NULL != ItemInfo->dwTypeData)
- {
- /* There's already a buffer allocated */
- Text.Buffer = ItemInfo->dwTypeData;
- Text.Length = ItemInfo->cch * sizeof(WCHAR);
- Text.MaximumLength = (ItemInfo->cch < INITIAL_STRING_SIZE ? INITIAL_STRING_SIZE
- : ItemInfo->cch + 1) * sizeof(WCHAR);
- }
- else
+ if (ItemInfo->dwTypeData != NULL)
{
- Text.Buffer = HeapAlloc(GetProcessHeap(), 0, INITIAL_STRING_SIZE * sizeof(WCHAR));
- if (NULL == Text.Buffer)
- {
- return FALSE;
- }
- Text.Length = 0;
- Text.MaximumLength = INITIAL_STRING_SIZE * sizeof(WCHAR);
- ItemInfo->cch = INITIAL_STRING_SIZE - 1;
+ HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
}
- ItemInfo->dwTypeData = (LPWSTR) &Text;
ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
| MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
+ ItemInfo->dwTypeData = NULL;
if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE))
{
- if (NULL != Text.Buffer)
- {
- HeapFree(GetProcessHeap(), 0, Text.Buffer);
- ItemInfo->dwTypeData = NULL;
- ItemInfo->cch = 0;
- }
ItemInfo->fType = 0;
return FALSE;
}
- if (MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType))
+ if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING)
{
- /* We have a string... */
- if (Text.MaximumLength < (ItemInfo->cch + 1) * sizeof(WCHAR))
+ ItemInfo->cch++;
+ ItemInfo->dwTypeData = HeapAlloc(GetProcessHeap(), 0,
+ ItemInfo->cch * sizeof(WCHAR));
+ if (NULL == ItemInfo->dwTypeData)
{
- /* ...but we didn't allocate enough memory. Let's try again */
- HeapFree(GetProcessHeap(), 0, Text.Buffer);
- Text.Buffer = HeapAlloc(GetProcessHeap(), 0, (ItemInfo->cch + 1) * sizeof(WCHAR));
- if (NULL == Text.Buffer)
- {
- ItemInfo->dwTypeData = NULL;
- ItemInfo->cch = 0;
- return FALSE;
- }
- Text.Length = (ItemInfo->cch + 1) * sizeof(WCHAR);
- Text.MaximumLength = (ItemInfo->cch + 1) * sizeof(WCHAR);
- ItemInfo->cch++;
- if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE))
- {
- HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
- ItemInfo->dwTypeData = NULL;
- ItemInfo->cch = 0;
- ItemInfo->fType = 0;
- }
+ return FALSE;
}
- }
- if (MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType))
- {
- ItemInfo->dwTypeData = Text.Buffer;
- ItemInfo->cch = Text.Length / sizeof(WCHAR);
- Text.Buffer[ItemInfo->cch] = L'\0';
- }
- else
- {
- /* Not a string, clean up the buffer */
- if (NULL != Text.Buffer)
+ if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE))
{
- HeapFree(GetProcessHeap(), 0, Text.Buffer);
+ ItemInfo->fType = 0;
+ return FALSE;
}
}
static BOOL FASTCALL
MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
{
- UNICODE_STRING Text;
- BOOL StringVal;
BOOL Ret;
- StringVal = (MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType) && NULL != ItemInfo->dwTypeData);
- if (StringVal)
- {
- Text.Buffer = ItemInfo->dwTypeData;
- Text.Length = wcslen(Text.Buffer) * sizeof(WCHAR);
- Text.MaximumLength = Text.Length + sizeof(WCHAR);
- ItemInfo->dwTypeData = (LPWSTR) &Text;
- }
+ if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING &&
+ ItemInfo->dwTypeData != NULL)
+ {
+ ItemInfo->cch = wcslen(ItemInfo->dwTypeData);
+ }
ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
| MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
-
- Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE);
- if (StringVal)
- {
- ItemInfo->dwTypeData = Text.Buffer;
- }
+
+ Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE);
return Ret;
}
static VOID FASTCALL
MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
{
- if (MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType) && NULL != ItemInfo->dwTypeData)
+ if (ItemInfo->dwTypeData != NULL)
{
HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
- ItemInfo->dwTypeData = NULL;
- ItemInfo->cch = 0;
}
}
/* check if there is a magic menu item associated with this item */
if (0 != Id && IS_MAGIC_ITEM(Id))
{
- switch(LOWORD(Id))
+ switch((INT_PTR) LOWORD(Id))
{
case (INT_PTR) HBMMENU_SYSTEM:
if (0 != Data)
case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
case (INT_PTR) HBMMENU_MBAR_CLOSE:
case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
- Size->cx = GetSystemMetrics(SM_CXSIZE);
- Size->cy = GetSystemMetrics(SM_CYSIZE);
+ /* FIXME: Why we need to subtract these magic values? */
+ Size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
+ Size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
return;
case (INT_PTR) HBMMENU_CALLBACK:
case (INT_PTR) HBMMENU_POPUP_CLOSE:
case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
default:
- FIXME("Magic menu bitmap not implemented\n");
+ DPRINT("Magic menu bitmap not implemented\n");
return;
}
}
UINT Flags = 0;
RECT r;
+ r = *Rect;
switch ((int) Item->hbmpItem)
{
case (INT_PTR) HBMMENU_SYSTEM:
Flags = DFCS_CAPTIONRESTORE;
break;
case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
+ r.right += 1;
Flags = DFCS_CAPTIONMIN;
break;
case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
+ r.right += 1;
Flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
break;
case (INT_PTR) HBMMENU_MBAR_CLOSE:
case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
default:
- FIXME("Magic menu bitmap not implemented\n");
+ DPRINT("Magic menu bitmap not implemented\n");
return;
}
- r = *Rect;
InflateRect(&r, -1, -1);
if (0 != (Item->fState & MF_HILITE))
{
dis.hDC = Dc;
dis.rcItem = Item->Rect;
DPRINT("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
- "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hwndOwner,
+ "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", Wnd,
dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
dis.rcItem.bottom);
/* Fall through to draw popup-menu arrow */
}
- DPRINT("rect={%ld,%ld,%ld,%ld}\n", Item->rect.left, Item->rect.top,
- Item->rect.right, Item->rect.bottom);
+ DPRINT("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))
{
MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
}
}
+
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
}
}
else
User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
{
LRESULT Result;
- HMODULE hUser32;
- hUser32 = GetModuleHandleW(L"USER32");
- Result = (LRESULT)LoadMenuW(hUser32, L"SYSMENU");
+ Result = (LRESULT)LoadMenuW(User32Instance, L"SYSMENU");
return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
}
MenuInit(VOID)
{
NONCLIENTMETRICSW ncm;
-
+
/* get the menu font */
if(!hMenuFont || !hMenuFontBold)
{
DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
return FALSE;
}
-
+
hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
if(hMenuFont == NULL)
{
DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
return FALSE;
}
-
+
ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
if(hMenuFontBold == NULL)
{
DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
return FALSE;
}
}
}
+VOID
+MenuCleanup(VOID)
+{
+ if (hMenuFont)
+ {
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
+ }
+
+ if (hMenuFontBold)
+ {
+ DeleteObject(hMenuFontBold);
+ hMenuFontBold = NULL;
+ }
+}
+
+
+
/***********************************************************************
* MenuCalcItemSize
*
/* Leave space for the sunken border */
ItemInfo->Rect.right += 2;
ItemInfo->Rect.bottom += 2;
+
+ /* Special case: Minimize button doesn't have a space behind it. */
+ if (ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
+ ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
+ ItemInfo->Rect.right -= 1;
}
/* it must be a text item - unless it's the system menu */
}
DPRINT("left=%ld top=%ld right=%ld bottom=%ld\n",
- Rrect->left, Rect->top, Rect->right, Rect->bottom);
+ Rect->left, Rect->top, Rect->right, Rect->bottom);
MenuInfo->Width = Rect->right - Rect->left;
MenuInfo->Height = 0;
MaxY = Rect->top + 1;
}
}
+/* FIXME: Is this really needed? */
+#if 0
/* Finish the line (set all items to the largest height found) */
while (Start < i)
{
}
Start++;
}
+#else
+ Start = i;
+#endif
}
Rect->bottom = MaxY;
{
FontOld = SelectObject(DC, hMenuFont);
- if (0 == MenuInfo.Height)
- {
- MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
- }
+ MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
Rect->bottom = Rect->top + MenuInfo.Height;
{
INT i;
ROSMENUITEMINFO ItemInfo;
+ INT OrigPos;
- DPRINT("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, offset);
+ DPRINT("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);
- if (NO_SELECTED_ITEM != MenuInfo->FocusedItem)
+
+ OrigPos = MenuInfo->FocusedItem;
+ if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */
{
- if (1 == MenuInfo->MenuItemCount)
+ OrigPos = 0;
+ i = -1;
+ }
+ else
+ {
+ i = MenuInfo->FocusedItem;
+ }
+
+ do
+ {
+ /* Step */
+ i += Offset;
+ /* Clip and wrap around */
+ if (i < 0)
{
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
+ i = MenuInfo->MenuItemCount - 1;
}
- else
+ else if (i >= MenuInfo->MenuItemCount)
{
- for (i = MenuInfo->FocusedItem + Offset;
- 0 <= i && i < MenuInfo->MenuItemCount;
- i += Offset)
- {
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
- 0 == (ItemInfo.fType & MF_SEPARATOR))
- {
- MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- }
+ i = 0;
}
- }
-
- for (i = (0 < Offset) ? 0 : MenuInfo->MenuItemCount - 1;
- 0 <= i && i < MenuInfo->MenuItemCount; i += Offset)
- {
+ /* If this is a good candidate; */
if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
- 0 == (ItemInfo.fType & MF_SEPARATOR))
+ 0 == (ItemInfo.fType & MF_SEPARATOR) &&
+ 0 == (ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
{
MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
- }
+ } while (i != OrigPos);
+ /* Not found */
MenuCleanupRosMenuItemInfo(&ItemInfo);
}
{
EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
}
-
+
/* Set default menu item */
if(Style & WS_MINIMIZE)
{
#if 0
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_STATE;
- if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
+ if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
(mii.fState & (MFS_GRAYED | MFS_DISABLED)))
{
DefItem = SC_CLOSE;
return FALSE;
}
- if (MenuInfo.FocusedItem != Index)
- {
- MenuSwitchTracking(Mt, &MenuInfo, Index);
- }
+ if (!(Item.fType & MF_SEPARATOR) &&
+ !(Item.fState & (MFS_DISABLED | MFS_GRAYED)) )
+ {
+ if (MenuInfo.FocusedItem != Index)
+ {
+ MenuSwitchTracking(Mt, &MenuInfo, Index);
+ }
- /* If the popup menu is not already "popped" */
- if (0 == (Item.fState & MF_MOUSESELECT))
- {
- Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+ /* If the popup menu is not already "popped" */
+ if (0 == (Item.fState & MF_MOUSESELECT))
+ {
+ Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+ }
}
MenuCleanupRosMenuItemInfo(&Item);
{
UINT Index;
ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
if (NULL != PtMenu)
{
}
else if (MenuInfo.FocusedItem != Index)
{
- MenuSwitchTracking(Mt, &MenuInfo, Index);
- Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+ MenuInitRosMenuItemInfo(&ItemInfo);
+ if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) &&
+ !(ItemInfo.fType & MF_SEPARATOR) &&
+ !(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
+ {
+ MenuSwitchTracking(Mt, &MenuInfo, Index);
+ Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+ }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
}
return TRUE;
{
Mt->OwnerWnd = NewWnd;
SetCapture(Mt->OwnerWnd);
+ NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt->OwnerWnd);
}
Mt->TopMenu = Mt->CurrentMenu = NewMenu; /* all subpopups are hidden */
}
SetCapture(Mt.OwnerWnd);
+ NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt.OwnerWnd);
while (! fEndMenu)
{
case WM_SYSKEYDOWN:
switch (Msg.wParam)
{
+ DbgPrint("Menu.c WM_SYSKEYDOWN wPram %d\n",Msg.wParam);
case VK_MENU:
fEndMenu = TRUE;
break;
+ case VK_LMENU:
+ fEndMenu = TRUE;
+ break;
}
break; /* WM_SYSKEYDOWN */
}
}
+ NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */
/* If dropdown is still painted and the close box is clicked on
static BOOL FASTCALL
MenuExitTracking(HWND Wnd)
{
- DPRINT("hwnd=%p\n", hWnd);
+ DPRINT("hwnd=%p\n", Wnd);
SendMessageW(Wnd, WM_EXITMENULOOP, 0, 0);
ShowCaret(0);
HMENU Menu = (HTSYSMENU == Ht) ? NtUserGetSystemMenu(Wnd, FALSE) : GetMenu(Wnd);
UINT Flags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
- DPRINT("wnd=%p ht=0x%04x (%ld,%ld)\n", Wnd, Ht, pt.x, pt.y);
+ DPRINT("wnd=%p ht=0x%04x (%ld,%ld)\n", Wnd, Ht, Pt.x, Pt.y);
if (IsMenu(Menu))
{
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
+ return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
lpNewItem));
}
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
- return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
+ return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
lpNewItem));
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
CheckMenuRadioItem(HMENU hmenu,
UINT idCheck,
UINT uFlags)
{
+ ROSMENUINFO mi;
+ PROSMENUITEMINFO Items;
+ int i;
+ BOOL ret = FALSE;
+
+ mi.cbSize = sizeof(MENUINFO);
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(idFirst > idLast) return ret;
+
+ if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret;
+
+ if(MenuGetAllRosMenuItemInfo(mi.Self, &Items) <= 0) return ret;
+
+ for (i = 0 ; i < mi.MenuItemCount; i++)
+ {
+ if (0 != (Items[i].fType & MF_MENUBARBREAK)) break;
+ if ( i >= idFirst && i <= idLast )
+ {
+ if ( i == idCheck)
+ {
+ Items[i].fType |= MFT_RADIOCHECK;
+ Items[i].fState |= MFS_CHECKED;
+ }
+ else
+ {
+ Items[i].fType &= ~MFT_RADIOCHECK;
+ Items[i].fState &= ~MFS_CHECKED;
+ }
+ if(!MenuSetRosMenuItemInfo(mi.Self, i ,&Items[i]))
+ break;
+ }
+ if ( i == mi.MenuItemCount) ret = TRUE;
+ }
+ MenuCleanupRosMenuItemInfo(Items);
+ return ret;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
DrawMenuBar(HWND hWnd)
{
- UNIMPLEMENTED
- /* FIXME - return NtUserCallHwndLock(hWnd, 0x55); */
- return FALSE;
+ return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR);
}
/*
* @implemented
*/
-UINT STDCALL
+BOOL STDCALL
EnableMenuItem(HMENU hMenu,
UINT uIDEnableItem,
UINT uEnable)
LONG STDCALL
GetMenuCheckMarkDimensions(VOID)
{
- return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
+ return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
GetSystemMetrics(SM_CYMENUCHECK)));
}
{
ROSMENUINFO mi;
BOOL res = FALSE;
-
+
if(!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO)))
return FALSE;
-
+
RtlZeroMemory(&mi, sizeof(MENUINFO));
mi.cbSize = sizeof(MENUINFO);
mi.fMask = lpcmi->fMask;
-
+
res = NtUserMenuInfo(hmenu, &mi, FALSE);
-
+
memcpy(lpcmi, &mi, sizeof(MENUINFO));
return res;
}
int nPos)
{
ROSMENUITEMINFO mii;
-
+
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_ID | MIIM_SUBMENU;
-
+
if (! NtUserMenuItemInfo(hMenu, nPos, MF_BYPOSITION, &mii, FALSE))
{
return -1;
}
-
+
if (NULL != mii.hSubMenu)
{
return -1;
{
return -1;
}
-
+
return mii.wID;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
GetMenuItemInfoA(
- HMENU hMenu,
- UINT uItem,
- BOOL fByPosition,
- LPMENUITEMINFOA lpmii)
+ HMENU Menu,
+ UINT Item,
+ BOOL ByPosition,
+ LPMENUITEMINFOA mii)
{
- UNIMPLEMENTED;
- return FALSE;
+ LPSTR AnsiBuffer;
+ MENUITEMINFOW miiW;
+
+ if (mii->cbSize != sizeof(MENUITEMINFOA) &&
+ mii->cbSize != sizeof(MENUITEMINFOA) - sizeof(HBITMAP))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if ((mii->fMask & (MIIM_STRING | MIIM_TYPE)) == 0)
+ {
+ /* No text requested, just pass on */
+ return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE);
+ }
+
+ RtlCopyMemory(&miiW, mii, mii->cbSize);
+ AnsiBuffer = mii->dwTypeData;
+
+ if (AnsiBuffer != NULL)
+ {
+ miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0,
+ miiW.cch * sizeof(WCHAR));
+ if (miiW.dwTypeData == NULL)
+ return FALSE;
+ }
+
+ if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE))
+ {
+ HeapFree(GetProcessHeap(), 0, miiW.dwTypeData);
+ return FALSE;
+ }
+
+ if (AnsiBuffer != NULL)
+ {
+ if (IS_STRING_ITEM(miiW.fType))
+ {
+ WideCharToMultiByte(CP_ACP, 0, miiW.dwTypeData, miiW.cch, AnsiBuffer,
+ mii->cch, NULL, NULL);
+ }
+ RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData);
+ }
+
+ RtlCopyMemory(mii, &miiW, miiW.cbSize);
+ if (AnsiBuffer)
+ {
+ mii->dwTypeData = AnsiBuffer;
+ mii->cch = strlen(AnsiBuffer);
+ }
+ return TRUE;
}
/*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
+BOOL STDCALL
GetMenuItemInfoW(
- HMENU hMenu,
- UINT uItem,
- BOOL fByPosition,
- LPMENUITEMINFOW lpmii)
+ HMENU Menu,
+ UINT Item,
+ BOOL ByPosition,
+ LPMENUITEMINFOW mii)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
GetMenuItemRect(HWND hWnd,
UINT uItem,
LPRECT lprcItem)
{
- UNIMPLEMENTED;
- return(FALSE);
+ return NtUserGetMenuItemRect( hWnd, hMenu, uItem, lprcItem);
}
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU;
-
+ mii.dwTypeData = NULL;
+
SetLastError(0);
if(NtUserMenuItemInfo(hMenu, uId, uFlags, &mii, FALSE))
{
return (UINT) -1;
}
nSubItems = MenuInfo.MenuItemCount;
-
+
/* FIXME - ported from wine, does that work (0xff)? */
if(GetLastError() != ERROR_INVALID_MENU_HANDLE)
return (nSubItems << 8) | ((mii.fState | mii.fType) & 0xff);
return (UINT)-1; /* Invalid submenu */
}
-
+
/* FIXME - ported from wine, does that work? */
return (mii.fType | mii.fState);
}
-
+
return (UINT)-1;
}
/*
- * @unimplemented
+ * @implemented
*/
int
STDCALL
int nMaxCount,
UINT uFlag)
{
- UNIMPLEMENTED;
- return 0;
+ MENUITEMINFOA mii;
+ mii.dwTypeData = lpString;
+ mii.fMask = MIIM_STRING;
+ mii.fType = MF_STRING;
+ mii.cbSize = sizeof(MENUITEMINFOA);
+ mii.cch = nMaxCount;
+
+ if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
+ return 0;
+ else
+ return mii.cch;
}
/*
- * @unimplemented
+ * @implemented
*/
int
STDCALL
int nMaxCount,
UINT uFlag)
{
- UNIMPLEMENTED;
- return 0;
+ MENUITEMINFOW miiW;
+ miiW.dwTypeData = lpString;
+ miiW.fMask = MIIM_STRING;
+ miiW.cbSize = sizeof(MENUITEMINFOW);
+ miiW.cch = nMaxCount;
+
+ if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
+ return 0;
+ else
+ return miiW.cch;
}
mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
mii.fType = 0;
mii.fState = MFS_ENABLED;
-
+
if(uFlags & MF_BITMAP)
{
mii.fType |= MFT_BITMAP;
mii.dwTypeData = (LPSTR)lpNewItem;
mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
}
-
+
if(uFlags & MF_RIGHTJUSTIFY)
{
mii.fType |= MFT_RIGHTJUSTIFY;
{
mii.fState |= MFS_GRAYED;
}
-
+
if(uFlags & MF_POPUP)
{
mii.fType |= MF_POPUP;
mii.fMask |= MIIM_ID;
mii.wID = (UINT)uIDNewItem;
}
- return InsertMenuItemA(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+ return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
}
BOOL CleanHeap = FALSE;
NTSTATUS Status;
- if((lpmii->cbSize == sizeof(MENUITEMINFOA)) ||
+ if((lpmii->cbSize == sizeof(MENUITEMINFOA)) ||
(lpmii->cbSize == sizeof(MENUITEMINFOA) - sizeof(HBITMAP)))
{
RtlMoveMemory ( &mi, lpmii, lpmii->cbSize );
/* copy the text string */
- if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
+ if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
(MENU_ITEM_TYPE(mi.fType) == MF_STRING) && mi.dwTypeData)
{
- Status = HEAP_strdupAtoW ( &mi.dwTypeData, (LPCSTR)mi.dwTypeData, &mi.cch );
+ Status = RtlCreateUnicodeStringFromAsciiz(&MenuText, (LPSTR)mi.dwTypeData);
if (!NT_SUCCESS (Status))
{
SetLastError (RtlNtStatusToDosError(Status));
return FALSE;
}
- RtlInitUnicodeString(&MenuText, (PWSTR)mi.dwTypeData);
- mi.dwTypeData = (LPWSTR)&MenuText;
+ mi.dwTypeData = MenuText.Buffer;
+ mi.cch = MenuText.Length / sizeof(WCHAR);
CleanHeap = TRUE;
}
res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
- if ( CleanHeap ) HEAP_free ( mi.dwTypeData );
+ if ( CleanHeap ) RtlFreeUnicodeString ( &MenuText );
}
return res;
}
MENUITEMINFOW mi;
UNICODE_STRING MenuText;
BOOL res = FALSE;
- BOOL CleanHeap = FALSE;
- HANDLE hHeap = RtlGetProcessHeap();
mi.hbmpItem = (HBITMAP)0;
- // while we could just pass 'lpmii' to win32k, we make a copy so that
- // if a bad user passes bad data, we crash his process instead of the
- // entire kernel
+ /* while we could just pass 'lpmii' to win32k, we make a copy so that
+ if a bad user passes bad data, we crash his process instead of the
+ entire kernel */
- if((lpmii->cbSize == sizeof(MENUITEMINFOW)) ||
+ if((lpmii->cbSize == sizeof(MENUITEMINFOW)) ||
(lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP)))
{
memcpy(&mi, lpmii, lpmii->cbSize);
-
+
/* copy the text string */
- if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
- (MENU_ITEM_TYPE(mi.fType) == MF_STRING) && mi.dwTypeData)
+ if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
+ (MENU_ITEM_TYPE(mi.fType) == MF_STRING) &&
+ mi.dwTypeData != NULL)
{
- if(lpmii->cch > 0)
- {
- if(!RtlCreateUnicodeString(&MenuText, (PWSTR)lpmii->dwTypeData))
- {
- SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
- return FALSE;
- }
- mi.dwTypeData = (LPWSTR)&MenuText;
- mi.cch = MenuText.Length / sizeof(WCHAR);
- CleanHeap = TRUE;
- }
+ RtlInitUnicodeString(&MenuText, (PWSTR)lpmii->dwTypeData);
+ mi.dwTypeData = MenuText.Buffer;
+ mi.cch = MenuText.Length / sizeof(WCHAR);
};
-
+
res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
-
- if(CleanHeap) RtlFreeHeap (hHeap, 0, mi.dwTypeData);
}
return res;
}
mii.dwTypeData = (LPWSTR)lpNewItem;
mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
}
-
+
if(uFlags & MF_RIGHTJUSTIFY)
{
mii.fType |= MFT_RIGHTJUSTIFY;
{
mii.fState |= MFS_GRAYED;
}
-
+
if(uFlags & MF_POPUP)
{
mii.fType |= MF_POPUP;
mii.fMask |= MIIM_ID;
mii.wID = (UINT)uIDNewItem;
}
- return InsertMenuItemW(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+ return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
+ MENUITEMINFOA mii;
+ memset( &mii, 0, sizeof(mii) );
+ mii.cbSize = sizeof(MENUITEMINFOA);
+ mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+ mii.fType = 0;
+ mii.fState = MFS_ENABLED;
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(!GetMenuItemInfoA( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii)) return FALSE;
+
+ if(uFlags & MF_BITMAP)
+ {
+ mii.fType |= MFT_BITMAP;
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = (HBITMAP) lpNewItem;
+ }
+ else if(uFlags & MF_OWNERDRAW)
+ {
+ mii.fType |= MFT_OWNERDRAW;
+ mii.fMask |= MIIM_DATA;
+ mii.dwItemData = (DWORD) lpNewItem;
+ }
+ else /* Default action MF_STRING. */
+ {
+ if(mii.dwTypeData != NULL)
+ {
+ HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+ }
+ /* Item beginning with a backspace is a help item */
+ if (*lpNewItem == '\b')
+ {
+ mii.fType |= MF_HELP;
+ lpNewItem++;
+ }
+ mii.fMask |= MIIM_TYPE;
+ mii.dwTypeData = (LPSTR)lpNewItem;
+ mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
+ }
+
+ if(uFlags & MF_RIGHTJUSTIFY)
+ {
+ mii.fType |= MFT_RIGHTJUSTIFY;
+ }
+ if(uFlags & MF_MENUBREAK)
+ {
+ mii.fType |= MFT_MENUBREAK;
+ }
+ if(uFlags & MF_MENUBARBREAK)
+ {
+ mii.fType |= MFT_MENUBARBREAK;
+ }
+ if(uFlags & MF_DISABLED)
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+ if(uFlags & MF_GRAYED)
+ {
+ mii.fState |= MFS_GRAYED;
+ }
+
+ if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+ NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
+
+ if(uFlags & MF_POPUP)
+ {
+ mii.fType |= MF_POPUP;
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)uIDNewItem;
+ }
+ else
+ {
+ mii.fMask |= MIIM_ID;
+ mii.wID = (UINT)uIDNewItem;
+ }
+
+ return SetMenuItemInfoA( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
+ MENUITEMINFOW mii;
+ memset ( &mii, 0, sizeof(mii) );
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(!NtUserMenuItemInfo( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ (PROSMENUITEMINFO) &mii,
+ FALSE)) return FALSE;
+
+ if(uFlags & MF_BITMAP)
+ {
+ mii.fType |= MFT_BITMAP;
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = (HBITMAP) lpNewItem;
+ }
+ else if(uFlags & MF_OWNERDRAW)
+ {
+ mii.fType |= MFT_OWNERDRAW;
+ mii.fMask |= MIIM_DATA;
+ mii.dwItemData = (DWORD) lpNewItem;
+ }
+ else
+ {
+ /*if(mii.dwTypeData != NULL)
+ {
+ HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+ }*/
+ if (*lpNewItem == '\b')
+ {
+ mii.fType |= MF_HELP;
+ lpNewItem++;
+ }
+ mii.fMask |= MIIM_TYPE;
+ mii.dwTypeData = (LPWSTR)lpNewItem;
+ mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
+ }
+
+ if(uFlags & MF_RIGHTJUSTIFY)
+ {
+ mii.fType |= MFT_RIGHTJUSTIFY;
+ }
+ if(uFlags & MF_MENUBREAK)
+ {
+ mii.fType |= MFT_MENUBREAK;
+ }
+ if(uFlags & MF_MENUBARBREAK)
+ {
+ mii.fType |= MFT_MENUBARBREAK;
+ }
+ if(uFlags & MF_DISABLED)
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+ if(uFlags & MF_GRAYED)
+ {
+ mii.fState |= MFS_GRAYED;
+ }
+
+ if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+ NtUserDestroyMenu( mii.hSubMenu );
+
+ if(uFlags & MF_POPUP)
+ {
+ mii.fType |= MF_POPUP;
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)uIDNewItem;
+ }
+ else
+ {
+ mii.fMask |= MIIM_ID;
+ mii.wID = (UINT)uIDNewItem;
+ }
+
+ return SetMenuItemInfoW( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii);
}
BOOL res = FALSE;
if(lpcmi->cbSize != sizeof(MENUINFO))
return res;
-
+
memcpy(&mi, lpcmi, sizeof(MENUINFO));
return NtUserMenuInfo(hmenu, &mi, TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
HBITMAP hBitmapUnchecked,
HBITMAP hBitmapChecked)
{
- UNIMPLEMENTED;
- return FALSE;
+ ROSMENUITEMINFO uItem;
+
+ if(!(NtUserMenuItemInfo(hMenu, uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags), &uItem, FALSE))) return FALSE;
+
+ if (!hBitmapChecked && !hBitmapUnchecked)
+ {
+ uItem.fState &= ~MF_USECHECKBITMAPS;
+ }
+ else /* Install new bitmaps */
+ {
+ uItem.hbmpChecked = hBitmapChecked;
+ uItem.hbmpUnchecked = hBitmapUnchecked;
+ uItem.fState |= MF_USECHECKBITMAPS;
+ }
+ return NtUserMenuItemInfo(hMenu, uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags), &uItem, TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
HMENU hMenu,
UINT uItem,
BOOL fByPosition,
- LPMENUITEMINFOA lpmii)
+ LPCMENUITEMINFOA lpmii)
{
- UNIMPLEMENTED;
- return FALSE;
+ MENUITEMINFOW MenuItemInfoW;
+ UNICODE_STRING UnicodeString;
+ ULONG Result;
+
+ RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
+
+ if ((MenuItemInfoW.fMask & (MIIM_TYPE | MIIM_STRING)) &&
+ (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING) &&
+ MenuItemInfoW.dwTypeData != NULL)
+ {
+ RtlCreateUnicodeStringFromAsciiz(&UnicodeString,
+ (LPSTR)MenuItemInfoW.dwTypeData);
+ MenuItemInfoW.dwTypeData = UnicodeString.Buffer;
+ MenuItemInfoW.cch = UnicodeString.Length / sizeof(WCHAR);
+ }
+ else
+ {
+ UnicodeString.Buffer = NULL;
+ }
+
+ Result = NtUserMenuItemInfo(hMenu, uItem, fByPosition,
+ (PROSMENUITEMINFO)&MenuItemInfoW, TRUE);
+
+ if (UnicodeString.Buffer != NULL)
+ {
+ RtlFreeUnicodeString(&UnicodeString);
+ }
+
+ return Result;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
HMENU hMenu,
UINT uItem,
BOOL fByPosition,
- LPMENUITEMINFOW lpmii)
+ LPCMENUITEMINFOW lpmii)
{
- UNIMPLEMENTED;
- return FALSE;
+ MENUITEMINFOW MenuItemInfoW;
+
+ RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
+ if (0 != (MenuItemInfoW.fMask & MIIM_STRING))
+ {
+ MenuItemInfoW.cch = wcslen(MenuItemInfoW.dwTypeData);
+ }
+
+ return NtUserMenuItemInfo(hMenu, uItem, fByPosition,
+ (PROSMENUITEMINFO)&MenuItemInfoW, TRUE);
}
/*
BOOL
STDCALL
SetSystemMenu (
- HWND hwnd,
+ HWND hwnd,
HMENU hMenu)
{
if(!hwnd)
ROSMENUINFO mi;
mi.cbSize = sizeof(ROSMENUINFO);
mi.fMask = MIM_HELPID;
-
+
if(NtUserMenuInfo(hmenu, &mi, FALSE))
{
return mi.dwContextHelpID;
{
case MF_APPEND :
return AppendMenuW(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-
+
case MF_DELETE :
return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);
{
case MF_APPEND :
return AppendMenuA(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-
+
case MF_DELETE :
return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);