vs 自绘控件--自绘多按钮控件

来源:互联网 发布:手机源码怎么用 编辑:程序博客网 时间:2024/06/10 19:10

最近的项目开发中,同事开发界面时遇到了这样的问题。在一个容器内要同时显示50+的按钮。使用vs控件开发的效果是按钮刷新较慢,肉眼观察有明显的延迟。一开始,想通过在容器内控制控件的重绘来加快刷新速度,未能实现。分析主要原因是,按钮重绘的延迟是因为系统逐个调用了每个按钮的重绘,而这一过程可能涉及到了按钮的其他一些操作,导致整体重绘速度降低。由于知识所限,目前在控件内无法提高刷新速度。经询问,决定使用自定义控件。思路是:在面板上自绘多按钮,并实现其点击响应。绘图部分应用System.Drawing.Graphics的支持,通过自定义事件的引发和响应实现对单个按钮的点击响应。

部分代码如下:

 


{
    public partial class UserControl1 : UserControl //自定义控件类
    {
        #region Members
        private int rowNo = 4; //Button的行数
        private int colNo = 4;//Button的列数
        private int bHeight = 30;//按钮的高
        private int bWidth = 20;//按钮的宽
        private int bBorder = 1;//按钮的边界宽度
        private Size iSize =new Size(120,80);//控件大小

        private String[][] title = null;//每个按钮的文本内容
        private MyButton[][] _buttons = null;//自定义MyButton类的数组,用于引发事件

        //记录鼠标按下的位置。行列,XY

        private int lastR = 4;
        private int lastC = 4;
        private int lastX = 0;
        private int lastY = 0;

        //自定义事件成员

        public event MyButtonEventHandle MyButtonEventHandle;
        #endregion

        #region Properties
        [Description("The no. of rows"),Browsable(true),DisplayName("Row No."),Category("Settings of Button")]
        public int RowNo
        {
            get { return rowNo; }
            set {
                if (value > 1)rowNo = value;
                ButtonHeight = (this.Height-2) / rowNo;
            }
        }

        [Description("The no. of columns"), Browsable(true), DisplayName("Col. No."), Category("Settings of Button")]
        public int ColNo
        {
            get { return colNo; }
            set {
                if (value > 1)colNo = value;
                ButtonWidth = (this.Width-2) / colNo;
            }
        }

        [Description("height of button"), Browsable(true), DisplayName("ButtomHeight"), Category("Settings of Button")]
        public int ButtonHeight
        {
            get { return bHeight; }
            set {
                if (value > 1)bHeight = value;
                if (ButtonHeight * RowNo+2 != Size.Height)
                {
                    this.Height = ButtonHeight * RowNo+2;
                    this.Size = new Size(this.Size.Width, ButtonHeight * RowNo+2);
                }
            }
        }

        [Description("Width of button"), Browsable(true), DisplayName("ButtomWidth"), Category("Settings of Button")]
        public int ButtonWidth
        {
            get { return bWidth; }
            set {
                if (value > 1)bWidth = value;
                if (ButtonWidth * ColNo+2 != Size.Width)
                {
                    this.Width = ButtonWidth * ColNo+2;
                    this.Size = new Size(ButtonWidth * ColNo+2, this.Size.Height);
                }
            }
        }

        [Description("Width of button"), Browsable(true), DisplayName("ButtomBorder"), Category("Settings of Button")]
        public int ButtonBorder
        {
            get { return bBorder; }
            set { if (value > 0 && value < bWidth && value < bHeight)bBorder = value; }
        }

        public new Size Size
        {
            get {
                iSize = base.Size;
                return iSize;
            }
            set {
                iSize = value;
                base.Size = iSize;
                if ((Size.Width-2) / ColNo != ButtonWidth || (Size.Height-2) / RowNo != ButtonHeight)
                {
                    ButtonHeight = (Size.Height-2) / RowNo;
                    ButtonWidth = (Size.Width-2) / ColNo;
                }
            }
        }

        public string[][] Title
        {
            set { if(value.Length < (rowNo*colNo) || value.Length > 0)title = value; }
        }
        #endregion

        public UserControl1()//构造函数
        {
            InitializeComponent();
        }


        protected override void OnLoad(EventArgs e)//控件OnLoad事件响应
        {
            base.OnLoad(e);
        }
        protected override void OnPaint(PaintEventArgs e)//绘制控件
        {
            base.OnPaint(e);         
            _buttons = new MyButton[rowNo][];
            for (int i = 0; i < rowNo; i++)
            {
                _buttons[i] = new MyButton[colNo];
                for (int j = 0; j < colNo; j++)
                {

                    // Declare and instantiate a new pen.
                    Pen lightSide = new Pen(Color.White);
                    Pen darkSide = new Pen(Color.Black);

                    //设定初始按钮坐标
                    Point pos1 = new Point(j*ButtonWidth+1,i*ButtonHeight+1);
                    Point pos2 = new Point(j*ButtonWidth+1+ButtonWidth-ButtonBorder,i*ButtonHeight+1);
                    Point pos3 = new Point(j * ButtonWidth + 1, i * ButtonHeight + 1 + ButtonHeight - ButtonBorder);
                    Point pos4 = new Point(j * ButtonWidth + 1 + ButtonWidth - ButtonBorder, i * ButtonHeight + 1 + ButtonHeight - ButtonBorder);
                    Size size = new Size(ButtonWidth - ButtonBorder, ButtonHeight-ButtonBorder);

                    //绘制按钮
                    e.Graphics.DrawLine(lightSide, pos1, pos2);
                    e.Graphics.DrawLine(lightSide, pos1, pos3);
                    e.Graphics.DrawLine(darkSide, pos2, pos4);
                    e.Graphics.DrawLine(darkSide, pos3, pos4);

                    //绘制按钮文本
                    if (title == null)
                    {
                        e.Graphics.DrawString(i + "," + j, new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos1);
                        _buttons[i][j] = new MyButton(i, j, i + "," + j);
                    }
                    else {
                        e.Graphics.DrawString(title[i][j].ToString(), new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos1);
                        _buttons[i][j] = new MyButton(i, j, title[i][j].ToString());
                    }
                }
            }           
        }

        private void Do_Down(Object sender, MouseEventArgs e)//响应鼠标按下事件
        {
            int x,y,inx,iny;
            x = e.X;
            y = e.Y;
            inx = x % (bWidth-bBorder);
            iny = y % (bHeight-bBorder);
            lastX = x / bWidth;
            lastY = y / bHeight;
            if (inx < bWidth && iny < bHeight && lastX < colNo && lastY < rowNo)
            {
                System.Drawing.Pen myPen = new System.Drawing.Pen(Color.Black);
                Point pos1 = new Point(lastX * bWidth + 1, lastY * bHeight + 1);
                Point pos2 = new Point(lastX * bWidth + 3, lastY * bHeight + 3);
                Point pos3 = new Point(lastX * ButtonWidth + 1 + ButtonWidth - ButtonBorder, lastY * ButtonHeight + 1);
                Point pos4 = new Point(lastX * ButtonWidth + 1, lastY * ButtonHeight + 1 + ButtonHeight - ButtonBorder);
                   
                Size size = new Size(bWidth - bBorder + 2, bHeight - bBorder + 2);
                Graphics a = this.CreateGraphics();
                a.DrawLine(myPen, pos1, pos3);
                a.DrawLine(myPen, pos1, pos4);
                for (int pointX = (lastX * bWidth + 6); pointX < (lastX * bWidth + 1 + ButtonWidth - ButtonBorder - 2); pointX += 2)
                {
                    a.DrawLine(myPen, pointX, lastY * bHeight + 2, pointX + 1, lastY * bHeight + 3);
                    a.DrawLine(myPen, pointX, lastY * bHeight + bHeight - 3 - ButtonBorder, pointX + 1, lastY * bHeight + bHeight -1 - ButtonBorder);
                }
                for (int pointY = (lastY * bHeight + 6); pointY < (lastY * bHeight + 1 + ButtonHeight - ButtonBorder - 2); pointY += 2)
                {
                    a.DrawLine(myPen, lastX * bWidth + 2, pointY, lastX * bWidth + 3, pointY+1);
                    a.DrawLine(myPen, lastX * bWidth -2 - ButtonBorder + bWidth, pointY, lastX * bWidth - ButtonBorder + bWidth-1, pointY + 1);
                }
               
                if (title == null)
                    {
                        a.DrawString(lastY + "," + lastX, new Font(FontFamily.GenericSerif, 9.0f), new SolidBrush(this.BackColor), pos1);
                        a.DrawString(lastY + "," + lastX, new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos2);
                    }
                    else
                    {
                        a.DrawString(title[lastY][lastX].ToString(), new Font(FontFamily.GenericSerif, 9.0f), new SolidBrush(this.BackColor), pos1);
                        a.DrawString(title[lastY][lastX].ToString(), new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos2);
                    }
                lastC = lastX;
                lastR = lastY;
            }
            else { }
        }
        private void Do_Up(Object sender, MouseEventArgs e)//响应鼠标松开事件
        {
            if (lastR < rowNo && lastC < colNo)
            {
                System.Drawing.Pen myPen = new System.Drawing.Pen(this.BackColor);
                Pen lightSide = new Pen(Color.White);
                Point pos1 = new Point(lastX * bWidth + 1, lastY * bHeight + 1);
                Point pos2 = new Point(lastX * bWidth + 3, lastY * bHeight + 3);
                Point pos3 = new Point(lastX * ButtonWidth + 1 + ButtonWidth - ButtonBorder, lastY * ButtonHeight + 1);
                Point pos4 = new Point(lastX * ButtonWidth + 1, lastY * ButtonHeight + 1 + ButtonHeight - ButtonBorder);
                   
                Size size = new Size(bWidth - bBorder + 2, bHeight - bBorder + 2);
                Graphics a = this.CreateGraphics();
                string _buttonText = null;

                a.DrawLine(lightSide, pos1, pos3);
                a.DrawLine(lightSide, pos1, pos4);
                for (int pointX = (lastX * bWidth + 6); pointX < (lastX * bWidth + 1 + ButtonWidth - ButtonBorder - 2); pointX += 2)
                {
                    a.DrawLine(myPen, pointX, lastY * bHeight + 2, pointX + 1, lastY * bHeight + 3);
                    a.DrawLine(myPen, pointX, lastY * bHeight + bHeight - 3 - ButtonBorder, pointX + 1, lastY * bHeight + bHeight - 1 - ButtonBorder);
                }
                for (int pointY = (lastY * bHeight + 6); pointY < (lastY * bHeight + 1 + ButtonHeight - ButtonBorder - 2); pointY += 2)
                {
                    a.DrawLine(myPen, lastX * bWidth + 2, pointY, lastX * bWidth + 3, pointY + 1);
                    a.DrawLine(myPen, lastX * bWidth - 2 - ButtonBorder + bWidth, pointY, lastX * bWidth - ButtonBorder + bWidth - 1, pointY + 1);
                }
                if (title == null)
                {
                    a.DrawString(lastY + "," + lastX, new Font(FontFamily.GenericSerif, 9.0f), new SolidBrush(this.BackColor), pos2);
                    a.DrawString(lastY + "," + lastX, new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos1);
                    _buttonText = lastR.ToString()+","+lastC.ToString();
                }
                else
                {
                    a.DrawString(title[lastY][lastX].ToString(), new Font(FontFamily.GenericSerif, 9.0f), new SolidBrush(this.BackColor), pos2);
                    a.DrawString(title[lastY][lastX].ToString(), new Font(FontFamily.GenericSerif, 9.0f), Brushes.Blue, pos1);
                    _buttonText = title[lastY][lastX];
                }

                //引发自定义事件
                MyButtonClickEventArgs _newEvent = new MyButtonClickEventArgs(_buttons[lastR][lastC]);
                OnClick(_newEvent);
            }
            else { }
        }
        public Point GetButtonIndex()
        {
            Point index = new Point(lastR, lastC);
            return index;
        }
        protected virtual void OnClick(MyButtonClickEventArgs e)
        {

            //调用委托的函数相应事件
            if (MyButtonEventHandle != null)
                MyButtonEventHandle(this, e);
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            PaintEventArgs pe = new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle);
            this.RaisePaintEvent(this, pe);
        }
    }

    //定义自定义事件的EventHandle。相当于声明了方法变量。

    public delegate void MyButtonEventHandle(object sender, MyButtonClickEventArgs args);

 

    //自定义按钮事件

    public  class MyButtonClickEventArgs : EventArgs
    {
        private readonly MyButton _button;

        public MyButtonClickEventArgs(MyButton button)
        {
            _button = button;
        }

        public MyButton OnClickButton
        {
            get { return _button; }
        }       
    }

 

    //自定义类MyButton,作为自定义事件的属性类型。

    public class MyButton
    {
        private readonly int _row = -1;
        private readonly int _col = -1;
        private readonly string _buttontext = null;

        public MyButton(int row, int col, string text)
        {
            _buttontext = text;
            _row = row;
            _col = col;
        }

        public int Row
        {
            get { return _row; }
        }

        public int Col
        {
            get { return _col; }
        }

        public string ButtonText
        {
            get { return _buttontext; }
        }
    }
}