From bf575f1f8f63b305121a98c130559cc903874505 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 19 Jul 2005 11:51:31 +0000 Subject: [PATCH] Initialize the various menu global variables on demand instead of at startup time. --- dlls/user/controls.h | 2 - dlls/user/menu.c | 214 +++++++++++++++++++----------------------- dlls/user/user_main.c | 3 - dlls/user/win.c | 4 +- 4 files changed, 101 insertions(+), 122 deletions(-) diff --git a/dlls/user/controls.h b/dlls/user/controls.h index 76271fb37d2..352e8326ee4 100644 --- a/dlls/user/controls.h +++ b/dlls/user/controls.h @@ -56,9 +56,7 @@ extern BOOL DESKTOP_SetPattern( LPCWSTR pattern ); extern HWND ICONTITLE_Create( HWND hwnd ); /* menu controls */ -extern BOOL MENU_Init(void); extern HWND MENU_IsMenuActive(void); -extern HMENU MENU_GetSysMenu(HWND hWndOwner, HMENU hSysPopup); extern UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth, INT orgX, INT orgY ); extern BOOL MENU_SetMenu(HWND, HMENU); diff --git a/dlls/user/menu.c b/dlls/user/menu.c index 913fbbbaffe..2a8b51cb76a 100644 --- a/dlls/user/menu.c +++ b/dlls/user/menu.c @@ -162,19 +162,9 @@ typedef struct #define WIN_ALLOWED_MENU(style) ((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) - /* Dimension of the menu bitmaps */ -static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0; - -static HBITMAP hStdMnArrow = 0; -static HBITMAP hBmpSysMenu = 0; - -static HFONT hMenuFont = 0; -static HFONT hMenuFontBold = 0; static SIZE menucharsize; static UINT ODitemheight; /* default owner drawn item height */ -static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */ - /* Use global popup window because there's no way 2 menus can * be tracked at the same time. */ static HWND top_popup; @@ -329,6 +319,52 @@ static HMENU get_win_sys_menu( HWND hwnd ) return ret; } +/*********************************************************************** + * get_menu_font + */ +static HFONT get_menu_font( BOOL bold ) +{ + static HFONT hMenuFont, hMenuFontBold; + + HFONT ret = bold ? hMenuFontBold : hMenuFont; + + if (!ret) + { + NONCLIENTMETRICSW ncm; + HFONT prev; + + ncm.cbSize = sizeof(NONCLIENTMETRICSW); + SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &ncm, 0); + + if (bold) + { + ncm.lfMenuFont.lfWeight += 300; + if (ncm.lfMenuFont.lfWeight > 1000) ncm.lfMenuFont.lfWeight = 1000; + } + if (!(ret = CreateFontIndirectW( &ncm.lfMenuFont ))) return 0; + prev = InterlockedCompareExchangePointer( (void **)(bold ? &hMenuFontBold : &hMenuFont), + ret, NULL ); + if (prev) + { + /* another thread beat us to it */ + DeleteObject( ret ); + ret = prev; + } + } + return ret; +} + +/*********************************************************************** + * get_arrow_bitmap + */ +static HBITMAP get_arrow_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)); + return arrow_bitmap; +} + /*********************************************************************** * MENU_CopySysPopup * @@ -374,9 +410,8 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) menu->hWnd = WIN_GetFullHandle( hWnd ); TRACE("hWnd %p (hMenu %p)\n", menu->hWnd, hMenu); - if (hPopupMenu == (HMENU)(-1)) + if (!hPopupMenu) hPopupMenu = MENU_CopySysPopup(); - else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup; if (hPopupMenu) { @@ -400,49 +435,6 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) } -/*********************************************************************** - * MENU_Init - * - * Menus initialisation. - */ -BOOL MENU_Init(void) -{ - NONCLIENTMETRICSW ncm; - - /* Load menu bitmaps */ - hStdMnArrow = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)); - /* Load system buttons bitmaps */ - hBmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)); - - if (hStdMnArrow) - { - BITMAP bm; - GetObjectW( hStdMnArrow, sizeof(bm), &bm ); - arrow_bitmap_width = bm.bmWidth; - arrow_bitmap_height = bm.bmHeight; - } else - return FALSE; - - if (!(MENU_DefSysPopup = MENU_CopySysPopup())) - return FALSE; - - ncm.cbSize = sizeof(NONCLIENTMETRICSW); - if (!(SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &ncm, 0))) - return FALSE; - - if (!(hMenuFont = CreateFontIndirectW( &ncm.lfMenuFont ))) - return FALSE; - - ncm.lfMenuFont.lfWeight += 300; - if ( ncm.lfMenuFont.lfWeight > 1000) - ncm.lfMenuFont.lfWeight = 1000; - - if (!(hMenuFontBold = CreateFontIndirectW( &ncm.lfMenuFont ))) - return FALSE; - - return TRUE; -} - /*********************************************************************** * MENU_InitSysMenuPopup * @@ -783,6 +775,9 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO } else { + static HBITMAP hBmpSysMenu; + + if (!hBmpSysMenu) hBmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)); bmp = hBmpSysMenu; if (!GetObjectW( bmp, sizeof(bm), &bm )) return; /* only use right half of the bitmap */ @@ -848,11 +843,16 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, { WCHAR *p; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); + UINT arrow_bitmap_width; + BITMAP bm; TRACE("dc=%p owner=%p (%d,%d)\n", hdc, hwndOwner, orgX, orgY); debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem, (menuBar ? " (MenuBar)" : "")); + GetObjectW( get_arrow_bitmap(), sizeof(bm), &bm ); + arrow_bitmap_width = bm.bmWidth; + SetRect( &lpitem->rect, orgX, orgY, orgX, orgY ); if (lpitem->fType & MF_OWNERDRAW) @@ -860,9 +860,7 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, MEASUREITEMSTRUCT mis; /* not done in Menu_Init: GetDialogBaseUnits() breaks there */ if( !menucharsize.cx ) { - HFONT hOldFont = SelectObject( hdc, hMenuFont ); menucharsize.cx = GdiGetCharDimensions( hdc, NULL, &menucharsize.cy ); - SelectObject( hdc, hOldFont ); /* Win95/98/ME will use menucharsize.cy here. Testing is possible * but it is unlikely an application will depend on that */ ODitemheight = HIWORD( GetDialogBaseUnits()); @@ -998,7 +996,7 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner ) if (lppop->nItems == 0) return; hdc = GetDC( 0 ); - SelectObject( hdc, hMenuFont); + SelectObject( hdc, get_menu_font(FALSE)); start = 0; maxX = 2 + 1; @@ -1299,6 +1297,12 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, INT y = rect.top + rect.bottom; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); + UINT arrow_bitmap_width, arrow_bitmap_height; + BITMAP bmp; + + GetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp ); + arrow_bitmap_width = bmp.bmWidth; + arrow_bitmap_height = bmp.bmHeight; if (!(lpitem->fType & MF_OWNERDRAW)) { @@ -1383,7 +1387,7 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, HDC hdcMem = CreateCompatibleDC( hdc ); HBITMAP hOrigBitmap; - hOrigBitmap = SelectObject( hdcMem, hStdMnArrow ); + hOrigBitmap = SelectObject( hdcMem, get_arrow_bitmap() ); BitBlt( hdc, rect.right - arrow_bitmap_width - 1, (y - arrow_bitmap_height) / 2, arrow_bitmap_width, arrow_bitmap_height, @@ -1418,7 +1422,7 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, if ( lpitem->fState & MFS_DEFAULT ) { - hfontOld = SelectObject( hdc, hMenuFontBold); + hfontOld = SelectObject( hdc, get_menu_font(TRUE) ); } if (menuBar) @@ -1493,7 +1497,7 @@ static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu ) GetClientRect( hwnd, &rect ); if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) )) - && (SelectObject( hdc, hMenuFont))) + && (SelectObject( hdc, get_menu_font(FALSE)))) { HPEN hPrevPen; @@ -1552,7 +1556,7 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, if (suppress_draw) { - hfontOld = SelectObject( hDC, hMenuFont); + hfontOld = SelectObject( hDC, get_menu_font(FALSE)); if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd); @@ -1652,7 +1656,7 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW); if (!top_popup) top_popup = lppop->hWnd; - SelectObject( hdc, hMenuFont); + SelectObject( hdc, get_menu_font(FALSE)); /* Clear previous highlighted item */ if (lppop->FocusedItem != NO_SELECTED_ITEM) @@ -2071,7 +2075,7 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd ); else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW); - SelectObject( hdc, hMenuFont); + SelectObject( hdc, get_menu_font(FALSE)); item->fState |= MF_HILITE; MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE ); @@ -3195,7 +3199,7 @@ UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth, if (!(lppop = MENU_GetMenu( GetMenu(hwnd) ))) return 0; hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW ); - SelectObject( hdc, hMenuFont); + SelectObject( hdc, get_menu_font(FALSE)); SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU)); MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd ); ReleaseDC( hwnd, hdc ); @@ -3663,39 +3667,35 @@ HMENU WINAPI CreateMenu(void) */ BOOL WINAPI DestroyMenu( HMENU hMenu ) { + LPPOPUPMENU lppop = MENU_GetMenu(hMenu); + TRACE("(%p)\n", hMenu); - /* Silently ignore attempts to destroy default system popup */ - if (hMenu && hMenu != MENU_DefSysPopup) + if (!lppop) return FALSE; + + lppop->wMagic = 0; /* Mark it as destroyed */ + + /* DestroyMenu should not destroy system menu popup owner */ + if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd) { - LPPOPUPMENU lppop = MENU_GetMenu(hMenu); - - if (!lppop) return FALSE; - - lppop->wMagic = 0; /* Mark it as destroyed */ - - /* DestroyMenu should not destroy system menu popup owner */ - if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd) - { - DestroyWindow( lppop->hWnd ); - lppop->hWnd = 0; - } - - if (lppop->items) /* recursively destroy submenus */ - { - int i; - MENUITEM *item = lppop->items; - for (i = lppop->nItems; i > 0; i--, item++) - { - if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu); - MENU_FreeItemData( item ); - } - HeapFree( GetProcessHeap(), 0, lppop->items ); - } - USER_HEAP_FREE( hMenu ); + DestroyWindow( lppop->hWnd ); + lppop->hWnd = 0; } - return (hMenu != MENU_DefSysPopup); + + if (lppop->items) /* recursively destroy submenus */ + { + int i; + MENUITEM *item = lppop->items; + for (i = lppop->nItems; i > 0; i--, item++) + { + if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu); + MENU_FreeItemData( item ); + } + HeapFree( GetProcessHeap(), 0, lppop->items ); + } + USER_HEAP_FREE( hMenu ); + return TRUE; } @@ -3714,32 +3714,14 @@ HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert ) } else if (wndPtr) { - if( wndPtr->hSysMenu ) + if (wndPtr->hSysMenu && bRevert) { - if( bRevert ) - { - DestroyMenu(wndPtr->hSysMenu); - wndPtr->hSysMenu = 0; - } - else - { - POPUPMENU *menu = MENU_GetMenu( wndPtr->hSysMenu ); - if( menu ) - { - if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup ) - menu->items[0].hSubMenu = MENU_CopySysPopup(); - } - else - { - WARN("Current sys-menu (%p) of wnd %p is broken\n", - wndPtr->hSysMenu, hWnd); - wndPtr->hSysMenu = 0; - } - } + DestroyMenu(wndPtr->hSysMenu); + wndPtr->hSysMenu = 0; } if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) ) - wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) ); + wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, 0 ); if( wndPtr->hSysMenu ) { @@ -3898,7 +3880,7 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFO hMenu = GetMenu(hwnd); if (!hFont) - hFont = hMenuFont; + hFont = get_menu_font(FALSE); lppop = MENU_GetMenu( hMenu ); if (lppop == NULL || lprect == NULL) diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c index 3c170453ca3..9e9cb4232f9 100644 --- a/dlls/user/user_main.c +++ b/dlls/user/user_main.c @@ -179,9 +179,6 @@ static BOOL process_attach(void) /* Initialize built-in window classes */ CLASS_RegisterBuiltinClasses(); - /* Initialize menus */ - if (!MENU_Init()) return FALSE; - /* Initialize message spying */ if (!SPY_Init()) return FALSE; diff --git a/dlls/user/win.c b/dlls/user/win.c index 92dbb966beb..c2284ef2f01 100644 --- a/dlls/user/win.c +++ b/dlls/user/win.c @@ -976,7 +976,9 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->userdata = 0; wndPtr->hIcon = 0; wndPtr->hIconSmall = 0; - wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, (HMENU)-1 ) : 0; + wndPtr->hSysMenu = 0; + + if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 ); /* * Correct the window styles.