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
原创粉丝点击