当前位置: 首页 > news >正文

winform 折叠Panel(带标题)

原理:通过修改控件高度来折叠

// 当前折叠状态private bool _collapsed;[Description("是否折叠"), Category("Advanced"), DefaultValue(false)]public bool Collapsed{get => _collapsed;set{if (value){_resizing = true;Height = TitleHeight;}else{_resizing = false;Height = _rowHeight;}_collapsed = value;Invalidate();}}

 

 

代码

 [DefaultEvent("Click"), DefaultProperty("Text")][Description("带标题折叠面板控件")]public  class CollapseTitlePanel : Panel{// 标题栏高度private int _titleHeight = 35;[Description("标题栏高度"), Category("Advanced"), DefaultValue(35)]public int TitleHeight{get => _titleHeight;set{if (_titleHeight != value){_titleHeight = Math.Max(19, value);CalcSystemBoxPos();Padding = new Padding(1, _titleHeight, 1, 1);Invalidate();}}}// 标题文字颜色private Color _titleForeColor = Color.White;[DefaultValue(typeof(Color), "White")][Description("标题文字颜色"), Category("Advanced")]public Color TitleForeColor{get => _titleForeColor;set { _titleForeColor = value; Invalidate(); }}// 标题背景色private Color _titleColor = Color.FromArgb(80, 160, 255);[DefaultValue(typeof(Color), "80, 160, 255")][Description("标题背景色"), Category("Advanced")]public Color TitleColor{get => _titleColor;set { _titleColor = value; Invalidate(); }}// 图标颜色private Color _symbolColor = Color.Black;[Description("图标颜色"), Category("Advanced"), DefaultValue(typeof(Color), "White")]public Color SymbolColor{get => _symbolColor;set { _symbolColor = value; Invalidate(); }}// 文字对齐方式private HorizontalAlignment _textAlign = HorizontalAlignment.Center;[DefaultValue(HorizontalAlignment.Center)][Description("文字对齐方向"), Category("Advanced")]public HorizontalAlignment TextAlign{get => _textAlign;set { _textAlign = value; Invalidate(); }}// 标题文字左右边距private int _titleInterval = 10;[DefaultValue(10)][Description("标题文字距边框距离"), Category("Advanced")]public int TitleInterval{get => _titleInterval;set { _titleInterval = value; Invalidate(); }}// 是否显示折叠按钮private bool _showCollapse=true;[Description("是否显示折叠按钮"), Category("Advanced"), DefaultValue(false)]public bool ShowCollapse{get => _showCollapse;set { _showCollapse = value; _showClose = false; Invalidate(); }}// 是否显示关闭按钮private bool _showClose;[Description("是否显示关闭按钮"), Category("Advanced"), DefaultValue(false)]public bool ShowClose{get => _showClose;set { _showClose = value; _showCollapse = false; Invalidate(); }}// 当前折叠状态private bool _collapsed;[Description("是否折叠"), Category("Advanced"), DefaultValue(false)]public bool Collapsed{get => _collapsed;set{if (value){_resizing = true;Height = TitleHeight;}else{_resizing = false;Height = _rowHeight;}_collapsed = value;Invalidate();}}// 折叠状态改变事件public event EventHandler OnCollapsed;// 圆角相关属性(简化版)private int _radius = 0;[Description("圆角大小"), Category("Advanced"), DefaultValue(0)]public int Radius{get => _radius;set { _radius = Math.Max(0, value); Invalidate(); }}private bool _showRadius = false;[Description("是否显示圆角"), Category("Advanced"), DefaultValue(false)]public bool ShowRadius{get => _showRadius;set { _showRadius = value; Invalidate(); }}private UICornerRadiusSides _radiusSides = UICornerRadiusSides.All;[Description("圆角显示位置"), Category("Advanced"), DefaultValue(UICornerRadiusSides.All)]public UICornerRadiusSides RadiusSides{get => _radiusSides;set { _radiusSides = value; Invalidate(); }}// 辅助字段private Rectangle _controlBoxRect;      // 按钮区域private bool _inControlBox;              // 鼠标是否在按钮区域内private int _rowHeight = 180;             // 展开时的高度private bool _resizing;                    // 是否正在折叠/展开(避免记录错误高度)public CollapseTitlePanel(){// 初始化基础属性Padding = new Padding(1, TitleHeight, 1, 1);_rowHeight = Height;CalcSystemBoxPos();// 绑定事件this.VisibleChanged += UITitlePanel_VisibleChanged;}// 计算按钮位置(右上角)private void CalcSystemBoxPos(){//_controlBoxRect = new Rectangle(Width - 6 - 28, TitleHeight / 2 - 14, 28, 28);_controlBoxRect = new Rectangle(0, 0, TitleHeight, TitleHeight);}// 重绘控件protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);Graphics g = e.Graphics;g.SmoothingMode = SmoothingMode.AntiAlias;// 1. 绘制标题背景using (GraphicsPath path = GetTitleFillPath(Radius, TitleHeight))using (SolidBrush titleBrush = new SolidBrush(Enabled ? TitleColor : Color.FromArgb(153, 180, 209))) // 禁用时颜色变灰
         {g.FillPath(titleBrush, path);}// 2. 画标题下方的分隔线(如果内容区存在)if (Height > TitleHeight){using (Pen pen = new Pen(Color.FromArgb(64, 64, 64))){g.DrawLine(pen, 0, TitleHeight, Width, TitleHeight);}}// 3. 绘制标题文字string text = Text;if (!string.IsNullOrEmpty(text)){Rectangle textRect = new Rectangle(_titleInterval,0,Width - _titleInterval * 2 - (ShowCollapse || ShowClose ? 28 : 0),TitleHeight);using (SolidBrush textBrush = new SolidBrush(Enabled ? TitleForeColor : Color.Gray)){StringFormat sf = new StringFormat{Alignment = StringAlignment.Center,LineAlignment = StringAlignment.Center};if (TextAlign == HorizontalAlignment.Left)sf.Alignment = StringAlignment.Near;else if (TextAlign == HorizontalAlignment.Right)sf.Alignment = StringAlignment.Far;g.DrawString(text, Font, textBrush, textRect, sf);}}// 4. 绘制折叠/关闭按钮if (ShowCollapse || ShowClose){// 按钮背景(鼠标悬停时高亮)if (_inControlBox){using (SolidBrush hoverBrush = new SolidBrush(Color.FromArgb(80, Color.White))){if (ShowRadius && _radius > 0){g.FillRoundedRectangle(hoverBrush, _controlBoxRect, 5);}else{g.FillRectangle(hoverBrush, _controlBoxRect);}}}// 绘制图标(使用 Unicode 符号或字体图标,这里用简单的箭头和叉号)string symbol = "";if (ShowCollapse){symbol = Collapsed ? "" : "";  // 向下箭头表示折叠,向上箭头表示展开
             }else if (ShowClose){symbol = "";}if (!string.IsNullOrEmpty(symbol)){using (SolidBrush symbolBrush = new SolidBrush(SymbolColor)){StringFormat sf = new StringFormat{Alignment = StringAlignment.Center,LineAlignment = StringAlignment.Center};//g.DrawString(symbol, new Font("Segoe UI", 12f), symbolBrush, _controlBoxRect, sf);g.DrawString(symbol, new Font("Segoe UI", 12f), symbolBrush, _controlBoxRect, sf);}}}}// 获取标题区域路径(支持圆角)private GraphicsPath GetTitleFillPath(int radius, int height){GraphicsPath path = new GraphicsPath();Rectangle rect = new Rectangle(0, 0, Width, height);if (radius > 0 && ShowRadius){// 判断哪些角需要圆角bool leftTop = (RadiusSides & UICornerRadiusSides.LeftTop) != 0;bool rightTop = (RadiusSides & UICornerRadiusSides.RightTop) != 0;// 标题只需要上边两个角有圆角if (leftTop)path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);elsepath.AddLine(rect.X, rect.Y, rect.X, rect.Y);if (rightTop)path.AddArc(rect.Right - radius, rect.Y, radius, radius, 270, 90);elsepath.AddLine(rect.Right, rect.Y, rect.Right, rect.Y);path.AddLine(rect.Right, rect.Y + height, rect.X, rect.Y + height);path.CloseFigure();}else{// 无圆角,直接画矩形path.AddRectangle(new Rectangle(0, 0, Width, height));}return path;}// 鼠标移动:检测是否进入按钮区域protected override void OnMouseMove(MouseEventArgs e){bool inBox = _controlBoxRect.Contains(e.Location);if (inBox != _inControlBox){_inControlBox = inBox;if (ShowCollapse || ShowClose)Invalidate(_controlBoxRect);}base.OnMouseMove(e);}// 鼠标离开:清除悬停状态protected override void OnMouseLeave(EventArgs e){base.OnMouseLeave(e);_inControlBox = false;Invalidate(_controlBoxRect);}// 鼠标点击:处理折叠和关闭protected override void OnMouseClick(MouseEventArgs e){if (ShowClose && _controlBoxRect.Contains(e.Location)){this.Hide();  // 点击关闭按钮隐藏面板return;}if (ShowCollapse && _controlBoxRect.Contains(e.Location)){Collapsed = !Collapsed;OnCollapsed?.Invoke(this, e);return;}base.OnMouseClick(e);}// 双击标题栏也可折叠/展开protected override void OnMouseDoubleClick(MouseEventArgs e){if (ShowCollapse && e.Y <= TitleHeight){Collapsed = !Collapsed;OnCollapsed?.Invoke(this, e);return;}base.OnMouseDoubleClick(e);}// 尺寸改变时记录展开高度(仅当不是由折叠代码引起时)protected override void OnSizeChanged(EventArgs e){base.OnSizeChanged(e);CalcSystemBoxPos();if (!_resizing){_rowHeight = Height;}}// 可见性变化时调整子控件位置,避免被标题栏覆盖private void UITitlePanel_VisibleChanged(object sender, EventArgs e){foreach (Control control in Controls){if (control.Top < TitleHeight){control.Top = TitleHeight + 1;}}}}// 圆角位置枚举(按位组合)
 [Flags]public enum UICornerRadiusSides{None = 0,LeftTop = 1,RightTop = 2,LeftBottom = 4,RightBottom = 8,All = LeftTop | RightTop | LeftBottom | RightBottom}// 扩展方法:绘制圆角矩形public static class GraphicsExtensions{public static void FillRoundedRectangle(this Graphics g, Brush brush, Rectangle rect, int radius){using (GraphicsPath path = GetRoundedRectPath(rect, radius)){g.FillPath(brush, path);}}private static GraphicsPath GetRoundedRectPath(Rectangle rect, int radius){GraphicsPath path = new GraphicsPath();if (radius <= 0){path.AddRectangle(rect);return path;}int d = radius * 2;path.AddArc(rect.X, rect.Y, d, d, 180, 90);path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90);path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90);path.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90);path.CloseFigure();return path;}}

 

http://www.jsqmd.com/news/457297/

相关文章:

  • 2026苏州装修公司TOP6口碑推荐 别墅装修、新房装修、二手房翻新、办公室装修公司推荐全区域覆盖 - 品牌智鉴榜
  • 成都高新区一般纳税人代账价格:定价逻辑与影响因素深度解析
  • Cursor Pro功能扩展技术突破:开源工具实战指南
  • 如何记笔记
  • 突破百度网盘限速:从45KB/s到8.7MB/s的意外方法
  • 内揵第三《鬼谷子》殷商后裔复国间谍学院教材
  • 3倍效率提升:RePKG重新定义Wallpaper Engine资源处理工作流
  • 计算机毕业设计hadoop+spark+hive考研分数线预测 考研推荐系统 大数据毕业设计(源码+LW文档+PPT+讲解)
  • 5倍效率提升:AI驱动的视频幻灯片智能提取技术全解析
  • 上海劳力士保养价格全解析:2000元到6000元,差在哪? - 时光修表匠
  • 解锁工业通信:QModMaster的全功能ModBus解决方案
  • AI Agent入门指南:AI产品经理的必修,从0到1掌握大模型核心智能体
  • 2026年度深圳车公庙眼镜配镜推荐,讲讲配镜品牌哪家口碑好 - 工业品牌热点
  • dnSpy文档导出完全指南:从问题诊断到高效实践
  • 从0到1打造AI智能体:一位AI产品经理的实战复盘与完整路线图
  • 分析2026年天津靠谱的诚信健身房,知名的健身房品牌企业哪家强 - 工业推荐榜
  • 智能抢购引擎:让技术民主化的京东抢购黑科技
  • 源丰水工污水厂曝气管更换服务性价比高吗,服务区域包括山东等地 - 工业设备
  • AI大模型训练相关参数如何估算?有这一篇就够了
  • 用Javascript实现时间实时,实现‘瘦身’
  • 【探索JAVA之路】:你真的了解 Stream 流吗?
  • 2026年羊绒衫厂家深度测评:基于原料纱线与生产技术的五维战力解析 - 十大品牌推荐
  • 2026年值得推荐的玻璃吸盘车出租公司,宁波舟山哪家性价比高 - mypinpai
  • 佛山GEO优化机构价格贵吗有推荐的吗 - myqiye
  • 个微iPad协议的会话状态同步:Java ConcurrentHashMap分片锁在高并发消息收发中的性能优化
  • 4步解锁多GPU语音识别:企业级实时转写的性能优化方案
  • 2026年天津口碑好的健身房服务排名,含私教,服务联系方式分享 - 工业推荐榜
  • 从抓包数据到Java模型:个微iPad协议的领域驱动设计(DDD)建模实践与代码生成
  • OpenClaw 教程,来看看这12个实战案例
  • 企业微信API接口的OAuth2.0授权流程:Java Spring Security自定义过滤器实现多租户权限隔离