RadioItems on the menu on TActionMainMenuBar

I am using TActionMainMenuBar to display TActions based menus. I grouped the actions by installing the same GroupIndex. Thus, they can work like RadioGroup, but the problem is that instead of switches, inverse is used.

Is there any way to change this?

+4
source share
1 answer

Here is my fix for TPlatformDefaultStyleActionBars .

enter image description here

Most of the code is simply copied from standard units except for TFixedThemedMenuItemStyle.DoDrawMenuCheck .

Note that you must also override TXPStyleMenuItem if you want to run your software on an OS prior to Vista.

 uses // ... add these units StdStyleActnCtrls, XPStyleActnCtrls, XPActnCtrls, ImgList, Types, Themes, StdActnMenus, ThemedActnCtrls, ListActns, UxTheme; type TFixedThemedMenuItemStyle = class(TThemedMenuItem) private FCheckRect: TRect; FGutterRect: TRect; FPaintRect: TRect; FSubMenuGlyphRect: TRect; FSeparatorHeight: Integer; procedure DoDrawMenuCheck; procedure DoDrawText(DC: HDC; const Text: string; var Rect: TRect; Flags: Longint); protected procedure DrawGlyph(const Location: TPoint); override; public procedure CalcBounds; override; end; TFixedPlatformDefaultStyleActionBars = class(TPlatformDefaultStyleActionBars) public function GetControlClass(ActionBar: TCustomActionBar; AnItem: TActionClientItem): TCustomActionControlClass; override; function GetStyleName: string; override; end; TForm1 = class(TForm) ActionMainMenuBar1: TActionMainMenuBar; ActionManager1: TActionManager; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private Style: TFixedPlatformDefaultStyleActionBars; public end; implementation procedure TForm1.FormCreate(Sender: TObject); begin Style := TFixedPlatformDefaultStyleActionBars.Create(); ActionManager1.Style := Style; end; procedure TForm1.FormDestroy(Sender: TObject); begin Style.Free(); end; procedure TFixedThemedMenuItemStyle.CalcBounds; const CheckMarkStates: array[Boolean] of Integer = (MC_CHECKMARKDISABLED, MC_CHECKMARKNORMAL); SubMenuStates: array[Boolean] of Integer = (MSM_DISABLED, MSM_NORMAL); var DC: HDC; LFont: HFONT; LTheme: HTheme; LBounds: TRect; LImageSize: TPoint; LHeight, LWidth, Offset: Integer; LGlyphSize, LGutterSize, LSeparatorSize, LSubMenuGlyphSize: TSize; LCheckMargins, LGutterMargins, LMenuItemMargins, LSeparatorMargins, LSubMenuGlyphMargins: TMargins; begin // Fill in parent object private fields. inherited; DC := CreateCompatibleDC(0); try LFont := SelectObject(DC, Screen.MenuFont.Handle); try Font.Assign(Screen.MenuFont); inherited; LTheme := ThemeServices.Theme[teMenu]; LHeight := 0; LWidth := 0; // Check/Glyph GetThemePartSize(LTheme, DC, MENU_POPUPCHECK, CheckMarkStates[Enabled], nil, TS_TRUE, LGlyphSize); GetThemeMargins(LTheme, DC, MENU_POPUPCHECK, CheckMarkStates[Enabled], TMT_CONTENTMARGINS, nil, LCheckMargins); // Gutter GetThemePartSize(LTheme, DC, MENU_POPUPGUTTER, 0, nil, TS_TRUE, LGutterSize); GetThemeMargins(LTheme, DC, MENU_POPUPGUTTER, 0, TMT_SIZINGMARGINS, nil, LGutterMargins); // Menu item GetThemeMargins(LTheme, DC, MENU_POPUPITEM, MPI_NORMAL, TMT_SIZINGMARGINS, nil, LMenuItemMargins); GetThemePartSize(LTheme, DC, MENU_POPUPSUBMENU, SubMenuStates[Enabled], nil, TS_TRUE, LSubMenuGlyphSize); GetThemeMargins(LTheme, DC, MENU_POPUPSUBMENU, SubMenuStates[Enabled], TMT_CONTENTMARGINS, nil, LSubMenuGlyphMargins); // Calculate check/glyph size LImageSize := GetImageSize; if LImageSize.Y > LGlyphSize.cy then LGlyphSize.cy := LImageSize.Y; if LImageSize.X > LGlyphSize.cx then LGlyphSize.cx := LImageSize.X; Inc(LHeight, LGlyphSize.cy); Inc(LWidth, LGlyphSize.cx); // Add margins for check/glyph Inc(LHeight, LCheckMargins.cyTopHeight + LCheckMargins.cyBottomHeight); Inc(LWidth, LCheckMargins.cxLeftWidth + LCheckMargins.cxRightWidth); FCheckRect := Rect(0, 0, LGlyphSize.cx + LCheckMargins.cxRightWidth + LCheckMargins.cxRightWidth, LGlyphSize.cy + LCheckMargins.cyBottomHeight + LCheckMargins.cyBottomHeight); // Add size and margins for gutter Inc(LWidth, LGutterMargins.cxLeftWidth); FGutterRect.Left := LWidth; FGutterRect.Right := FGutterRect.Left + LGutterSize.cx; Inc(LWidth, LGutterSize.cx + LGutterMargins.cxRightWidth); // Add margins for menu item Inc(LWidth, LMenuItemMargins.cxLeftWidth + LMenuItemMargins.cxRightWidth); Offset := LWidth - TextBounds.Left - LMenuItemMargins.cxRightWidth; LBounds := TextBounds; OffsetRect(LBounds, Offset, -1); TextBounds := LBounds; // Add size of potential submenu glyph Inc(LWidth, LSubMenuGlyphSize.cx); Inc(LWidth, LSubMenuGlyphMargins.cxLeftWidth); Inc(LWidth, LSubMenuGlyphMargins.cxRightWidth); // Add Width of menu item to FSubMenuGlyphRect before using FSubMenuGlyphRect := Rect(-LSubMenuGlyphMargins.cxRightWidth - LSubMenuGlyphSize.cx, (Height - LSubMenuGlyphSize.cy) div 2, -LSubMenuGlyphMargins.cxRightWidth, ((Height - LSubMenuGlyphSize.cy) div 2) + LSubMenuGlyphSize.cy); // Add margins for menu short cut if ActionClient <> nil then begin LBounds := Rect(0, 0, 0, 0); DoDrawText(DC, ActionClient.ShortCutText, LBounds, DT_CALCRECT or DT_NOCLIP); end else LBounds := ShortCutBounds; Offset := FSubMenuGlyphRect.Left - LBounds.Right - LMenuItemMargins.cxRightWidth - LSubMenuGlyphMargins.cxLeftWidth; OffsetRect(LBounds, Offset, 0); // Add Width of menu item to ShortCutBounds before using ShortCutBounds := LBounds; Inc(LWidth, LMenuItemMargins.cxLeftWidth + LMenuItemMargins.cxRightWidth); // Adjust size if separator if Separator then begin GetThemePartSize(LTheme, DC, MENU_POPUPSEPARATOR, 0, nil, TS_TRUE, LSeparatorSize); GetThemeMargins(LTheme, DC, MENU_POPUPSEPARATOR, 0, TMT_SIZINGMARGINS, nil, LSeparatorMargins); LHeight := LSeparatorSize.cy + LSeparatorMargins.cyBottomHeight; LWidth := LSeparatorSize.cx; FSeparatorHeight := LSeparatorSize.cy; end; FGutterRect.Top := 0; FGutterRect.Bottom := LHeight; SetBounds(Left, Top, LWidth + TextBounds.Right - TextBounds.Left + ShortCutBounds.Right - ShortCutBounds.Left, LHeight); finally SelectObject(DC, LFont); end; finally DeleteDC(DC); end; end; // THE ONLY SERIOUS DIFFERENCE: RENDERING BULLETS INSTEAD OF CHECKMARKS FOR RADIO ITEMS procedure TFixedThemedMenuItemStyle.DoDrawMenuCheck; const CheckMarkBkgs: array[Boolean] of Integer = (MCB_DISABLED, MCB_NORMAL); CheckMarkStates: array[Boolean] of Integer = (MC_CHECKMARKDISABLED, MC_CHECKMARKNORMAL); RadioMarkStates: array[Boolean] of Integer = (MC_BULLETDISABLED, MC_BULLETNORMAL); begin if IsChecked then begin DrawThemeBackground(ThemeServices.Theme[teMenu], Canvas.Handle, MENU_POPUPCHECKBACKGROUND, CheckMarkBkgs[Enabled], FCheckRect, nil); if not HasGlyph then begin if IsGrouped then begin DrawThemeBackground(ThemeServices.Theme[teMenu], Canvas.Handle, MENU_POPUPCHECK, RadioMarkStates[Enabled], FCheckRect, nil); end else begin DrawThemeBackground(ThemeServices.Theme[teMenu], Canvas.Handle, MENU_POPUPCHECK, CheckMarkStates[Enabled], FCheckRect, nil); end; end; end; end; procedure TFixedThemedMenuItemStyle.DoDrawText( DC: HDC; const Text: string; var Rect: TRect; Flags: Integer); const MenuStates: array[Boolean] of Integer = (MPI_DISABLED, MPI_NORMAL); var Options: TDTTOpts; begin // Setup Options {$IF NOT DEFINED(CLR)} FillChar(Options, SizeOf(Options), 0); Options.dwSize := SizeOf(Options); {$ELSE} Options.dwSize := Marshal.SizeOf(TypeOf(Options)); {$IFEND} Options.dwFlags := DTT_TEXTCOLOR or DTT_COMPOSITED; if Flags and DT_CALCRECT = DT_CALCRECT then Options.dwFlags := Options.dwFlags or DTT_CALCRECT; // Retrieve text color GetThemeColor(ThemeServices.Theme[teMenu], MENU_POPUPITEM, MenuStates[Enabled or ActionBar.DesignMode], TMT_TEXTCOLOR, Options.crText); // Draw menu item text DrawThemeTextEx(ThemeServices.Theme[teMenu], DC, MENU_POPUPITEM, MenuStates[Enabled or ActionBar.DesignMode], Text, Length(Text), Flags, Rect, Options); end; procedure TFixedThemedMenuItemStyle.DrawGlyph(const Location: TPoint); var LImageSize, LLocation: TPoint; begin if (Action is TCustomAction) and TCustomAction(Action).Checked then DoDrawMenuCheck; if HasGlyph then begin LImageSize := GetImageSize; LLocation.X := ((FCheckRect.Right - FCheckRect.Left) - LImageSize.X) div 2; LLocation.Y := ((FCheckRect.Bottom - FCheckRect.Top) - LImageSize.Y) div 2; inherited DrawGlyph(LLocation); end; end; type TActionControlStyle = (csStandard, csXPStyle, csThemed); function GetActionControlStyle: TActionControlStyle; begin if Win32MajorVersion >= 6 then begin if ThemeServices.Theme[teMenu] <> 0 then Result := csThemed else Result := csXPStyle; end else if CheckWin32Version(5, 1) then Result := csXPStyle else Result := csStandard; end; function TFixedPlatformDefaultStyleActionBars.GetControlClass(ActionBar: TCustomActionBar; AnItem: TActionClientItem): TCustomActionControlClass; begin if ActionBar is TCustomActionToolBar then begin if AnItem.HasItems then case GetActionControlStyle of csStandard: Result := TStandardDropDownButton; csXPStyle: Result := TXPStyleDropDownBtn; else Result := TThemedDropDownButton; end else if (AnItem.Action is TStaticListAction) or (AnItem.Action is TVirtualListAction) then Result := TCustomComboControl else case GetActionControlStyle of csStandard: Result := TStandardButtonControl; csXPStyle: Result := TXPStyleButton; else Result := TThemedButtonControl; end end else if ActionBar is TCustomActionMainMenuBar then case GetActionControlStyle of csStandard: Result := TStandardMenuButton; csXPStyle: Result := TXPStyleMenuButton; else Result := TThemedMenuButton; end else if ActionBar is TCustomizeActionToolBar then begin with TCustomizeActionToolbar(ActionBar) do if not Assigned(RootMenu) or (AnItem.ParentItem <> TCustomizeActionToolBar(RootMenu).AdditionalItem) then case GetActionControlStyle of csStandard: Result := TStandardMenuItem; csXPStyle: Result := TXPStyleMenuItem; else Result := TFixedThemedMenuItemStyle; end else case GetActionControlStyle of csStandard: Result := TStandardAddRemoveItem; csXPStyle: Result := TXPStyleAddRemoveItem; else Result := TThemedAddRemoveItem; end end else if ActionBar is TCustomActionPopupMenu then case GetActionControlStyle of csStandard: Result := TStandardMenuItem; csXPStyle: Result := TXPStyleMenuItem; else Result := TFixedThemedMenuItemStyle; end else case GetActionControlStyle of csStandard: Result := TStandardButtonControl; csXPStyle: Result := TXPStyleButton; else Result := TThemedButtonControl; end end; function TFixedPlatformDefaultStyleActionBars.GetStyleName: string; begin Result := 'My fixed platform style'; end; 
+1
source

Source: https://habr.com/ru/post/1411724/


All Articles