如何更改主题选项卡标题的文本颜色?

2024-01-25

再会!

我需要更改 TPageControl 中某些 TabSheet 的标题的文本颜色。图片上有类似这样的东西

我知道如何使用 OnDrawTab 来完成它。但如果我启用了 OwnerDraw,Windows XP 主题的装饰就会消失。这就是为什么我尝试手动绘制这个装饰。这就是我尝试这样做的方式:

procedure TForm1.PageControl1DrawTab(Control: TCustomTabControl;
  TabIndex: Integer; const Rect: TRect; Active: Boolean);
var
  FRect: TRect;
  Text: string;
begin
  FRect := Control.TabRect(TabIndex);
  if Active then
    ThemeServices.DrawElement(Control.Canvas.Handle, ThemeServices.GetElementDetails(ttTabItemHot), FRect)
  else
    ThemeServices.DrawElement(Control.Canvas.Handle, ThemeServices.GetElementDetails(ttTabItemNormal), FRect);
  Text := PageControl1.Pages[TabIndex].Caption;
  Control.Canvas.Brush.Style := bsClear;
  if not Active then
    FRect.Top := FRect.Top + 4;
  DrawText(Control.Canvas.Handle, PChar(Text), Length(Text), FRect, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
end;

我得到了这个

(左 - OwnerDraw 版本,右 - 默认绘制)

如您所见,TabSheets 有一些未过度绘制的边框。我不能透支这个边界。

如何正确绘制选项卡的背景(如右侧的 PageControl)?


一个可能的解决方案是覆盖PaintWindow的方法TPageControl http://docwiki.embarcadero.com/Libraries/en/Vcl.ComCtrls.TPageControl而不是使用 Ownerdraw ,通过这种方式,您可以控制选项卡的每个视觉方面。

检查这个基本示例。

type
  TPageControl = class(Vcl.ComCtrls.TPageControl)
  private
    FColorTextTab: TColor;
    procedure  DrawTab(LCanvas: TCanvas; Index: Integer);
    procedure  DoDraw(DC: HDC; DrawTabs: Boolean);
    procedure SetColorTextTab(const Value: TColor);
  protected
    procedure PaintWindow(DC: HDC); override;
  published
    property  ColorTextTab : TColor read FColorTextTab write SetColorTextTab;

  end;

  TForm1 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    CheckBox1: TCheckBox;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    TabSheet3: TTabSheet;
    TabSheet4: TTabSheet;
    TabSheet5: TTabSheet;
    TabSheet6: TTabSheet;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
 Math,
 Themes,
 Types;


type
  TCustomTabControlClass = class(TCustomTabControl);

procedure AngleTextOut2(Canvas: TCanvas; Angle: Integer; X, Y: Integer; const Text: string);
var
  NewFontHandle, OldFontHandle: hFont;
  LogRec: TLogFont;
begin
  GetObject(Canvas.Font.Handle, SizeOf(LogRec), Addr(LogRec));
  LogRec.lfEscapement := Angle * 10;
  LogRec.lfOrientation := LogRec.lfEscapement;
  NewFontHandle := CreateFontIndirect(LogRec);
  OldFontHandle := SelectObject(Canvas.Handle, NewFontHandle);
  SetBkMode(Canvas.Handle, TRANSPARENT);
  Canvas.TextOut(X, Y, Text);
  NewFontHandle := SelectObject(Canvas.Handle, OldFontHandle);
  DeleteObject(NewFontHandle);
end;


{ TPageControl }
procedure TPageControl.DrawTab(LCanvas: TCanvas; Index: Integer);
var
  LDetails    : TThemedElementDetails;
  LImageIndex : Integer;
  LThemedTab  : TThemedTab;
  LIconRect   : TRect;
  R, LayoutR  : TRect;
  LImageW, LImageH, DxImage : Integer;
  LTextX, LTextY: Integer;
  LTextColor    : TColor;
    //draw the text in the tab
    procedure DrawControlText(const S: string; var R: TRect; Flags: Cardinal);
    var
      TextFormat: TTextFormatFlags;
    begin
      LCanvas.Font       := Font;
      TextFormat         := TTextFormatFlags(Flags);
      LCanvas.Font.Color := LTextColor;
      StyleServices.DrawText(LCanvas.Handle, LDetails, S, R, TextFormat, LCanvas.Font.Color);
    end;

begin
  //get the size of tab image (icon)
  if (Images <> nil) and (Index < Images.Count) then
  begin
    LImageW := Images.Width;
    LImageH := Images.Height;
    DxImage := 3;
  end
  else
  begin
    LImageW := 0;
    LImageH := 0;
    DxImage := 0;
  end;

  R := TabRect(Index);


  //check the left position of the tab.
  if R.Left < 0 then Exit;

  //adjust the size of the tab to draw
  if TabPosition in [tpTop, tpBottom] then
  begin
    if Index = TabIndex then
      InflateRect(R, 0, 2);
  end
  else
  if Index = TabIndex then
    Dec(R.Left, 2)
  else
    Dec(R.Right, 2);

  LCanvas.Font.Assign(Font);
  LayoutR := R;
  LThemedTab := ttTabDontCare;
  //Get the type of the active tab to draw

  case TabPosition of
    tpTop:
      begin
        if Index = TabIndex then
          LThemedTab := ttTabItemSelected
        else
        {
        if (Index = HotTabIndex) and MouseInControl then
          LThemedTab := ttTabItemHot
        else
        }
          LThemedTab := ttTabItemNormal;
      end;
    tpLeft:
      begin
        if Index = TabIndex then
          LThemedTab := ttTabItemLeftEdgeSelected
        else
        {
        if (Index = HotTabIndex) and MouseInControl then
          LThemedTab := ttTabItemLeftEdgeHot
        else
        }
          LThemedTab := ttTabItemLeftEdgeNormal;
      end;
    tpBottom:
      begin
        if Index = TabIndex then
          LThemedTab := ttTabItemBothEdgeSelected
        else
        {
        if (Index = HotTabIndex) and MouseInControl then
          LThemedTab := ttTabItemBothEdgeHot
        else
        }
          LThemedTab := ttTabItemBothEdgeNormal;
      end;
    tpRight:
      begin
        if Index = TabIndex then
          LThemedTab := ttTabItemRightEdgeSelected
        else
        {
        if (Index = HotTabIndex) and MouseInControl then
          LThemedTab := ttTabItemRightEdgeHot
        else
        }
          LThemedTab := ttTabItemRightEdgeNormal;
      end;
  end;

  //draw the tab
  if StyleServices.Available then
  begin
    LDetails := StyleServices.GetElementDetails(LThemedTab);//necesary for DrawControlText and draw the icon
    StyleServices.DrawElement(LCanvas.Handle, LDetails, R);
  end;

  //get the index of the image (icon)
  if Self is TCustomTabControl then
    LImageIndex := TCustomTabControlClass(Self).GetImageIndex(Index)
  else
    LImageIndex := Index;

  //draw the image
  if (Images <> nil) and (LImageIndex >= 0) and (LImageIndex < Images.Count) then
  begin
    LIconRect := LayoutR;
    case TabPosition of
      tpTop, tpBottom:
        begin
          LIconRect.Left := LIconRect.Left + DxImage;
          LIconRect.Right := LIconRect.Left + LImageW;
          LayoutR.Left := LIconRect.Right;
          LIconRect.Top := LIconRect.Top + (LIconRect.Bottom - LIconRect.Top) div 2 - LImageH div 2;
          if (TabPosition = tpTop) and (Index = TabIndex) then
            OffsetRect(LIconRect, 0, -1)
          else
          if (TabPosition = tpBottom) and (Index = TabIndex) then
            OffsetRect(LIconRect, 0, 1);
        end;
      tpLeft:
        begin
          LIconRect.Bottom := LIconRect.Bottom - DxImage;
          LIconRect.Top := LIconRect.Bottom - LImageH;
          LayoutR.Bottom := LIconRect.Top;
          LIconRect.Left := LIconRect.Left + (LIconRect.Right - LIconRect.Left) div 2 - LImageW div 2;
        end;
      tpRight:
        begin
          LIconRect.Top := LIconRect.Top + DxImage;
          LIconRect.Bottom := LIconRect.Top + LImageH;
          LayoutR.Top := LIconRect.Bottom;
          LIconRect.Left := LIconRect.Left + (LIconRect.Right - LIconRect.Left) div 2 - LImageW div 2;
        end;
    end;
    if StyleServices.Available then
      StyleServices.DrawIcon(LCanvas.Handle, LDetails, LIconRect, Images.Handle, LImageIndex);
  end;

  //draw the text of the tab
  if StyleServices.Available then
  begin
    //StyleServices.GetElementColor(LDetails, ecTextColor, LTextColor);
    LTextColor:=FColorTextTab;

    if (TabPosition = tpTop) and (Index = TabIndex) then
      OffsetRect(LayoutR, 0, -1)
    else
    if (TabPosition = tpBottom) and (Index = TabIndex) then
      OffsetRect(LayoutR, 0, 1);

    if TabPosition = tpLeft then
    begin
      LTextX := LayoutR.Left + (LayoutR.Right - LayoutR.Left) div 2 - LCanvas.TextHeight(Tabs[Index]) div 2;
      LTextY := LayoutR.Top + (LayoutR.Bottom - LayoutR.Top) div 2 + LCanvas.TextWidth(Tabs[Index]) div 2;
      LCanvas.Font.Color:=LTextColor;
      AngleTextOut2(LCanvas, 90, LTextX, LTextY, Tabs[Index]);
    end
    else
    if TabPosition = tpRight then
    begin
      LTextX := LayoutR.Left + (LayoutR.Right - LayoutR.Left) div 2 + LCanvas.TextHeight(Tabs[Index]) div 2;
      LTextY := LayoutR.Top + (LayoutR.Bottom - LayoutR.Top) div 2 - LCanvas.TextWidth(Tabs[Index]) div 2;
      LCanvas.Font.Color:=LTextColor;
      AngleTextOut2(LCanvas, -90, LTextX, LTextY, Tabs[Index]);
    end
    else
     DrawControlText(Tabs[Index], LayoutR, DT_VCENTER or DT_CENTER or DT_SINGLELINE  or DT_NOCLIP);
  end;
end;

procedure TPageControl.DoDraw(DC: HDC; DrawTabs: Boolean);
var
  Details: TThemedElementDetails;
  R: TRect;
  LIndex, SelIndex: Integer;
begin
  Details := StyleServices.GetElementDetails(ttTabItemNormal);
  SelIndex := TabIndex;
  try
    Canvas.Handle := DC;
    if DrawTabs then
      for LIndex := 0 to Tabs.Count - 1 do
        if LIndex <> SelIndex then
         DrawTab(Canvas, LIndex);

    if SelIndex < 0 then
      R := Rect(0, 0, Width, Height)
    else
    begin
      R := TabRect(SelIndex);
      R.Left := 0;
      R.Top := R.Bottom;
      R.Right := Width;
      R.Bottom := Height;
    end;

    StyleServices.DrawElement(DC, StyleServices.GetElementDetails(ttPane), R);

    if (SelIndex >= 0) and DrawTabs then
      DrawTab(Canvas, SelIndex);
  finally
    Canvas.Handle := 0;
  end;
end;

procedure TPageControl.PaintWindow(DC: HDC);
begin
 DoDraw(DC, True);
 //inherited;
end;

procedure TPageControl.SetColorTextTab(const Value: TColor);
begin
  FColorTextTab := Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  PageControl1.ColorTextTab:=clGreen;
end;

这就是结果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何更改主题选项卡标题的文本颜色? 的相关文章

随机推荐

  • 转换 Android Base64 位图并在 HTML Base64 图像上显示

    我开发了一个自定义消息应用程序 它将消息从客户端 Android 发送到另一个客户端 Web 我的问题是当我发送图像文件时 我将其编码为Base64字符串 然后将其发送给另一个客户端 当接收方客户端为Android时 应用程序成功解码Bas
  • 在 Elm 中解析嵌套 JSON

    我有这种情况 this is in post elm type alias Model img String text String source String date String comments Comments Model thi
  • 是否有用于本机反应的“固定标头”或“粘性标头”?

    有没有办法为本机反应提供固定且永久的顶部标题栏 我认为它被称为标题 几乎就像状态栏一样 它始终存在 但它需要位于顶部 甚至在反应导航的 标题 之前 我的计划是在那里放置一个全局搜索输入 这样您就可以在应用程序的任何位置进行搜索 搜索内容不受
  • 如何以及何时使用 /dev/shm 来提高效率?

    How is dev shm比在常规文件系统上写入文件更有效吗 据我所知 dev shm也是硬盘上的一个空间 因此读 写速度是相同的 我的问题是 我有一个 96GB 的文件 但只有 64GB RAM 64GB 交换空间 然后 同一进程中的多
  • C Shell:重定向和管道工作,但不是输入和输出重定向与 1 个或多个管道的组合

    我的 C shell 可以成功处理重定向 例如 ls al gt output txt pre 输出 txt 尽管 pre 确实成功执行 但从未生成任何输出文件 pre 是一个可执行文件 可以打印 GPA 超过 3 0 的姓名 sort 是
  • 哪些枚举值在 C++14 中是未定义行为,为什么?

    标准中的脚注暗示任何枚举表达式值都是已定义的行为 为什么 Clang 的未定义行为清理程序会标记超出范围的值 考虑以下程序 enum A B 3 C 7 int main A d static cast a 8 return d B 下的输
  • Automapper:如何不重复从复杂类型到基类的映射配置

    我有一堆继承于此的 DTO 类CardBase base class public class CardBase public int TransId get set public string UserId get set public
  • $provide.decorator $controller return throw undefined 不是函数 angularjs

    我想在通过视图加载控制器时添加动态控制器的脚本 这是我的文件树 索引 html app js views 产品 html cat html controllers prod js cat js 我希望当用户得到 prod 应用程序将加载 在
  • Android imeOptions 更改编程

    我有两个基于单选按钮更改事件的 EditText txtPassword txtEmail 我只是隐藏和显示 txtPassword 字段 我只想用编程方式更改 ImeOptions 因为我编写了以下代码 txtPassword setIm
  • 在Python中计算加权成对距离矩阵

    我试图找到在 Python 中执行以下成对距离计算的最快方法 我想用距离来排名list of objects通过他们的相似性 中的每一项list of objects其特征在于四个测量值 a b c d 它们是在非常不同的尺度上进行的 例如
  • OpenCL 标头包含与 C++ 中的相对路径问题

    我正在尝试在 Eclipse CTD 上运行 OpenCL C 示例 该示例 在 Mac 上 包含 OpenCL 标头 如下所示 include
  • docker-compose 中的 Redis:有什么方法可以指定 redis.conf 文件吗?

    我的 Redis 容器在 docker compose yml 中被定义为标准映像 redis image redis ports 6379 我猜它正在使用标准设置 例如在本地主机上绑定到 Redis 我需要将其绑定到0 0 0 0 有什么
  • elasticsearch-查询多个索引是可能的吗?

    我有一个包含 3 个索引的 elasticsearch 集群 users user events visit events register pages page 所以 现在我需要运行处理多个索引的查询 Eg 获取第X页注册用户的性别 要获
  • 返回重复记录

    我只是想从表中返回重复的记录 就我而言 如果多个记录在 col1 col2 col3 和 col4 中具有相同的值 则记录是重复的 SELECT col1 col2 col3 col4 COUNT AS cnt FROM yourTable
  • 在类内部或外部重载运算符有什么区别?

    在C 中 我知道有两种重载方法 我们可以在里面重载它 比如类a 或户外 如课堂b 但是 问题是 这两者在编译时或运行时有什么区别吗 class a public int x a operator a p operator is overlo
  • 当网络过载时QTcpSocket的行为是什么?

    我有一个 QTcpSocket 在一个单独的线程中发送大量数据 其中一些应用程序分布在网络上 如何检测我的网络是否过载并且我的套接字无法再发送任何内容 QTcpSocket 会缓冲所有数据吗 我如何查看正在排队发送的缓冲数据的大小 这会等于
  • 有人尝试过 NetBeans 6.5 Python IDE 吗?

    有没有人尝试过NetBeans 6 5 Python IDE http en wikipedia org wiki NetBeans Other NetBeans IDE Bundles 你有什么意见 比它更好 更差吗PyDev http
  • Rails 为具有多对多关系的模型创建表单

    我有两个模型 Recipe and Tag 有一个has and belongs to many关系 对于这种关系 我有一个简单的连接表 RecipesTags Recipe has and belongs to many tags Tag
  • 流星兼容性

    我正在考虑使用 Meteor 创建我的下一个应用程序 但我之前有一些问题 据我了解 服务器和客户端之间的通信使用DDP协议 WebSockets 哪些浏览器支持 Meteor Meteor通信协议和socket io有什么区别 如果没有区别
  • 如何更改主题选项卡标题的文本颜色?

    再会 我需要更改 TPageControl 中某些 TabSheet 的标题的文本颜色 图片上有类似这样的东西 我知道如何使用 OnDrawTab 来完成它 但如果我启用了 OwnerDraw Windows XP 主题的装饰就会消失 这就