首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# TabControl 自訂繪製:完整實現選項卡顏色、字型與狀態切換

     編輯:關於C語言

核心概念:OwnerDrawFixed 模式

預設的 TabControl 外觀由系統主題決定,難以滿足品牌色或狀態指示需求。解決關鍵在於將 DrawMode 設為 TabDrawMode.OwnerDrawFixed,並處理 DrawItem 事件,自行繪製每個索引標籤的背景、文字與圖示。

基礎實作:啟用自訂繪製並註冊事件

在表單建構函式或 Load 事件中完成初始化:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler(this.tabControl1_DrawItem);

進階繪製邏輯:區分「選中」與「未選中」狀態

以下範例展示如何為選中索引標籤套用漸層背景與粗體字,未選中則使用純色背景:

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    var tabControl = (TabControl)sender;
    var tabPage = tabControl.TabPages[e.Index];
    var tabRect = tabControl.GetTabRect(e.Index);
    var isSelected = (e.Index == tabControl.SelectedIndex);

    // 1. 定義字型與筆刷
    Font tabFont = isSelected ? new Font(e.Font, FontStyle.Bold) : e.Font;
    Brush backBrush = isSelected
        ? new System.Drawing.Drawing2D.LinearGradientBrush(
            tabRect, SystemColors.ControlLightLight, SystemColors.Control, LinearGradientMode.BackwardDiagonal)
        : new SolidBrush(Color.White);
    Brush foreBrush = isSelected ? Brushes.Black : Brushes.Black; // 可依設計調整

    // 2. 繪製背景
    e.Graphics.FillRectangle(backBrush, tabRect);

    // 3. 計算文字繪製區域(留白 4px 上邊距)
    var textRect = new RectangleF(tabRect.X, tabRect.Y + 4, tabRect.Width, tabRect.Height - 4);
    var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };

    // 4. 繪製文字
    e.Graphics.DrawString(tabPage.Text, tabFont, foreBrush, textRect, sf);

    // 5. 釋放非託管資源
    if (backBrush is IDisposable d) d.Dispose();
    if (tabFont != e.Font) tabFont.Dispose();
}

關鍵細節與優化建議

  • 效能考量: DrawItem 會頻繁觸發,建議將 Font、Brush、StringFormat 等可重用物件提升為欄位或靜態唯讀,避免每次重新分配。
  • 高 DPI 適配: 使用 e.Graphics.DpiX/DpiY 計算縮放比例,或改用 TextRenderer.DrawText 獲得更清銳的文字渲染。
  • 圖示支援: 若 TabPage.ImageIndex 有值,可在繪製文字前呼叫 e.Graphics.DrawImage 繪製圖示,並相應調整 textRect 的 X 座標。
  • 焦點虛線框: 若需保留鍵盤導航的焦點指示,可在 e.State.HasFlag(DrawItemState.Focus) 為 true 時呼叫 ControlPaint.DrawFocusRectangle。

完整範例:含關閉按鈕繪製的進階版本

若需在索引標籤右側顯示關閉圖示(僅當索引標籤數 > 1 時),可擴展如下:

private const int CloseBtnSize = 14;
private readonly Image _closeNormal = Properties.Resources.close_normal;
private readonly Image _closeHover = Properties.Resources.close_hover;

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    // ... 前述背景與文字繪製碼 ...

    // 繪製關閉按鈕(僅多索引標籤時)
    if (tabControl.TabCount > 1)
    {
        var btnRect = new Rectangle(
            tabRect.Right - CloseBtnSize - 4,
            tabRect.Y + (tabRect.Height - CloseBtnSize) / 2,
            CloseBtnSize, CloseBtnSize);

        var img = (e.State & DrawItemState.HotLight) == DrawItemState.HotLight ? _closeHover : _closeNormal;
        e.Graphics.DrawImage(img, btnRect);
        // 建議將 btnRect 存入 Tag 或 Dictionary 供 MouseDown/MouseMove 判斷點擊區域
    }
}

總結

掌握 OwnerDrawFixed 與 DrawItem 事件,即可完全掌控 TabControl 的視覺表現。從簡單的顏色切換到複雜的漸層、圖示、關閉按鈕,皆能在統一邏輯中實現,打造符合產品設計語言的專業介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved