曲沐阳吧 关注:3贴子:239
  • 5回复贴,共1

一些关于Invalidate的内容

只看楼主收藏回复

1楼,最近被画图这个搞到死,还是不明白,经过点播才知道Invalidate的机制...


IP属地:北京1楼2011-08-11 15:39回复
    一、Invalidate介绍
    void Invalidate( BOOL bErase = TRUE );
    该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。


    IP属地:北京2楼2011-08-11 15:39
    回复
      二、与UpdateWindow( )的区别
      UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。


      IP属地:北京3楼2011-08-11 15:40
      回复
        示例
        [C#] 下面的示例使用户能够将图像或图像文件拖到窗体上,并使它在放置点显示。每次绘制窗体时,都重写 OnPaint 方法以重新绘制图像;否则图像将保持到下一次重新绘制。DragEnter 事件处理方法决定拖到窗体中的数据的类型,并提供适当的反馈。如果 Image 可以从该数据中创建,则 DragDrop 事件处理方法就会在该窗体上显示此图像。因为 DragEventArgs.X 和 DragEventArgs.Y 值为屏幕坐标,所以示例使用 PointToClient 方法将它们转换成工作区坐标。
        


        IP属地:北京4楼2011-08-11 15:40
        回复
          private Image picture;
          private Point pictureLocation;
          public Form1()
          {
          // Enable drag-and-drop operations and
          // add handlers for DragEnter and DragDrop.
          this.AllowDrop = true;
          this.DragDrop += new DragEventHandler(this.Form1_DragDrop);
          this.DragEnter += new DragEventHandler(this.Form1_DragEnter);
          }
          protected override void OnPaint(PaintEventArgs e)
          {
          // If there is an image and it has a location,
          // paint it when the Form is repainted.
          base.OnPaint(e);
          if(this.picture != null && this.pictureLocation != Point.Empty)
          {
          e.Graphics.DrawImage(this.picture, this.pictureLocation);
          }
          }
          private void Form1_DragDrop(object sender, DragEventArgs e)
          {
          // Handle FileDrop data.
          if(e.Data.GetDataPresent(DataFormats.FileDrop) )
          {
          // Assign the file names to a string array, in
          // case the user has selected multiple files.
          string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
          try
          {
          // Assign the first image to the picture variable.
          this.picture = Image.FromFile(files[0]);
          // Set the picture location equal to the drop point.
          this.pictureLocation = this.PointToClient(new Point(e.X, e.Y) );
          }
          catch(Exception ex)
          {
          MessageBox.Show(ex.Message);
          return;
          }
          }
          // Handle Bitmap data.
          if(e.Data.GetDataPresent(DataFormats.Bitmap) )
          {
          try
          {
          // Create an Image and assign it to the picture variable.
          this.picture = (Image)e.Data.GetData(DataFormats.Bitmap);
          // Set the picture location equal to the drop point.
          this.pictureLocation = this.PointToClient(new Point(e.X, e.Y) );
          }
          catch(Exception ex)
          {
          MessageBox.Show(ex.Message);
          return;
          }
          }
          // Force the form to be redrawn with the image.
          this.Invalidate();
          }
          private void Form1_DragEnter(object sender, DragEventArgs e)
          {
          // If the data is a file or a bitmap, display the copy cursor.
          if (e.Data.GetDataPresent(DataFormats.Bitmap) ||
          e.Data.GetDataPresent(DataFormats.FileDrop) )
          {
          e.Effect = DragDropEffects.Copy;
          }
          else
          {
          e.Effect = DragDropEffects.None;
          }
          }


          IP属地:北京5楼2011-08-11 15:41
          回复
            Control.Invalidate方法:使控件的特定区域无效并向控件发送绘制消息。
            通常情况下,用Invalidate()使区域无效就可触发该控件的重画了,但在一些条件下却没有触发重画.
            例如:
            private void button1_Click(object sender, EventArgs e)
            {
            textBox1.Text = "888";
            textBox1.Invalidate();
            //textBox1.Update();
            // textBox1.Refresh();
            Thread.Sleep(5000);
            textBox1.Text = "999";
            }
            这是由于Thread.Sleep(5000)这一句的存在,textBox1虽然Invalidate()了,但并没有显示"888",而是5秒后直接显示999了.
            得用textBox1.Update();或textBox1.Refresh();才行.
            Control.Update 方法:使控件重绘其工作区内的无效区域。
            Control.Refresh 方法:强制控件使其工作区无效并立即重绘自己和任何子控件;
            等效于将 Invalidate 方法设置为 true 并将该方法与 Update 一起使用。
            那么既然有了Update,为何还要存在Invalidate呢?
            原因是Invalidate有重载的版本例如:Invalidate(Rectangle, Boolean) 使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。还可以使分配给该控件的子控件无效
            其实Invalidate 方法控制绘制或重新绘制的内容。Update 方法才是控制发生绘制或重新绘制的时间(即执行重绘制命名).


            IP属地:北京7楼2011-08-11 16:01
            回复