From a7eca7b2d58519329ab76a9a6f5fd0bcea914b9d Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 12 Jun 2009 16:20:19 +0000 Subject: [PATCH] win32: draw popup menu in Vista style on vista/w7 git-svn-id: trunk@20606 - --- lcl/interfaces/win32/win32callback.inc | 3 +- lcl/interfaces/win32/win32themes.pas | 2 +- lcl/interfaces/win32/win32wsmenus.pp | 406 +++++++++++++++++++++---- 3 files changed, 345 insertions(+), 66 deletions(-) diff --git a/lcl/interfaces/win32/win32callback.inc b/lcl/interfaces/win32/win32callback.inc index 5a1c5b4f24..1450bdb2ea 100644 --- a/lcl/interfaces/win32/win32callback.inc +++ b/lcl/interfaces/win32/win32callback.inc @@ -1540,7 +1540,8 @@ begin begin DrawMenuItem(TMenuItem(menuItem), PDrawItemStruct(LParam)^._hDC, PDrawItemStruct(LParam)^.rcItem, - PDrawItemStruct(LParam)^.itemState and ODS_SELECTED <> 0); + PDrawItemStruct(LParam)^.itemState and ODS_SELECTED <> 0, + PDrawItemStruct(LParam)^.itemState and ODS_NOACCEL <> 0); end end; diff --git a/lcl/interfaces/win32/win32themes.pas b/lcl/interfaces/win32/win32themes.pas index 349c6150d6..03f5201805 100644 --- a/lcl/interfaces/win32/win32themes.pas +++ b/lcl/interfaces/win32/win32themes.pas @@ -23,7 +23,6 @@ type FThemeData: TThemeData; // Holds a list of theme data handles. protected function GetTheme(Element: TThemedElement): HTHEME; - property Theme[Element: TThemedElement]: HTHEME read GetTheme; function InitThemes: Boolean; override; procedure UnloadThemeData; override; function UseThemes: Boolean; override; @@ -58,6 +57,7 @@ type function ContentRect(DC: HDC; Details: TThemedElementDetails; BoundingRect: TRect): TRect; override; function HasTransparentParts(Details: TThemedElementDetails): Boolean; override; procedure PaintBorder(Control: TObject; EraseLRCorner: Boolean); override; + property Theme[Element: TThemedElement]: HTHEME read GetTheme; end; implementation diff --git a/lcl/interfaces/win32/win32wsmenus.pp b/lcl/interfaces/win32/win32wsmenus.pp index bfe482dc7e..6b0196eef4 100644 --- a/lcl/interfaces/win32/win32wsmenus.pp +++ b/lcl/interfaces/win32/win32wsmenus.pp @@ -38,7 +38,7 @@ uses //////////////////////////////////////////////////// WSMenus, WSLCLClasses, WSProc, Windows, Controls, Classes, SysUtils, Win32Int, Win32Proc, Win32WSImgList, - InterfaceBase, LCLProc, Themes; + InterfaceBase, LCLProc, Themes, Win32UxTheme, TmSchema, Win32Themes; type @@ -79,10 +79,11 @@ type class procedure Popup(const APopupMenu: TPopupMenu; const X, Y: integer); override; end; - function MenuItemSize(aMenuItem: TMenuItem; aHDC: HDC): TSize; - procedure DrawMenuItem(const aMenuItem: TMenuItem; const aHDC: HDC; const aRect: Windows.RECT; const aSelected: boolean); + function MenuItemSize(AMenuItem: TMenuItem; AHDC: HDC): TSize; + procedure DrawMenuItem(const AMenuItem: TMenuItem; const AHDC: HDC; const ARect: Windows.RECT; const ASelected, ANoAccel: boolean); function FindMenuItemAccelerator(const ACharCode: char; const AMenuHandle: HMENU): integer; - + procedure DrawMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC; + const ImageRect: TRect; const ASelected: Boolean); implementation @@ -104,6 +105,24 @@ const MF_ENABLED ); + PopupItemStates: array[{ Enabled } Boolean, { Selected } Boolean] of TThemedMenu = + ( + (tmPopupItemDisabled, tmPopupItemDisabledHot), + (tmPopupItemNormal, tmPopupItemHot) + ); + + PopupCheckBgStates: array[{ Enabled } Boolean] of TThemedMenu = + ( + tmPopupCheckBackgroundDisabled, + tmPopupCheckBackgroundNormal + ); + + PopupCheckStates: array[{ Enabled } Boolean, { RadioItem } Boolean] of TThemedMenu = + ( + (tmPopupCheckMarkDisabled, tmPopupBulletDisabled), + (tmPopupCheckMarkNormal, tmPopupBulletNormal) + ); + var menuiteminfosize : DWORD = 0; @@ -111,6 +130,20 @@ type TCaptionFlags = (cfBold, cfUnderline); TCaptionFlagsSet = set of TCaptionFlags; + // metrics for vista drawing + TVistaMenuMetrics = record + ItemMargins: TMargins; + CheckSize: TSize; + CheckMargins: TMargins; + CheckBgMargins: TMargins; + GutterSize: TSize; + SubMenuSize: TSize; + TextSize: TSize; + TextMargins: TMargins; + ShortCustSize: TSize; + SeparatorSize: TSize; + end; + (* Returns index of the character in the menu item caption that is displayed as underlined and is therefore the hot key of the menu item. If the caption does not contain any underlined character, 0 is returned. @@ -164,34 +197,36 @@ begin else Result := MakeLResult(0, 0); end; -function GetMenuItemFont(const aFlags: TCaptionFlagsSet): HFONT; +function GetMenuItemFont(const AFlags: TCaptionFlagsSet): HFONT; var lf: LOGFONT; ncm: NONCLIENTMETRICS; begin - ncm.cbSize:= sizeof(ncm); + ncm.cbSize := sizeof(ncm); if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), @ncm, 0) then - lf:= ncm.lfMenuFont + lf := ncm.lfMenuFont else - GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), @lf); - if cfUnderline in aFlags then lf.lfUnderline := 1 - else lf.lfUnderline := 0; - if cfBold in aFlags then + GetObject(GetStockObject(DEFAULT_GUI_FONT), SizeOf(LOGFONT), @lf); + if cfUnderline in AFlags then + lf.lfUnderline := 1 + else + lf.lfUnderline := 0; + if cfBold in AFlags then begin - if lf.lfWeight<=400 then - lf.lfWeight:= lf.lfWeight + 300 + if lf.lfWeight <= 400 then + lf.lfWeight := lf.lfWeight + 300 else - lf.lfWeight:= lf.lfWeight + 100; + lf.lfWeight := lf.lfWeight + 100; end; Result := CreateFontIndirect(@lf); end; (* Get the menu item caption including shortcut *) -function CompleteMenuItemCaption(const aMenuItem: TMenuItem): string; +function CompleteMenuItemCaption(const AMenuItem: TMenuItem): string; begin - Result := aMenuItem.Caption; - if aMenuItem.shortCut <> scNone then - Result := Result + ShortCutToText(aMenuItem.shortCut); + Result := AMenuItem.Caption; + if AMenuItem.ShortCut <> scNone then + Result := Result + ' ' + ShortCutToText(AMenuItem.ShortCut); end; (* Get the maximum length of the given string in pixels *) @@ -206,7 +241,7 @@ var {$endif WindowsUnicodeSupport} begin FillChar(tmpRect, SizeOf(tmpRect), 0); - newFont := getMenuItemFont(aDecoration); + newFont := GetMenuItemFont(aDecoration); oldFont := SelectObject(aHDC, newFont); {$ifdef WindowsUnicodeSupport} if UnicodeEnabledOS then @@ -300,35 +335,262 @@ begin Result := (aMenuItemHeight - anElementHeight) div 2; end; -function MenuItemSize(aMenuItem: TMenuItem; aHDC: HDC): TSize; +function IsVistaMenu: Boolean; inline; +begin + Result := ThemeServices.ThemesAvailable and (WindowsVersion >= wvVista) and + (TWin32ThemeServices(ThemeServices).Theme[teMenu] <> 0); +end; + +function GetVistaMenuMetrics(const AMenuItem: TMenuItem; DC: HDC): TVistaMenuMetrics; +var + Theme: HTHEME; + TextRect: TRect; + W: WideString; + AFont, OldFont: HFONT; +begin + Theme := TWin32ThemeServices(ThemeServices).Theme[teMenu]; + GetThemeMargins(Theme, 0, MENU_POPUPITEM, 0, TMT_CONTENTMARGINS, nil, Result.ItemMargins); + GetThemePartSize(Theme, 0, MENU_POPUPCHECK, 0, nil, TS_TRUE, Result.CheckSize); + GetThemeMargins(Theme, 0, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, nil, Result.CheckMargins); + GetThemeMargins(Theme, 0, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, nil, Result.CheckBgMargins); + GetThemePartSize(Theme, 0, MENU_POPUPGUTTER, 0, nil, TS_TRUE, Result.GutterSize); + GetThemePartSize(Theme, 0, MENU_POPUPSUBMENU, 0, nil, TS_TRUE, Result.SubMenuSize); + + if AMenuItem.IsLine then + begin + GetThemePartSize(Theme, 0, MENU_POPUPSEPARATOR, 0, nil, TS_TRUE, Result.SeparatorSize); + FillChar(Result.TextMargins, SizeOf(Result.TextMargins), 0); + FillChar(Result.TextSize, SizeOf(Result.TextSize), 0); + end + else + begin + Result.TextMargins := Result.ItemMargins; + GetThemeInt(Theme, MENU_POPUPITEM, 0, TMT_BORDERSIZE, Result.TextMargins.cxRightWidth); + GetThemeInt(Theme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, Result.TextMargins.cxLeftWidth); + + if AMenuItem.Default then + begin + AFont := GetMenuItemFont([cfBold]); + OldFont := SelectObject(DC, AFont); + end + else + OldFont := 0; + + W := UTF8ToUTF16(CompleteMenuItemCaption(AMenuItem)); + GetThemeTextExtent(Theme, DC, MENU_POPUPITEM, 0, PWideChar(W), Length(W), + DT_SINGLELINE or DT_LEFT or DT_EXPANDTABS, nil, TextRect); + Result.TextSize.cx := TextRect.Right - TextRect.Left; + Result.TextSize.cy := TextRect.Bottom - TextRect.Top; + + if AMenuItem.ShortCut <> scNone then + begin; + W := UTF8ToUTF16(ShortCutToText(AMenuItem.ShortCut)); + GetThemeTextExtent(Theme, DC, MENU_POPUPITEM, 0, PWideChar(W), Length(W), + DT_SINGLELINE or DT_LEFT, nil, TextRect); + Result.ShortCustSize.cx := TextRect.Right - TextRect.Left; + Result.ShortCustSize.cy := TextRect.Bottom - TextRect.Top; + end; + if OldFont <> 0 then + DeleteObject(SelectObject(DC, OldFont)); + end; +end; + +function VistaPopupMenuItemSize(AMenuItem: TMenuItem; ADC: HDC): TSize; +var + Metrics: TVistaMenuMetrics; +begin + Metrics := GetVistaMenuMetrics(AMenuItem, ADC); + // count check + Result.cx := Metrics.CheckSize.cx + Metrics.CheckMargins.cxRightWidth + Metrics.CheckMargins.cxLeftWidth; + if AMenuItem.IsLine then + begin + Result.cx := Result.cx + Metrics.SeparatorSize.cx + Metrics.ItemMargins.cxLeftWidth + Metrics.ItemMargins.cxRightWidth; + Result.cy := Metrics.SeparatorSize.cy + Metrics.ItemMargins.cyTopHeight + Metrics.ItemMargins.cyBottomHeight; + end + else + begin + Result.cy := Metrics.CheckSize.cy + Metrics.CheckMargins.cyTopHeight + Metrics.CheckMargins.cyBottomHeight; + if AMenuItem.HasIcon then + begin + Result.cy := Max(Result.cy, AMenuItem.GetIconSize.y); + Result.cx := Max(Result.cx, AMenuItem.GetIconSize.x); + end; + end; + // count gutter + Result.cx := Result.cx + (Metrics.CheckBgMargins.cxRightWidth - Metrics.CheckMargins.cxRightWidth) + + Metrics.GutterSize.cx; + // count text + Result.cx := Result.cx + Metrics.TextSize.cx; + Result.cx := Result.cx + Metrics.TextMargins.cxLeftWidth + Metrics.TextMargins.cxRightWidth; +end; + +procedure DrawVistaPopupMenu(const AMenuItem: TMenuItem; const AHDC: HDC; const ARect: TRect; const ASelected, ANoAccel: boolean); +var + Details, Tmp: TThemedElementDetails; + Metrics: TVistaMenuMetrics; + CheckRect, GutterRect, TextRect, SeparatorRect, ImageRect: TRect; + IconSize: TPoint; + TextFlags: DWord; + AFont, OldFont: HFONT; + IsRightToLeft: Boolean; +begin + Metrics := GetVistaMenuMetrics(AMenuItem, AHDC); + // draw backgound + Details := ThemeServices.GetElementDetails(PopupItemStates[AMenuItem.Enabled, ASelected]); + if ThemeServices.HasTransparentParts(Details) then + begin + Tmp := ThemeServices.GetElementDetails(tmPopupBackground); + ThemeServices.DrawElement(AHDC, Tmp, ARect, nil); + end; + IsRightToLeft := AMenuItem.GetIsRightToLeft; + // calc check/image rect + CheckRect := ARect; + if IsRightToLeft then + CheckRect.left := CheckRect.Right - Metrics.CheckSize.cx - Metrics.CheckMargins.cxRightWidth - Metrics.CheckMargins.cxLeftWidth + else + CheckRect.Right := CheckRect.Left + Metrics.CheckSize.cx + Metrics.CheckMargins.cxRightWidth + Metrics.CheckMargins.cxLeftWidth; + CheckRect.Bottom := CheckRect.Top + Metrics.CheckSize.cy + Metrics.CheckMargins.cyTopHeight + Metrics.CheckMargins.cyBottomHeight; + // draw gutter + GutterRect := CheckRect; + if IsRightToLeft then + begin + GutterRect.Right := GutterRect.Left - Metrics.CheckBgMargins.cxRightWidth + Metrics.CheckMargins.cxRightWidth; + GutterRect.Left := GutterRect.Right - Metrics.GutterSize.cx; + end + else + begin + GutterRect.Left := GutterRect.Right + Metrics.CheckBgMargins.cxRightWidth - Metrics.CheckMargins.cxRightWidth; + GutterRect.Right := GutterRect.Left + Metrics.GutterSize.cx; + end; + Tmp := ThemeServices.GetElementDetails(tmPopupGutter); + ThemeServices.DrawElement(AHDC, Tmp, GutterRect, nil); + // draw menu item + ThemeServices.DrawElement(AHDC, Details, ARect, nil); + + if AMenuItem.IsLine then + begin + // draw separator + if IsRightToLeft then + begin + SeparatorRect.Left := GutterRect.Left - Metrics.ItemMargins.cxLeftWidth; + SeparatorRect.Right := ARect.Left - Metrics.ItemMargins.cxRightWidth; + end + else + begin + SeparatorRect.Left := GutterRect.Right + Metrics.ItemMargins.cxLeftWidth; + SeparatorRect.Right := ARect.Right - Metrics.ItemMargins.cxRightWidth; + end; + SeparatorRect.Top := ARect.Top + Metrics.ItemMargins.cyTopHeight; + SeparatorRect.Bottom := ARect.Bottom - Metrics.ItemMargins.cyBottomHeight; + Tmp := ThemeServices.GetElementDetails(tmPopupSeparator); + ThemeServices.DrawElement(AHDC, Tmp, SeparatorRect, nil); + end + else + begin + // draw check/image + if AMenuItem.HasIcon then + begin + ImageRect := CheckRect; + IconSize := AMenuItem.GetIconSize; + ImageRect.Left := (ImageRect.Left + ImageRect.Right - IconSize.x) div 2; + ImageRect.Top := (ImageRect.Top + ImageRect.Bottom - IconSize.y) div 2; + ImageRect.Right := IconSize.x; + ImageRect.Bottom := IconSize.y; + DrawMenuItemIcon(AMenuItem, AHDC, ImageRect, ASelected); + end + else + if AMenuItem.Checked then + begin + Tmp := ThemeServices.GetElementDetails(PopupCheckBgStates[AMenuItem.Enabled]); + ThemeServices.DrawElement(AHDC, Tmp, CheckRect, nil); + Tmp := ThemeServices.GetElementDetails(PopupCheckStates[AMenuItem.Enabled, AMenuItem.RadioItem]); + ThemeServices.DrawElement(AHDC, Tmp, CheckRect, nil); + end; + // draw text + TextRect := GutterRect; + if IsRightToLeft then + begin + TextRect.Right := TextRect.Left - Metrics.TextMargins.cxLeftWidth; + TextRect.Left := ARect.Left + Metrics.TextMargins.cxRightWidth; + end + else + begin + TextRect.Left := TextRect.Right + Metrics.TextMargins.cxLeftWidth; + TextRect.Right := ARect.Right - Metrics.TextMargins.cxRightWidth; + end; + TextRect.Top := (TextRect.Top + TextRect.Bottom - Metrics.TextSize.cy) div 2; + TextRect.Bottom := TextRect.Top + Metrics.TextSize.cy; + TextFlags := DT_SINGLELINE or DT_EXPANDTABS; + // todo: distinct UseRightToLeftAlignment and UseRightToLeftReading + if IsRightToLeft then + TextFlags := TextFlags or DT_RIGHT or DT_RTLREADING + else + TextFlags := TextFlags or DT_LEFT; + if ANoAccel then + TextFlags := TextFlags or DT_HIDEPREFIX; + if AMenuItem.Default then + begin + AFont := GetMenuItemFont([cfBold]); + OldFont := SelectObject(AHDC, AFont); + end + else + OldFont := 0; + ThemeServices.DrawText(AHDC, Details, AMenuItem.Caption, TextRect, TextFlags, 0); + if AMenuItem.ShortCut <> scNone then + begin + if IsRightToLeft then + begin + TextRect.Right := TextRect.Left + Metrics.ShortCustSize.cx; + TextFlags := TextFlags xor DT_RIGHT or DT_LEFT; + end + else + begin + TextRect.Left := TextRect.Right - Metrics.ShortCustSize.cx; + TextFlags := TextFlags xor DT_LEFT or DT_RIGHT; + end; + ThemeServices.DrawText(AHDC, Details, ShortCutToText(AMenuItem.ShortCut), TextRect, TextFlags, 0); + end; + if OldFont <> 0 then + DeleteObject(SelectObject(AHDC, OldFont)); + end; +end; + +function MenuItemSize(AMenuItem: TMenuItem; AHDC: HDC): TSize; var decoration: TCaptionFlagsSet; minimumHeight: Integer; begin - if aMenuItem.Default then + // TODO: vista menubar + if IsVistaMenu and not AMenuItem.IsInMenuBar then + begin + Result := VistaPopupMenuItemSize(AMenuItem, AHDC); + Exit; + end; + + if AMenuItem.Default then decoration := [cfBold] else decoration := []; - Result := StringSize(CompleteMenuItemCaption(aMenuItem), aHDC, decoration); - inc(Result.cx, LeftCaptionPosition(aMenuItem)); + Result := StringSize(CompleteMenuItemCaption(AMenuItem), AHDC, decoration); + inc(Result.cx, LeftCaptionPosition(AMenuItem)); - if not aMenuItem.IsInMenuBar then + if not AMenuItem.IsInMenuBar then inc(Result.cx, SpaceBetweenIcons) else dec(Result.cx, SpaceBetweenIcons); - if (aMenuItem.ShortCut <> scNone) then + if (AMenuItem.ShortCut <> scNone) then Inc(Result.cx, SpaceBetweenIcons); minimumHeight := GetSystemMetrics(SM_CYMENU); - if not aMenuItem.IsInMenuBar then + if not AMenuItem.IsInMenuBar then Dec(minimumHeight, 2); - if aMenuItem.IsLine then + if AMenuItem.IsLine then Result.cy := 10 // it is a separator else begin - if aMenuItem.hasIcon then + if AMenuItem.hasIcon then Result.cy := Max(Result.cy, aMenuItem.GetIconSize.y); Inc(Result.cy, 2); if Result.cy < minimumHeight then @@ -449,12 +711,12 @@ begin else decoration := []; - newFont := getMenuItemFont(decoration); + newFont := GetMenuItemFont(decoration); oldFont := SelectObject(aHDC, newFont); IsRightToLeft := aMenuItem.GetIsRightToLeft; etoFlags := ETO_OPAQUE; - dtFlags := 0; + dtFlags := DT_EXPANDTABS; if IsRightToLeft then begin etoFlags := etoFlags or ETO_RTLREADING; @@ -527,73 +789,89 @@ begin DeleteObject(newFont); end; -procedure DrawMenuItemIcon(const aMenuItem: TMenuItem; const aHDC: HDC; - const aRect: Windows.RECT; const aSelected, aChecked: boolean); +procedure DrawMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC; + const ImageRect: TRect; const ASelected: Boolean); var - x: Integer; AEffect: TGraphicsDrawEffect; AImageList: TCustomImageList; FreeImageList: Boolean; AImageIndex: Integer; - ImageRect: TRect; begin - AImageList := aMenuItem.GetImageList; + AImageList := AMenuItem.GetImageList; if AImageList = nil then begin AImageList := TImageList.Create(nil); - AImageList.Width := aMenuItem.Bitmap.Width; // maybe height to prevent too wide bitmaps? - AImageList.Height := aMenuItem.Bitmap.Height; - AImageIndex := AImageList.Add(aMenuItem.Bitmap, nil); + AImageList.Width := AMenuItem.Bitmap.Width; // maybe height to prevent too wide bitmaps? + AImageList.Height := AMenuItem.Bitmap.Height; + AImageIndex := AImageList.Add(AMenuItem.Bitmap, nil); FreeImageList := True; end else begin FreeImageList := False; - AImageIndex := aMenuItem.ImageIndex; + AImageIndex := AMenuItem.ImageIndex; end; - if not aMenuItem.Enabled then + if not AMenuItem.Enabled then AEffect := gdeDisabled else - if aSelected then + if ASelected then AEffect := gdeHighlighted else AEffect := gdeNormal; - if aMenuItem.GetIsRightToLeft then - x := aRect.Right - AImageList.Width - spaceBetweenIcons - else - x := aRect.Left + spaceBetweenIcons; - - ImageRect := Rect(x, aRect.top + TopPosition(aRect.bottom - aRect.top, AImageList.Height), - AImageList.Width, AImageList.Height); - - if aChecked then // draw rectangle around - begin - FrameRect(aHDC, - Rect(ImageRect.Left - 1, ImageRect.Top - 1, ImageRect.Left + ImageRect.Right + 1, ImageRect.Top + ImageRect.Bottom + 1), - GetSysColorBrush(COLOR_HIGHLIGHT)); - end; - if AImageIndex < AImageList.Count then - TWin32WSCustomImageList.DrawToDC(AImageList, AImageIndex, aHDC, + TWin32WSCustomImageList.DrawToDC(AImageList, AImageIndex, AHDC, ImageRect, AImageList.BkColor, AImageList.BlendColor, AEffect, AImageList.DrawingStyle, AImageList.ImageType); if FreeImageList then AImageList.Free; end; -procedure DrawMenuItem(const aMenuItem: TMenuItem; const aHDC: HDC; const aRect: Windows.RECT; const aSelected: boolean); +procedure DrawClassicMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC; + const ARect: TRect; const ASelected, AChecked: boolean); +var + x: Integer; + ImageRect: TRect; + IconSize: TPoint; begin + IconSize := AMenuItem.GetIconSize; + if AMenuItem.GetIsRightToLeft then + x := ARect.Right - IconSize.x - spaceBetweenIcons + else + x := ARect.Left + spaceBetweenIcons; + + ImageRect := Rect(x, ARect.top + TopPosition(ARect.Bottom - ARect.Top, IconSize.y), + IconSize.x, IconSize.y); + + if AChecked then // draw rectangle around + begin + FrameRect(aHDC, + Rect(ImageRect.Left - 1, ImageRect.Top - 1, ImageRect.Left + ImageRect.Right + 1, ImageRect.Top + ImageRect.Bottom + 1), + GetSysColorBrush(COLOR_HIGHLIGHT)); + end; + + DrawMenuItemIcon(AMenuItem, AHDC, ImageRect, ASelected); +end; + +procedure DrawMenuItem(const AMenuItem: TMenuItem; const AHDC: HDC; const ARect: Windows.RECT; const ASelected, ANoAccel: boolean); +begin + // TODO: vista menubar + if IsVistaMenu and not AMenuItem.IsInMenuBar then + begin + DrawVistaPopupMenu(AMenuItem, AHDC, ARect, ASelected, ANoAccel); + Exit; + end; + if aMenuItem.IsLine then - DrawSeparator(aHDC, aRect) + DrawSeparator(AHDC, ARect) else begin - DrawMenuItemText(aMenuItem, aHDC, aRect, aSelected); - if aMenuItem.hasIcon then - DrawMenuItemIcon(aMenuItem, aHDC, aRect, aSelected, aMenuItem.Checked) else - if aMenuItem.Checked then - DrawMenuItemCheckMark(aMenuItem, aHDC, aRect, aSelected); + DrawMenuItemText(AMenuItem, AHDC, ARect, ASelected); + if aMenuItem.HasIcon then + DrawClassicMenuItemIcon(AMenuItem, AHDC, ARect, ASelected, AMenuItem.Checked) else + if AMenuItem.Checked then + DrawMenuItemCheckMark(AMenuItem, AHDC, ARect, ASelected); end; end;