Files

287 lines
9.6 KiB
C#
Raw Permalink Normal View History

2026-09-09 18:42:38 +08:00
using AntdUI.Theme;
using AntdUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace JinYuan.ControlLib
{
public partial class CustomComboBox : ComboBox
{
private Color darkBackColor = Color.FromArgb(30, 30, 30);
private Color lightBackColor = Color.White;
private Color darkForeColor = Color.White;
private Color lightForeColor = Color.Black;
private Color darkBorderColor = Color.FromArgb(64, 64, 64);
private Color lightBorderColor = Color.FromArgb(217, 217, 217);
private Color darkArrowColor = Color.White;
private Color lightArrowColor = Color.Black;
private Color darkWatermarkColor = Color.Gray;
private Color lightWatermarkColor = Color.LightGray;
private string watermarkText = string.Empty;
[Category("行为")]
public string WatermarkText
{
get { return watermarkText; }
set
{
watermarkText = value;
Invalidate();
}
}
private int cornerRadius = 5; // 新增:控制圆角半径的字段
[Category("外观")]
[DefaultValue(5)]
public int CornerRadius
{
get { return cornerRadius; }
set
{
if (cornerRadius != value)
{
cornerRadius = value;
Invalidate();
}
}
}
public CustomComboBox()
{
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
DrawMode = DrawMode.OwnerDrawFixed;
DropDownStyle = ComboBoxStyle.DropDownList;
UpdateTheme(Config.IsDark);
}
public void UpdateTheme(bool isDark)
{
BackColor = isDark ? darkBackColor : lightBackColor;
ForeColor = isDark ? darkForeColor : lightForeColor;
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
using (var path = CreateRoundedRectangle(new Rectangle(0, 0, Width - 1, Height - 1), cornerRadius))
{
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
var rect = new Rectangle(0, 0, Width - 1, Height - 1);
var borderColor = Config.IsDark ? darkBorderColor : lightBorderColor;
var arrowColor = Config.IsDark ? darkArrowColor : lightArrowColor;
// Draw background
using (var brush = new SolidBrush(BackColor))
{
g.FillPath(brush, path);
}
// Draw border
using (var pen = new Pen(borderColor))
{
g.DrawPath(pen, path);
}
// Draw text or watermark
var textRect = new Rectangle(cornerRadius, 2, Width - 20 - cornerRadius, Height - 4);
var flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
if (SelectedItem != null)
{
string displayText = GetCustomItemText(SelectedItem);
using (var brush = new SolidBrush(ForeColor))
{
TextRenderer.DrawText(g, displayText, Font, textRect, ForeColor, flags);
}
}
else if (!string.IsNullOrEmpty(watermarkText))
{
var watermarkColor = Config.IsDark ? darkWatermarkColor : lightWatermarkColor;
TextRenderer.DrawText(g, watermarkText, Font, textRect, watermarkColor, flags);
}
// Draw arrow
var arrowSize = 8;
var arrowRect = new Rectangle(Width - arrowSize - 8 - cornerRadius, (Height - arrowSize) / 2, arrowSize, arrowSize);
using (var brush = new SolidBrush(arrowColor))
{
Point[] arrow = {
new Point(arrowRect.Left, arrowRect.Top),
new Point(arrowRect.Right, arrowRect.Top),
new Point(arrowRect.Left + arrowRect.Width / 2, arrowRect.Bottom)
};
g.FillPolygon(brush, arrow);
}
}
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (e.Index < 0) return;
// 设置下拉项的背景色
Color backColor;
Color textColor;
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
// 选中项的颜色
backColor = Config.IsDark ? Color.FromArgb(45, 45, 45) : Color.FromArgb(230, 230, 230);
textColor = Config.IsDark ? darkForeColor : lightForeColor;
}
else
{
// 未选中项的颜色
backColor = Config.IsDark ? darkBackColor : lightBackColor;
textColor = Config.IsDark ? darkForeColor : lightForeColor;
}
// 使用新的背景色绘制背景
using (var backBrush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(backBrush, e.Bounds);
}
// 绘制文本
if (e.Index >= 0)
{
string itemText = GetCustomItemText(Items[e.Index]);
// 设置文本边距
Rectangle textBounds = new Rectangle(
e.Bounds.X + 5, // 左边距
e.Bounds.Y,
e.Bounds.Width - 10, // 右边距
e.Bounds.Height
);
// 使用TextRenderer绘制文本以获得更好的文本渲染效果
TextRenderer.DrawText(
e.Graphics,
itemText,
Font,
textBounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left
);
}
// 如果有焦点,绘制焦点矩形
if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
{
using (Pen focusPen = new Pen(Config.IsDark ? Color.FromArgb(70, 70, 70) : Color.FromArgb(180, 180, 180)))
{
e.Graphics.DrawRectangle(focusPen, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1));
}
}
}
// 添加这个方法来处理下拉列表的外观
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == 0x204E) // WM_CTLCOLORLISTBOX
{
// 获取下拉列表的句柄
var hDC = m.WParam;
var hListBox = m.LParam;
using (Graphics g = Graphics.FromHdc(hDC))
{
// 设置下拉列表的背景色
using (SolidBrush backBrush = new SolidBrush(Config.IsDark ? darkBackColor : lightBackColor))
{
g.FillRectangle(backBrush, this.DropDownRectangle);
}
}
}
base.WndProc(ref m);
}
// 获取下拉列表的矩形区域
private Rectangle DropDownRectangle
{
get
{
return new Rectangle(0, 0, DropDownWidth, ItemHeight * Math.Max(Items.Count, 1));
}
}
private string GetCustomItemText(object item)
{
if (item == null)
return string.Empty;
if (string.IsNullOrEmpty(DisplayMember))
return item.ToString();
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(item).Find(DisplayMember, true);
if (descriptor != null)
return descriptor.GetValue(item)?.ToString() ?? string.Empty;
return item.ToString();
}
public object GetSelectedValue()
{
if (SelectedItem == null)
return null;
if (string.IsNullOrEmpty(ValueMember))
return SelectedItem;
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(SelectedItem).Find(ValueMember, true);
if (descriptor != null)
return descriptor.GetValue(SelectedItem);
return null;
}
private GraphicsPath CreateRoundedRectangle(Rectangle bounds, int radius)
{
int diameter = radius * 2;
Size size = new Size(diameter, diameter);
Rectangle arc = new Rectangle(bounds.Location, size);
GraphicsPath path = new GraphicsPath();
if (radius == 0)
{
path.AddRectangle(bounds);
return path;
}
// 左上角
path.AddArc(arc, 180, 90);
// 右上角
arc.X = bounds.Right - diameter;
path.AddArc(arc, 270, 90);
// 右下角
arc.Y = bounds.Bottom - diameter;
path.AddArc(arc, 0, 90);
// 左下角
arc.X = bounds.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
return path;
}
}
}