现在我有一个自定义控件,我把这个自定义控件作为画布,然后在这个画布上添加各种控件,添加上的控件可以拖动和改变大小,当我把一个添加上的控件移动的时候,整个画布都重绘了,几个控件的时候还没什么感觉,但是控件多的时候就会出现卡了,已经使用了双缓冲,今天在网上看到了一篇文章,是关于局部刷新的,但只是简单的说了下,求大神给思路或者上点源码。

解决方案 »

  1.   

    局部刷新也是刷新移动的距离,由于不能确定移动多少距离,也就无法确定到底要局部刷新多少范围,不理想,另外一个控件上放N个控件还外带paint更不理想,建议用临时图片双缓存,或者把要拖动的控件等用绘制来代替,控件事件自行在鼠标事件中编写.
      

  2.   

    C# 这方面功能有限,建议去C++/C哪里问
      

  3.   

    给你个思路:先记录控件所在位置RECT,在控件的Move事件里:把现在的RECT跟原来的RECT得到一个大的矩形,有如:
    UniteBox.minX = min(OldBox.minX, NewBox.minX);
    UniteBox.minY = min(OldBox.minY, NewBox.minY);
    UniteBox.maxX = max(OldBox.maxX, NewBox.maxX);
    UniteBox.maxY = max(OldBox.maxY, NewBox.maxY);最后刷新这个大的矩形框!
      

  4.   

    通常情况下,我们使用Refresh,那么就是全局刷新,这样很影响效率。
    要实现局部刷新,我们就必须调用OnPaint方法,但是局部刷新怎么办?那就要用到区域的失效,我们迫使窗体的一个区域失效(Invalidate(Region或者Rectangle),调用系统的OnPaint,系统就会刷新失效的区域。这样就可以做到局部刷新了。
    一般情况下,如果你调用了invalidate方法,系统会在满足条件的情况下刷新区域,但是我们也可以强制进行调用OnPaint函数,就是this.Uptate();
    你试试
     public partial class Form1 : Form
        {
            Rectangle rect1;
            Rectangle rect2;
            Rectangle rect3;
            Timer timer;
            public Form1()
            {
                InitializeComponent();
                rect1 = new Rectangle(10, 10, 200, 20);
                rect2 = new Rectangle(350, 50, 100, 20);
                rect3 = new Rectangle(10, 70, 50, 50);
                timer = new Timer();
                timer.Enabled = true;
                timer.Interval = 500;
                timer.Tick += new EventHandler(Timer_Tick);
                
            }
    private void Timer_Tick(object sender, EventArgs e)
            {
                Graphics g = this.CreateGraphics();
                draw(g);           
            }
            private void draw(Graphics g)
            {
                g.SetClip(this.ClientRectangle);
                int value = new Random().Next(1, 4);
                switch (value)
                {
                    case 1: this.Invalidate(rect1); /*refreshRect1(g);*/ toolStripStatusLabel1.Text = "Rect1"; break;
                    case 2: this.Invalidate(rect2);/* refreshRect2(g);*/ toolStripStatusLabel1.Text = "Rect2"; break;
                    case 3: this.Invalidate(rect3); /*refreshRect3(g);*/ toolStripStatusLabel1.Text = "Rect3"; break;
                }
                this.Update();
            }
            private void refreshRect1(Graphics g)
            {
                Color[] _colors = new Color[] { Color.Red, Color.Blue,
                    Color.Yellow, Color.Tomato, Color.RosyBrown };
                Random r = new Random();
                int i= r.Next(0, 5);
                g.SetClip(rect1, System.Drawing.Drawing2D.CombineMode.Replace);
                g.FillRectangle(new SolidBrush(_colors[i]), rect1);
            }
            private void refreshRect2(Graphics g)
            {
                g.SetClip(rect2, System.Drawing.Drawing2D.CombineMode.Replace);
                g.FillRectangle(Brushes.White, rect2);
                g.DrawString(DateTime.Now.ToString("HH:mm:ss"), Font, Brushes.RosyBrown, rect2);
                
                
            }
            private void refreshRect3(Graphics g)
            {
                g.SetClip(rect3, System.Drawing.Drawing2D.CombineMode.Replace);
                g.FillRectangle(Brushes.White, rect3);
                g.TranslateTransform(25, 90);
                int i = new Random().Next(0, 360);
                g.RotateTransform(i);
                g.DrawLines(Pens.Brown, new Point[] { new Point(0, -20), new Point(-17, 10),new Point(17,0),new Point(0,-20)});
                
                
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                Graphics g = e.Graphics;
                refreshRect1(g);
                refreshRect2(g);
                refreshRect3(g);
            }
    希望对你有用。