diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index cf88cf2ea88..4b301268164 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -89,7 +89,7 @@ DWORD STDCALL NtUserBuildMenuItemList( HMENU hMenu, - LPCMENUITEMINFOW* lpmiil, + PVOID Buffer, ULONG nBufSize, DWORD Reserved); diff --git a/reactos/lib/user32/windows/menu.c b/reactos/lib/user32/windows/menu.c index 8693ba8f1d1..9ef4f8d98c0 100644 --- a/reactos/lib/user32/windows/menu.c +++ b/reactos/lib/user32/windows/menu.c @@ -16,7 +16,7 @@ * 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.30 2003/08/27 22:58:12 weiden Exp $ +/* $Id: menu.c,v 1.31 2003/08/28 10:39:44 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/menu.c @@ -311,17 +311,165 @@ MenuGetMenuBarHeight(HWND hWnd, ULONG MenuBarWidth, LONG OrgX, LONG OrgY) return(GetSystemMetrics(SM_CYMENU)); } +static BOOL +MeasureMenuItem(HWND hWnd, HMENU mnu, HDC hDC, MENUITEMINFOW *mii, RECT *mir, LPWSTR str) +{ + BOOL res = FALSE; + MEASUREITEMSTRUCT mis; + SIZE sz; + + if(mii->fType & MFT_OWNERDRAW) + { + /* send WM_MEASUREITEM message to window */ + mis.CtlType = ODT_MENU; + mis.CtlID = 0; + mis.itemID = mii->wID; + mis.itemWidth = 0; + mis.itemHeight = 0; + mis.itemData = mii->dwItemData; + res = (BOOL)SendMessageW(hWnd, WM_MEASUREITEM, 0, (LPARAM)&mis); + if(res) + { + mir->right = mir->left + mis.itemWidth; + mir->bottom = mir->top + mis.itemHeight; + } + else + { + /* FIXME calculate size internally assuming the menu item is empty */ + mir->right = mir->left + 1; + mir->bottom = mir->top + 1; + } + return res; + } + else + { + GetTextExtentPoint32W(hDC, str, mii->cch, &sz); + /* FIXME calculate the size of the menu item */ + mir->right = mir->left + sz.cx + 6; + mir->bottom = mir->top + max(sz.cy, GetSystemMetrics(SM_CYMENU)); + return TRUE; + } +} + +static BOOL +DrawMenuItem(HWND hWnd, HMENU mnu, HDC hDC, MENUITEMINFOW *mii, RECT *mir, LPWSTR str) +{ + BOOL res = FALSE; + DRAWITEMSTRUCT dis; + + if(mii->fType & MFT_OWNERDRAW) + { + /* send WM_DRAWITEM message to window */ + dis.CtlType = ODT_MENU; + dis.CtlID = 0; + dis.itemID = mii->wID; + dis.itemAction = ODA_DRAWENTIRE; /* FIXME */ + dis.itemState = 0; /* FIXME */ + dis.hwndItem = (HWND)mnu; + dis.hDC = hDC; + RtlCopyMemory(&dis.rcItem, mir, sizeof(RECT)); + dis.itemData = mii->dwItemData; + res = (BOOL)SendMessageW(hWnd, WM_DRAWITEM, 0, (LPARAM)&dis); + return res; + } + else + { + /* FIXME draw the menu item */ + SetTextColor(hDC, COLOR_MENUTEXT); + DrawTextW(hDC, str, -1, mir, DT_SINGLELINE | DT_VCENTER | DT_CENTER); + } + return res; +} + UINT MenuDrawMenuBar(HDC hDC, LPRECT Rect, HWND hWnd, BOOL Draw) { - /* FIXME cache menu bar items using NtUserDrawMenuBarTemp() */ + UINT height; + HMENU mnu; + HANDLE hHeap; + PVOID Buf, hBuf; + DWORD BufSize, Items, Items2; + MENUITEMINFOW *mii; + RECT *omir, *mir = NULL; + LPWSTR str; + + height = Rect->bottom - Rect->top; + mnu = GetMenu(hWnd); /* Fixme - pass menu handle as parameter */ + /* get menu item list size */ + BufSize = NtUserBuildMenuItemList(mnu, (VOID*)1, 0, 0); + if(BufSize) + { + /* FIXME cache menu bar items using NtUserDrawMenuBarTemp() + instead of allocating and deallocating memory everytime */ - /* FIXME select menu font first */ - SetTextColor(hDC, COLOR_MENUTEXT); - DrawTextW(hDC, L"FIXME: Draw Menubar", -1, Rect, DT_SINGLELINE | DT_VCENTER); + hHeap = GetProcessHeap(); + hBuf = HeapAlloc(hHeap, 0, BufSize); + if(!hBuf) + return(Rect->bottom - Rect->top); + Buf = hBuf; + /* copy menu items into buffer */ + Items = Items2 = NtUserBuildMenuItemList(mnu, Buf, BufSize, 0); + + /* calculate menu item rectangles */ + while(Items > 0) + { + omir = mir; + mii = (LPMENUITEMINFOW)Buf; + Buf += sizeof(MENUITEMINFOW); + mir = (LPRECT)Buf; + Buf += sizeof(RECT); + if(mii->cch) + { + str = (LPWSTR)Buf; + Buf += (mii->cch + 1) * sizeof(WCHAR); + } + else + str = NULL; + if(omir) + { + mir->left = omir->right + 1; + mir->top = omir->top; + mir->right += mir->left; + mir->bottom += mir->top; + } + else + { + mir->left = Rect->left; + mir->top = Rect->top; + } + MeasureMenuItem(hWnd, mnu, hDC, mii, mir, str); + + height = max(height, mir->top + mir->bottom); + /* DbgPrint("Measure menu item %ws: (%d, %d, %d, %d)\n", str, mir->left, mir->top, mir->right, mir->bottom); */ + Items--; + } + height = max(height, GetSystemMetrics(SM_CYMENU)); + + Buf = hBuf; + /* draw menu items */ + while (Items2 > 0) + { + mii = (LPMENUITEMINFOW)Buf; + Buf += sizeof(MENUITEMINFOW); + mir = (LPRECT)Buf; + Buf += sizeof(RECT); + if(mii->cch) + { + str = (LPWSTR)Buf; + Buf += (mii->cch + 1) * sizeof(WCHAR); + } + else + str = NULL; + /* DbgPrint("Draw menu item %ws at (%d, %d, %d, %d)\n", str, mir->left, mir->top, mir->right, mir->bottom); */ + DrawMenuItem(hWnd, mnu, hDC, mii, mir, str); + Items2--; + } + + HeapFree(hHeap, 0, hBuf); + } - return(Rect->bottom - Rect->top); + return height; } diff --git a/reactos/subsys/win32k/include/menu.h b/reactos/subsys/win32k/include/menu.h index 9dcf6a93d6e..a0c39beef15 100644 --- a/reactos/subsys/win32k/include/menu.h +++ b/reactos/subsys/win32k/include/menu.h @@ -26,6 +26,7 @@ typedef struct _MENU_ITEM ULONG_PTR dwItemData; UNICODE_STRING Text; HBITMAP hbmpItem; + RECT Rect; } MENU_ITEM, *PMENU_ITEM; typedef struct _MENU_OBJECT @@ -116,7 +117,7 @@ DWORD STDCALL NtUserBuildMenuItemList( HMENU hMenu, - LPCMENUITEMINFOW* lpmiil, + PVOID Buffer, ULONG nBufSize, DWORD Reserved); diff --git a/reactos/subsys/win32k/ntuser/menu.c b/reactos/subsys/win32k/ntuser/menu.c index eca19162e2c..d40beb213d6 100644 --- a/reactos/subsys/win32k/ntuser/menu.c +++ b/reactos/subsys/win32k/ntuser/menu.c @@ -16,7 +16,7 @@ * 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.28 2003/08/27 22:58:12 weiden Exp $ +/* $Id: menu.c,v 1.29 2003/08/28 10:39:44 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -778,22 +778,67 @@ IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable) return res; } -/* + DWORD FASTCALL -IntBuildMenuItemList(PMENU_OBJECT MenuObject, MENUITEMINFOW *lpmiil, ULONG nMax) +IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) { - DWORD Index = 0; + DWORD res = 0; + UINT sz; + MENUITEMINFOW mii; + PVOID Buf; PMENU_ITEM CurItem = MenuObject->MenuItemList; - while(CurItem && (nMax > 0)) + if(nMax) { - memcpy(&lpmiil[Index], &CurItem->MenuItem, sizeof(MENUITEMINFOW)); - CurItem = CurItem->Next; - Index++; - nMax--; + sz = sizeof(MENUITEMINFOW) + sizeof(RECT); + Buf = Buffer; + mii.cbSize = sz; + mii.fMask = 0; + while(CurItem && (nMax >= sz)) + { + mii.cch = CurItem->Text.Length / sizeof(WCHAR); + mii.dwItemData = CurItem->dwItemData; + if(CurItem->Text.Length) + mii.dwTypeData = NULL; + else + mii.dwTypeData = (LPWSTR)CurItem->Text.Buffer; + mii.fState = CurItem->fState; + mii.fType = CurItem->fType; + mii.hbmpChecked = CurItem->hbmpChecked; + mii.hbmpItem = CurItem->hbmpItem; + mii.hbmpUnchecked = CurItem->hbmpUnchecked; + mii.hSubMenu = CurItem->hSubMenu; + RtlCopyMemory(Buf, &mii, sizeof(MENUITEMINFOW)); + Buf += sizeof(MENUITEMINFOW); + RtlCopyMemory(Buf, &CurItem->Rect, sizeof(RECT)); + Buf += sizeof(RECT); + nMax -= sz; + + if(CurItem->Text.Length && (nMax >= CurItem->Text.Length + sizeof(WCHAR))) + { + /* copy string */ + RtlCopyMemory(Buf, (LPWSTR)CurItem->Text.Buffer, CurItem->Text.Length); + Buf += CurItem->Text.Length + sizeof(WCHAR); + nMax -= CurItem->Text.Length + sizeof(WCHAR); + } + else + break; + + CurItem = CurItem->Next; + res++; + } } - return Index; + else + { + while(CurItem) + { + res += sizeof(MENUITEMINFOW) + sizeof(RECT); + res += CurItem->Text.Length + sizeof(WCHAR); + CurItem = CurItem->Next; + } + } + return res; } -*/ + DWORD FASTCALL IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck) @@ -1009,7 +1054,7 @@ DWORD STDCALL NtUserBuildMenuItemList( HMENU hMenu, - LPCMENUITEMINFOW* lpmiil, + VOID* Buffer, ULONG nBufSize, DWORD Reserved) { @@ -1021,14 +1066,11 @@ NtUserBuildMenuItemList( return (DWORD)-1; } - if(lpmiil) + if(Buffer) { - /* FIXME need to pass the menu strings to user32 somehow.... - ExAcquireFastMutexUnsafe(&MenuObject->MenuItemsLock); - res = IntBuildMenuItemList(MenuObject, lpmiil, nBufSize / sizeof(LPCMENUITEMINFO)); + res = IntBuildMenuItemList(MenuObject, Buffer, nBufSize); ExReleaseFastMutexUnsafe(&MenuObject->MenuItemsLock); - */ } else {