C# 绘制多个控件的边框
来源:互联网 发布:模拟软件下载 编辑:程序博客网 时间:2024/05/18 01:03
这几天想绘制一组控件的边框,即:这一组控件默认有一个边框,鼠标移上去之后,边框变亮一点,鼠标点击一下,这组控件的边框就变为高亮状态(同时其他高亮边框的控件组恢复默认边框)。于是自己写了一个类,可以很方便的管理控件(组)的边框变换:控件(组)的大小发生变化时,边框的位置也能随之更新;同时加入了过渡效果,边框的变化是渐变的。这里就分享一下我的代码吧。
使用方法:
例如,上面的窗体界面中需要创建三个边框:
左边的dataGridView_Variables及下面的“刷新”、“提交”按钮button_Refresh、button_Commit分为一组,需要一个边框;
右上方的textBox_Receive及自己绘制的滚动条控件scrollBar_Receive为一组(滚动条紧贴着textBox_Receive的右侧,这里自动隐藏了,所以看不到),需要另外一个边框;
右下方的textBox_Send以及textBox_Send右侧的滚动条控件scrollBar_Send为一组(这个自绘的滚动条控件也自动隐藏了,所以看不到),需要第三个边框。
首先,在主窗体类public partial class MainWindow : Form 中添加一个局部变量:
private ControlBorderManager bordermanager = new ControlBorderManager();
然后,在form_load事件中添加如下初始化代码:
private void MainWindow_Load(object sender, EventArgs e){ bordermanager.AddControlGroup( this, new Control[] { textBox_Receive, scrollBar_Receive }, Color.FromArgb(80, 80, 80), Color.FromArgb(150, 150, 150), Color.FromArgb(41, 204, 41), () => { return new Rectangle( textBox_Receive.Left - 1, textBox_Receive.Top - 1, textBox_Receive.Width + scrollBar_Receive.Width + 1, textBox_Receive.Height + 1 ); }); bordermanager.AddControlGroup( this, new Control[] { textBox_Send, scrollBar_Send }, Color.FromArgb(80, 80, 80), Color.FromArgb(150, 150, 150), Color.FromArgb(41, 204, 41), () => { return new Rectangle( textBox_Send.Left - 1, textBox_Send.Top - 1, textBox_Send.Width + scrollBar_Send.Width + 1, textBox_Send.Height + 1 ); }); bordermanager.AddControlGroup( this, new Control[] { dataGridView_Variables, button_Refresh, button_Commit }, Color.FromArgb(80, 80, 80), Color.FromArgb(150, 150, 150), Color.FromArgb(41, 204, 41), () => { return new Rectangle( dataGridView_Variables.Left - 1, dataGridView_Variables.Top - 1, dataGridView_Variables.Width + 1, dataGridView_Variables.Height + button_Refresh.Height + 1 ); });}
需要传入的参数有:
this指针;
控件组;
默认边框颜色;
鼠标悬停边框颜色;
鼠标点击之后的边框颜色;
计算边框矩形的函数指针,以便于动态计算边框的位置,这样控件大小发生改变,边框的位置也能自动更新。
这样,就可以实现三个控件组的边框变换效果了。同时,边框变换时有过渡效果。
代码:
ControlBorderManager类:(ControlBorderManager.cs)
public class ControlBorderManager { //过渡效果使用的定时器为System.Windows.Forms.Timer,所以无需考虑多线程同步。 private const int FrameCount = 30; //过度动画总帧数 private const int Interval = 10; //帧与帧之间的间隔(毫秒),实际间隔会比设置的间隔略长 public enum State { Default, MouseOn, Focus }; private struct ControlGroup { public Control[] controls; public State state; public State FormerState; public Color DefaultColor; public Color MouseOnColor; public Color FocusColor; public Func<Rectangle> GetBorderRect; } private List<ControlGroup> ControlGroups = new List<ControlGroup>(); private Form form; //窗体是否正在处于拖动改变大小的状态。如果窗体正在改变大小,在OnPaint事件里就不进行边框的绘制, //否则边框会拖出一大片“轨迹”出来。 private bool Resizing = false; public ControlBorderManager() {; } //返回id,以后便可以查询该控件组的状态 public int AddControlGroup( Form FormInstance, //窗体的this Control[] Controls, Color DefaultColor, Color MouseOnColor, Color FocusColor, Func<Rectangle> GetBorderRect //这个函数需要返回一个Rectangle,表示此控件组的边框 ) { ControlGroup group; group.controls = Controls; group.state = State.Default; group.FormerState = State.Default; group.DefaultColor = DefaultColor; group.MouseOnColor = MouseOnColor; group.FocusColor = FocusColor; group.GetBorderRect = GetBorderRect; ControlGroups.Add(group); form = FormInstance; int id = ControlGroups.Count - 1; Action<object, EventArgs> OnMouseEnter = (sender, e) => { if (ControlGroups[id].state == State.Focus) return; ControlGroup newgroup; newgroup.controls = ControlGroups[id].controls; newgroup.FormerState = ControlGroups[id].state; newgroup.state = State.MouseOn; newgroup.DefaultColor = ControlGroups[id].DefaultColor; newgroup.MouseOnColor = ControlGroups[id].MouseOnColor; newgroup.FocusColor = ControlGroups[id].FocusColor; newgroup.GetBorderRect = ControlGroups[id].GetBorderRect; ControlGroups[id] = newgroup; DrawBorder(id); }; Action<object, EventArgs> OnMouseLeave = (sender, e) => { if (ControlGroups[id].state == State.Focus) return; ControlGroup newgroup; newgroup.controls = ControlGroups[id].controls; newgroup.FormerState = ControlGroups[id].state; newgroup.state = State.Default; newgroup.DefaultColor = ControlGroups[id].DefaultColor; newgroup.MouseOnColor = ControlGroups[id].MouseOnColor; newgroup.FocusColor = ControlGroups[id].FocusColor; newgroup.GetBorderRect = ControlGroups[id].GetBorderRect; ControlGroups[id] = newgroup; DrawBorder(id); }; Action<object, MouseEventArgs> OnMouseDown = (sender, e) => { if (ControlGroups[id].state == State.Focus) return; ControlGroup newgroup; newgroup.controls = ControlGroups[id].controls; newgroup.FormerState = ControlGroups[id].state; newgroup.state = State.Focus; newgroup.DefaultColor = ControlGroups[id].DefaultColor; newgroup.MouseOnColor = ControlGroups[id].MouseOnColor; newgroup.FocusColor = ControlGroups[id].FocusColor; newgroup.GetBorderRect = ControlGroups[id].GetBorderRect; ControlGroups[id] = newgroup; DrawBorder(id); ControlGroup newgroup2; for (int i = 0; i < ControlGroups.Count; i++) { if (i == id) continue; newgroup2.controls = ControlGroups[i].controls; newgroup2.FormerState = ControlGroups[i].state; newgroup2.state = State.Default; newgroup2.DefaultColor = ControlGroups[i].DefaultColor; newgroup2.MouseOnColor = ControlGroups[i].MouseOnColor; newgroup2.FocusColor = ControlGroups[i].FocusColor; newgroup2.GetBorderRect = ControlGroups[i].GetBorderRect; ControlGroups[i] = newgroup2; DrawBorder(i); } }; foreach(Control control in Controls) { control.MouseEnter += new EventHandler(OnMouseEnter); control.MouseLeave += new EventHandler(OnMouseLeave); control.MouseDown += new MouseEventHandler(OnMouseDown); } form.Paint += new PaintEventHandler(OnPaint); form.ResizeBegin += new EventHandler((_sender, _e) => { //防止边框拖出一片“轨迹”出来 Resizing = true; form.Refresh(); }); form.ResizeEnd += new EventHandler((_sender, _e) => { //防止边框拖出一片“轨迹”出来 Resizing = false; form.Refresh(); }); return id; } public State GetState(int id) { if (id >= 0 && id < ControlGroups.Count) { return ControlGroups[id].state; } else { return State.Default; } } private void DrawBorder(int id) //绘制边框,有过渡效果。 { Color FormerColor; Color CurrentColor; State CurrentState = ControlGroups[id].state; switch (ControlGroups[id].FormerState) { case State.Default: FormerColor = ControlGroups[id].DefaultColor; break; case State.MouseOn: FormerColor = ControlGroups[id].MouseOnColor; break; case State.Focus: FormerColor = ControlGroups[id].FocusColor; break; default: FormerColor= ControlGroups[id].DefaultColor; break; } switch (ControlGroups[id].state) { case State.Default: CurrentColor = ControlGroups[id].DefaultColor; break; case State.MouseOn: CurrentColor = ControlGroups[id].MouseOnColor; break; case State.Focus: CurrentColor = ControlGroups[id].FocusColor; break; default: CurrentColor = ControlGroups[id].DefaultColor; break; } int n = 0; float Rstep = ((float)CurrentColor.R - (float)FormerColor.R) / (float)FrameCount; float Gstep = ((float)CurrentColor.G - (float)FormerColor.G) / (float)FrameCount; float Bstep = ((float)CurrentColor.B - (float)FormerColor.B) / (float)FrameCount; float R = FormerColor.R; float G = FormerColor.G; float B = FormerColor.B; Rectangle BorderRect = ControlGroups[id].GetBorderRect(); var timer = new System.Windows.Forms.Timer(); timer.Interval = Interval; timer.Tick += new EventHandler((_sender, _e) => { R += Rstep; G += Gstep; B += Bstep; if (n >= FrameCount || ControlGroups[id].state != CurrentState) { //如果已经画完或者状态已经改变 timer.Stop(); timer.Dispose(); return; } Color c = Color.FromArgb((int)R, (int)G, (int)B); Brush b = new SolidBrush(c); form.CreateGraphics().DrawRectangle(new Pen(b), BorderRect); //绘制矩形边框 n++; }); timer.Start(); } private void OnPaint(object sender, PaintEventArgs e) //响应窗体的paint事件。相应Paint事件的时候无需过渡效果。 { if (Resizing) return; Color CurrentColor; Brush b; foreach (ControlGroup group in ControlGroups) { switch (group.state) { case State.Default: CurrentColor = group.DefaultColor; break; case State.MouseOn: CurrentColor = group.MouseOnColor; break; case State.Focus: CurrentColor = group.FocusColor; break; default: CurrentColor = group.DefaultColor; break; } b = new SolidBrush(CurrentColor); e.Graphics.DrawRectangle(new Pen(b), group.GetBorderRect()); //绘制矩形边框 } } }
这个类默认是画矩形边框的,宽度为1。如果想画别的形状的边框(如圆角矩形),或者别的宽度的边框,只需改动其中的两行绘制边框的代码即可。(代码中注释为“绘制徐行边框”的两行)
0 0
- C# 绘制多个控件的边框
- C#绘制Label边框
- C# TableLayoutPanel 绘制边框,防闪屏
- C# GDI+绘制的 使用率图形控件
- Java-SWing:为控件绘制虚线边框
- android 绘制控件圆角边框
- C# Treeview控件绘制
- c# 对窗体绘制圆角边框
- C#如何把控件的边框角画为圆弧
- C#中如何改变DataGridView控件边框颜色的方法
- Winform的Panel绘制边框
- 很好用的panel或者用户控件绘制边框颜色命令
- 控件的边框线
- 控件的边框设置
- 绘制边框
- WM中使用C#自已绘制的一个列表控件
- C#中提高绘制控件时的效率
- Ugui Image控件绘制多个动态图
- 【Java SE】异常处理
- LeetCode:104_Maximum Depth of Binary Tree | 二叉树的最大深度 | Easy
- Android NDK JNI 简单例子1 : Android NDK配置和下载
- 贝叶斯概率
- 使用maoreduce实现一个超级简单的爬虫功能
- C# 绘制多个控件的边框
- 获取手机通讯录联系人
- [菜鸟笔记--Java的进阶之路三]
- springmvc_mybatis中关于图片上传的写法
- 有多少面试可以重来
- git学习心得(一)——如何关联本地库和远程
- 秒杀多线程系列
- maven fastdfs_client.jar找不到问题解决
- Nginx关于连接超时配置的实验