Search code examples
delphiglyph

XP Style Glyph annoyance in ActionBars


I dont like to ask too many questions in relation to the appearance of components, but these days appearance in Applications seems just as important.

Anyway, please see the below images:

enter image description here

Both are using the TActionManager and TActionMainMenuBar to create my main menu. The menu in the left of the image is using the Platform Default Style, the menu on the right is using the XP style defined by my TActionManager.

Notice how when the left menu is highlighted, the glyph remains the same which is perfect.

Now look at the XP style menu on the right, the glyph draws a drop shadow, pops out slightly and you can see the transparency makes the glyph appear slightly odd.

I want to enable the XP style for my UI, but the way the glyphs are painted I do not like. I also want to change my TToolbar to a TActionToolBar and apply the same XP style, but this will render the glyphs the same too.

How can I make the XP style menu defined in the TActionManager, not render the glyphs like this?

Thanks.

EDIT

This is now the result, having applied some of the techniques from the answers below:

enter image description here

Craig.


Solution

  • Here is some sample code that overrides the XP STYLE, creating a derived class that you can tweak as you like. First step here is to substitute your own derived menu item class, and change its DrawGlyph code, as David told you. I figured you could maybe use some sample code.

    This is just a quick demo. It doesn't draw a box around checked items with glyphs, so this custom style is not compatible with Checked items, unless they have no glyphs. You would have to figure out how you want to draw the checked-glyph items (Where I wrote the DrawGlyphFrame would be a good place to add something to draw a checked-state rectangle around a glyph if the Action.Checked property is set).

    unit MyActionControlStyle;
    
    // Using this unit: Add it to your project. In your project set your
    // style at runtime, add the unit to your uses clause and then set the style
    // in that form's formcreate event:
    //   ActionManager1.Style := MyActionControlStyle.MyStyle;
    
    interface
    
    uses Forms,
         Types,
         Controls,
         XPActnCtrls,
         XPStyleActnCtrls,
         ActnMan,
         ActnList,
         ActnMenus,
         ActnCtrls;
    
    type
    
     TMyStyleMenuItem = class(TXPStyleMenuItem)
      protected
          procedure DrawGlyph(const Location: TPoint); override;
    
    //      procedure DrawGlyphFrame(const Location:TPoint);
    
     end;
     TMyStyleMenuButton = class(TXPStyleMenuButton)
     end;
    
     TMyStyleActionBars = class(TXPStyleActionBars)
       // override the stuff that I want different than XP Style:
        function GetControlClass(ActionBar: TCustomActionBar;
          AnItem: TActionClientItem): TCustomActionControlClass; override;
    
     end;
    
    var
     MyStyle:TMyStyleActionBars;
    
    implementation
    
    
    uses ToolWin, Classes, Windows, Graphics, GraphUtil, ImgList;
    { TMyStyleActionBars }
    
    function TMyStyleActionBars.GetControlClass(ActionBar: TCustomActionBar;
      AnItem: TActionClientItem): TCustomActionControlClass;
    begin
     if ActionBar is TCustomActionPopupMenu then
        Result := TMyStyleMenuItem
      else
      if ActionBar is TCustomActionMainMenuBar then
        Result := TMyStyleMenuButton
      else
        Result := inherited GetControlClass(ActionBar,AnItem);
    
    end;
    
    { TMyStyleMenuItem }
    
    procedure TMyStyleMenuItem.DrawGlyph(const Location: TPoint);
    var
      ImageList: TCustomImageList;
      DrawEnabled: Boolean;
    begin
    //  DrawGlyphFrame(Location);
      if not HasGlyph and IsChecked then
      begin
        Canvas.Pen.Color := ActionBar.ColorMap.FontColor;
        DrawCheck(Canvas, Point((TextBounds.Left - 5) div 2, Height div 2), 2);
      end;
    
      if not HasGlyph then exit;
      if Assigned(Action) then
        ImageList := ActionClient.Action.ActionList.Images
      else
        ImageList := ActionClient.OwningCollection.ActionManager.Images;
      if not Assigned(ImageList) then exit;
      DrawEnabled := Enabled and (ActionClient.ImageIndex <> -1) or
        (csDesigning in ComponentState);
      ImageList.Draw(Canvas, Location.X, Location.Y, ActionClient.ImageIndex,
        dsTransparent, itImage, DrawEnabled);
    
    end;
    
    initialization
      MyStyle := TMyStyleActionBars.Create;
      RegisterActnBarStyle(MyStyle);
    finalization
      UnregisterActnBarStyle(MyStyle);
      MyStyle.Free;
    end.