当启用VCL样式时,我该如何改变TPanel的颜色?

15

当启用VCL样式时,我需要更改TPanel的颜色。 我尝试使用并修改文章《启用VCL样式更改编辑控件颜色》中列出的代码,但对于TPanel不起作用。 我该如何在启用VCL样式的情况下更改TPanel的颜色?

3个回答

21
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;

这里输入图片描述


1
似乎有更简单的方法,请参考其他答案。 - George Birbilis
ecEdgeHighLightColor已经很接近了,但获取TPanel绘制主体的颜色所用的实际常量是什么? - Gabriel
我已经找到了答案:tpPanelBackground + ecFillColor。它适用于大多数主题,但不适用于'Auric'。但对于Auric,它将给出一个足够接近的结果。 更新:这将始终有效:cl:=TStyleManager.ActiveStyle.GetSystemColor(clBtnFace); - Gabriel

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

谢谢你的提示,我正在将我的一些旧Delphi代码升级到Berlin 10.1 Update 2版本,但是我使用的一个TPanel控件派生类没有绘制背景。 - George Birbilis
3
很高兴能帮助到您。被接受的答案似乎有些过头了。 - boggy
太棒了!在XE5中玩弄TSpeedButton的样式元素后,我成功地改变了它的字体颜色和样式,尽管启用了视觉主题。这可能会对某些人有所帮助。 - user30478

4

根据@costa的回答,使用:

StyleElements := StyleElements - [seClient];

在您的 TPanel 子类的构造函数中,或者如果您只有一些 TPanel(或子类)实例,可以执行以下操作:
with myPanel do StyleElements := StyleElements - [seClient];

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

想要了解更多关于 StyleElements 的内容,请阅读这篇文章:

调整 VCL 样式以适应窗体和控件 - http://edn.embarcadero.com/article/42812


1
这是一种更简单的解决方案。使用TControlStyle,也适用于Delphi 2007。{ ControlStyle := MyPanel.ControlStyle; Exclude(ControlStyle, csParentBackground); MyPanel.ControlStyle := ControlStyle; } - Airs
1
我曾经准备转向C#和XAML,直到我找到了这个解决方案。 - Phil Rogers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接