【问题标题】:How I can change the color of a TPanel with the VCL Styles enabled?如何在启用 VCL 样式的情况下更改 TPanel 的颜色?
【发布时间】:2012-04-25 04:01:19
【问题描述】:

启用 VCL 样式后,我需要更改 TPanel 的颜色。我尝试使用和修改文章 Changing the color of Edit Controls with VCL Styles Enabled 中列出的代码,但它不适用于 TPanel。如何在启用 VCL 样式的情况下更改 TPanel 的颜色?

【问题讨论】:

    标签: delphi delphi-xe2 vcl-styles


    【解决方案1】:

    TPanel 不使用样式挂钩来绘制控件,因此您不能使用文章中描述的技术。相反,您必须重写 paint 方法。

    使用插入器类检查此示例。

    type
    
      TPanel=Class(Vcl.ExtCtrls.TPanel)
      protected
        procedure Paint; override;
      End;
    
    
    Uses
      Vcl.Styles,
      Vcl.Themes;
    
    {$R *.dfm}
    
    { TPanel }
    
    procedure TPanel.Paint;
    const
      Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);
      VerticalAlignments: array[TVerticalAlignment] of Longint = (DT_TOP, DT_BOTTOM, DT_VCENTER);
    var
      Rect: TRect;
      LColor: TColor;
      LStyle: TCustomStyleServices;
      LDetails: TThemedElementDetails;
      TopColor        : TColor;
      BottomColor     : TColor;
      LBaseColor      : TColor;
      LBaseTopColor   : TColor;
      LBaseBottomColor: TColor;
      Flags: Longint;
    
      procedure AdjustColors(Bevel: TPanelBevel);
      begin
        TopColor := LBaseTopColor;
        if Bevel = bvLowered then
          TopColor := LBaseBottomColor;
        BottomColor := LBaseBottomColor;
        if Bevel = bvLowered then
          BottomColor := LBaseTopColor;
      end;
    
    begin
      Rect := GetClientRect;
    
      LBaseColor := Color;//use the color property value to get the background color.
      LBaseTopColor := clBtnHighlight;
      LBaseBottomColor := clBtnShadow;
      LStyle := StyleServices;
      if LStyle.Enabled then
      begin
        LDetails := LStyle.GetElementDetails(tpPanelBevel);
        if LStyle.GetElementColor(LDetails, ecEdgeHighLightColor, LColor) and (LColor <> clNone) then
          LBaseTopColor := LColor;
        if LStyle.GetElementColor(LDetails, ecEdgeShadowColor, LColor) and (LColor <> clNone) then
          LBaseBottomColor := LColor;
      end;
    
      if BevelOuter <> bvNone then
      begin
        AdjustColors(BevelOuter);
        Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
      end;
      if not (LStyle.Enabled and (csParentBackground in ControlStyle)) then
        Frame3D(Canvas, Rect, LBaseColor, LBaseColor, BorderWidth)
      else
        InflateRect(Rect, -Integer(BorderWidth), -Integer(BorderWidth));
      if BevelInner <> bvNone then
      begin
        AdjustColors(BevelInner);
        Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
      end;
      with Canvas do
      begin
        if not LStyle.Enabled or not ParentBackground then
        begin
          Brush.Color := LBaseColor;
          FillRect(Rect);
        end;
    
        if ShowCaption and (Caption <> '') then
        begin
          Brush.Style := bsClear;
          Font := Self.Font;
          Flags := DT_EXPANDTABS or DT_SINGLELINE or
            VerticalAlignments[VerticalAlignment] or Alignments[Alignment];
          Flags := DrawTextBiDiModeFlags(Flags);
          if LStyle.Enabled then
          begin
            LDetails := LStyle.GetElementDetails(tpPanelBackground);
            if not LStyle.GetElementColor(LDetails, ecTextColor, LColor) or (LColor = clNone) then
              LColor := Font.Color;
            LStyle.DrawText(Handle, LDetails, Caption, Rect, TTextFormatFlags(Flags), LColor)
          end
          else
            DrawText(Handle, Caption, -1, Rect, Flags);
        end;
      end;
    end;
    

    【讨论】:

    • 似乎有更简单的方法,请参阅其他答案
    • ecEdgeHighLightColor 已经足够接近,但获取用于绘制 TPanel 主体的颜色的实际常量是哪个?
    • 我找到了答案:tpPanelBackground + ecFillColor。它适用于大多数主题,但不适用于“Auric”。但对于 Auric 来说,它会给出一个足够接近的结果。 -------------------------- 更新:这将始终有效:cl:= TStyleManager.ActiveStyle.GetSystemColor(clBtnFace);
    【解决方案2】:

    在 XE5 中,如果您关闭 StyleElements 属性中的 seClient 标志,则 Color 属性会再次按预期工作。

    【讨论】:

    • 感谢您的提示,正在将我的一些旧 Delphi 代码升级到 Berlin 10.1 Update 2 并且它没有绘制我正在使用的 TPanel 控件后代的背景
    • @GeorgeBirbilis:很高兴它帮助了你。接受的答案似乎有点矫枉过正。
    • 太棒了!在 XE5 中使用 TSpeedButton 的样式元素,尽管启用了视觉主题,我仍能够更改其字体颜色和样式。可以帮助别人。
    【解决方案3】:

    根据@costa 的回答,使用:

    StyleElements := StyleElements - [seClient];
    

    在您的 TPanel 后代类的构造函数中

    或者,如果您只有一些 TPanel(或后代类)实例,您可以这样做:

    with myPanel do StyleElements := StyleElements - [seClient];
    

    使用 -[...] 语法,因为 StyleElements 是一个集合

    有关 StyleElements 的更多信息,请阅读这篇文章:

    为表单和控件调整 VCL 样式 - http://edn.embarcadero.com/article/42812

    【讨论】:

    • 这是一个更简单的解决方案。适用于 Delphi 2007 以及使用 TControlStyle。 { ControlStyle := MyPanel.ControlStyle;排除(ControlStyle,csParentBackground); MyPanel.ControlStyle := ControlStyle; }
    • 在找到这个解决方案之前,我正处于切换到 C# 和 XAML 的边缘。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多