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

C# 自繪水晶按鈕控制項:漸層、陰影與動態光澤效果實作

     編輯:關於C語言

控制項架構

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

public class CrystalButton : Button {
    private bool isPressed = false;
    private bool isMouseOver = false;
    private Color baseBackColor;

    public CrystalButton() {
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | 
                 ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
        baseBackColor = Color.FromArgb(
            Math.Min(BackColor.R + 0x22, 255),
            Math.Min(BackColor.G + 0x22, 255),
            Math.Min(BackColor.B + 0x22, 255));
    }

幾何路徑:圓角矩形

protected GraphicsPath GetRoundRectPath(Rectangle rect) {
    GraphicsPath path = new GraphicsPath();
    if (rect.Width <= 0) rect.Width = 1;
    if (rect.Height <= 0) rect.Height = 1;
    int radius = rect.Height;
    path.AddArc(rect.Left, rect.Top, radius, radius, 90, 180);
    path.AddArc(rect.Right - radius, rect.Top, radius, radius, 270, 180);
    path.CloseFigure();
    return path;
}

protected GraphicsPath GetHighlightPath(Rectangle rect) {
    GraphicsPath path = new GraphicsPath();
    if (rect.Width <= 0) rect.Width = 1;
    if (rect.Height <= 0) rect.Height = 1;
    int radius = rect.Height;
    path.AddArc(rect.Left, rect.Top, radius, radius, 190, 80);
    path.AddArc(rect.Right - radius, rect.Top, radius, radius, 270, 80);
    path.CloseFigure();
    return path;
}

繪製邏輯:三層疊加

protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    Graphics g = e.Graphics;
    g.SmoothingMode = SmoothingMode.HighQuality;
    g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

    Rectangle rect = ClientRectangle;
    GraphicsPath mainPath = GetRoundRectPath(rect);
    
    // 1. 基底填滿
    g.FillRectangle(new SolidBrush(baseBackColor), rect);
    g.FillPath(new SolidBrush(baseBackColor), mainPath);
    this.Region = new Region(mainPath);  // 點擊區域同步圓角

    // 2. 陰影/立體感(多層漸變疊加)
    DrawShadow(g, isPressed);

    // 3. 高光(垂直線性漸層)
    DrawHighlight(g, isPressed);

    // 4. 文字(按下時下移 4px,滑鼠懸停底線)
    DrawText(g, isPressed);

    // 5. 焦點框
    if (Focused)
        g.DrawPath(new Pen(Color.FromArgb(0x22, Color.White), 3), mainPath);
}

陰影繪製

private void DrawShadow(Graphics g, bool pressed) {
    Rectangle r = ClientRectangle;
    r.Inflate(-r.Width / 10, -r.Height / 4);
    float stepX = r.Width / 100f, stepY = r.Height / 100f;
    r.Y += ClientRectangle.Height / 4;
    if (pressed) r.Y += 4;

    for (int a = 1; a < 33; a++) {
        Rectangle layer = r;
        layer.Inflate(-(int)(stepX * a), -(int)(stepY * a));
        GraphicsPath p = GetRoundRectPath(layer);
        int R = Math.Min(baseBackColor.R + 3 * a, 255);
        int G = Math.Min(baseBackColor.G + 3 * a, 255);
        int B = Math.Min(baseBackColor.B + 3 * a, 255);
        g.FillPath(new SolidBrush(Color.FromArgb(R, G, B)), p);
    }
}

高光繪製

private void DrawHighlight(Graphics g, bool pressed) {
    Rectangle r = ClientRectangle;
    r.Inflate(-4, -4);
    if (pressed) r.Y += 4;
    GraphicsPath p = GetHighlightPath(r);
    RectangleF bounds = p.GetBounds();
    bounds.Height += 1;
    g.FillPath(new LinearGradientBrush(bounds,
        Color.FromArgb(0xFF, Color.White),
        Color.FromArgb(0xFF, baseBackColor),
        LinearGradientMode.Vertical), p);
}

文字繪製

private void DrawText(Graphics g, bool pressed) {
    Rectangle r = ClientRectangle;
    Rectangle r1 = ClientRectangle;
    StringFormat fmt = new StringFormat {
        Alignment = StringAlignment.Center,
        LineAlignment = StringAlignment.Center
    };
    r.Y = ClientRectangle.Height / 5;
    r1.Y = r.Y;
    if (pressed) { r.Y += 4; r1.Y += 4; }

    Font font = isMouseOver ? new Font(Font, FontStyle.Underline) : Font;
    g.DrawString(Text, font, new SolidBrush(Color.FromArgb(0x66, baseBackColor)), r, fmt);  // 陰影字
    g.DrawString(Text, font, new SolidBrush(ForeColor), r1, fmt);  // 主字
}

互動狀態管理

protected override void OnMouseDown(MouseEventArgs e) {
    if (!isPressed) { isPressed = true; Invalidate(); }
    base.OnMouseDown(e);
}

protected override void OnMouseUp(MouseEventArgs e) {
    if (isPressed) { isPressed = false; Invalidate(); }
    base.OnMouseUp(e);
}

protected override void OnMouseEnter(EventArgs e) {
    if (!isMouseOver) { isMouseOver = true; Invalidate(); }
    base.OnMouseEnter(e);
}

protected override void OnMouseLeave(EventArgs e) {
    if (isMouseOver) { isMouseOver = false; Invalidate(); }
    base.OnMouseLeave(e);
}

protected override void OnKeyDown(KeyEventArgs e) {
    if (!isPressed && e.KeyCode == Keys.Space) { isPressed = true; Invalidate(); }
    base.OnKeyDown(e);
}

protected override void OnKeyUp(KeyEventArgs e) {
    if (isPressed && e.KeyCode == Keys.Space) { isPressed = false; Invalidate(); }
    base.OnKeyUp(e);
}

protected override void OnBackColorChanged(EventArgs e) {
    baseBackColor = Color.FromArgb(
        Math.Min(BackColor.R + 0x22, 255),
        Math.Min(BackColor.G + 0x22, 255),
        Math.Min(BackColor.B + 0x22, 255));
    Invalidate();
    base.OnBackColorChanged(e);
}

效果總結

  • 無圖片依賴:純 GDI+ 向量繪製,任意縮放不失真
  • 三態視覺回饋:正常、懸停(底線)、按下(下沉 + 光影變化)
  • 鍵盤無障礙:Space 鍵觸發按下效果
  • 焦點指示:白色半透明外框
  • 自動適應色系:依 BackColor 動態計算陰影/高光色
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved