private void PaintImage(Image img)
{
Graphics graphics = this.CreateGraphics();
graphics.DrawImage(img, new Rectangle(50, 50, img.Width, img.Height));
}PaintImage(Image.FromFile(@"C:\test.png"));通过上面的方法调用,已经成功在窗体上绘制了一张图片,但是我想在每二次调用PaintImage方法的时候,先把第一次绘制的图片清除,再绘制新的图片。请问大家!在不调用窗体方法this.Invalidate()或this.Refresh()的前提下能不能把先前绘制的东西清除掉?我最想知道的是:
Graphics类有没有只清除指定区域(矩形->Rectangle对象)的方法?如果没有,那有没有其他的解决方法呢?在线等待!谢谢...

解决方案 »

  1.   

    Invalidate就可以指定一个Rectangle来便这个区域无效从而引起重绘的:
    public void Invalidate(Rectangle rc);
      

  2.   

    另外你可以用窗体的当前背景建立一个Brush,然后用Graphics.FillRectangle来便指定的区域用指定颜色绘制,从而使原来的图消失.例如:private void clearIamge(Rectangle rect)
    {
    Graphics graphics = this.CreateGraphics();
    using(SolidBrush brush = new SolidBrush(this.BackColor))
    {
    graphics.FillRectangle(brush, rect);
    }
    }
      

  3.   

    TO:hbxtlhx(平民百姓)这方法我用过了!如果使区域无效的话!绘制的图片的时候,图片闪一下就会消失...
      

  4.   

    楼上说的是,graphics.FillRectangle(brushs.white, rect);
      

  5.   

    我试过啦!可是还不能达到规定的要求...事情是这样的!在此之前:我用了Graphics类绘制了一个背景图(占满整个窗体),然后在背景图之上再调用PaintImage方法绘制其他的图形!在这样的情况下,如果用了您所提供的第二种方法的话,会将背景图绘履盖掉的我想保证在不断重履的调用PaintImage方法之后,背景图都不受影响...
      

  6.   

    说清楚啊....你可以把你的窗体的背景图只画一部分来达到清楚图片显示的效果.
    就是说用Graphics.DrawImage把你的背景图在那个区域画一次就可以了.
    用这个重载的方法:
    public void DrawImage(Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit);
      

  7.   

    比如你在Rectangle为(50,50, 100,100)的区域画了一个图,那么,你可以这样来清楚:
    graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);
      

  8.   

    您的意思是这样是吧?private void PaintImage(Image img)
    {
    Graphics graphics = this.CreateGraphics();
    graphics.DrawImage(img, new Rectangle(50, 50, img.Width, img.Height), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
    }这样子也不可以啊!
    或者你可以试试。在背景图之上,重履调用PaintImage方法!如果每一次绘制的图片尺寸为100*100;第二次绘制的图片尺寸为:25*25,您就清楚我所说的情况了....
      

  9.   

    我清楚你的意思,但好像你不清 楚我的意思,或者你可以这样:private void PaintImage(Image img)
    {
    //先清楚原来的图
    Rectangle rect = this.m_Rect;
    Graphics graphics = this.CreateGraphics();
    graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);
    //这里才开始画一下个图.
    rect = new Rectangle(50, 50, img.Width, img.Height);
    graphics.DrawImage(img, rect, new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
    this.m_Rect=rect;
    }
      

  10.   

    改一个句子:
    ...
    rect = new Rectangle(50, 50, img.Width, img.Height);
    graphics.DrawImage(img, rect, rect, GraphicsUnit.Pixel);
    ...
      

  11.   

    这种方式实现的话是可以!
    每次调用方法就先绘制背景图的一部分,然后再绘制新的图片!做一个假象!
    可是Graphics绘制图片本来就很耗费资源,加上每次都是两个操作,好现不太现实。
    如果我每1秒就要更换图片一次!而且每次的图片都比较大的话,就有可能会把机子拖得很慢。
      

  12.   

    如果每1秒更换图片一次已经足够了
    用双缓冲,假定画布是白色,每次重绘前先把画布绘成白色,然后再绘图.
    我做的是鼠标移动图像,每秒不止一次,图像大小是1600*1200 Jpg,原来就是没有限制绘制的次数,太耗CPU了,后来限制每秒绘24次基本上还行
    还有就是我发现Invalidate比FillRectangle耗的资源多,所以才用FillRectangle绘画布的
      

  13.   

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;namespace WindowsApplication1
    {
        public class Form1 : Form
        {        /// <summary>
            /// 必需的设计器变量。
            /// </summary>
            private System.ComponentModel.IContainer components = null;        /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (this.m_Brush != null)
                {
                    this.m_Brush.Dispose();
                    this.m_Brush = null;
                }// end if            if (this.m_objGraphics != null)
                {
                    this.m_objGraphics.Dispose();
                    this.m_objGraphics = null;
                }// end if            if (this.m_Graphics != null)
                {
                    this.m_Graphics.Dispose();
                    this.m_Graphics = null;
                }// end if            if (this.m_arryImage != null)
                {
                    int count = this.m_arryImage.Count;
                    for (int i = 0; i < count; i++)
                    {
                        Image img = (Image)this.m_arryImage[i];
                        img.Dispose();
                        img = null;
                    }// end if
                }// end if            if (this.m_Bitmap != null)
                {
                    this.m_Bitmap.Dispose();
                    this.m_Bitmap = null;
                }// end if
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }        #region Windows 窗体设计器生成的代码        /// <summary>
            /// 设计器支持所需的方法 - 不要
            /// 使用代码编辑器修改此方法的内容。
            /// </summary>
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(292, 273);
                this.Name = "Form1";
                this.Text = "Form1";
                this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
                this.ResumeLayout(false);        }        #endregion        /// <summary>
            /// 保存要绘制的图像
            /// </summary>
            private ArrayList m_arryImage;        /// <summary>
            /// 图像文件夹路径(10张1600*1200,JPG)
            /// </summary>
            private const string IMAGEFILE = @"E:\桌面";        /// <summary>
            /// 内存中的画布
            /// </summary>
            private Bitmap m_Bitmap;        /// <summary>
            /// 画布上的绘画对象
            /// </summary>
            private Graphics m_Graphics;        /// <summary>
            /// 窗体的绘图对象
            /// </summary>
            private Graphics m_objGraphics;        /// <summary>
            /// 笔刷
            /// </summary>
            private SolidBrush m_Brush;        /// <summary>
            /// 画布的大小
            /// </summary>
            private Rectangle m_Rect;        /// <summary>
            /// 要绘制图像的数量
            /// </summary>
            private int m_ImageCount;        public Form1()
            {
                InitializeComponent();
                //提示CreateGraphics()是.Net中可以直接在其它线程中使用的对像(我记得好像就只有4个吧,记不太清了,可以查查MSDN)
                this.m_objGraphics = this.CreateGraphics();
                this.m_Brush = new SolidBrush(Color.White);
            }        protected override void OnLoad(EventArgs e)
            {
                this.m_Rect = new Rectangle(0,0,this.Width, this.Height);
                this.m_Bitmap = new Bitmap(this.Width, this.Height);
                this.m_Graphics = Graphics.FromImage(this.m_Bitmap);
                if (System.IO.Directory.Exists(IMAGEFILE))
                {
                    //获取所有文件
                    string[] Files = System.IO.Directory.GetFiles(IMAGEFILE);                //要绘制的图像
                    this.m_arryImage = new ArrayList();               
                     //获取图像是最慢的
                    for( int i = 0; i < Files.Length ;i++)
                    {
                        if (CheckFileType(Files[i]))
                            this.m_arryImage.Add( Image.FromFile(Files[i]) );
                    }// end foreach                     //要绘制的数量
                    this.m_ImageCount = this.m_arryImage.Count;
                }// end if
                base.OnLoad(e);
            }// end void        /// <summary>
            /// 检查文件的类型
            /// </summary>
            /// <param name="file">完整路径名称</param>
            /// <returns>是否是图像文件</returns>
            private bool CheckFileType( string file )
            {
                bool IsImage = false;
                int index = file.IndexOfAny(new char[] { '.' }) + 1;
                string strType = file.Substring(index, file.Length - index);
                switch (strType.ToLower() )
                {
                    case "jpg":
                        IsImage = true;
                        break;
                }// end switch
                return IsImage;
            }// end void        protected override void OnPaint(PaintEventArgs e)
            {
                DrawImage();
                base.OnPaint(e);
            }// end void        /// <summary>
            /// 每秒绘制一次
            /// </summary>
            private void DrawImage()
            {
                int index = 0;
                //长时间运行的程序最好放到后台线程中执行
                //由于是长时间运行的程序控制上也有点问题,不过用线程可以避免此类问题
                //这里只是做一个示例,其它的自己思考吧            
                while (true)
                {
                    //清除绘图面
                    this.m_Graphics.FillRectangle(this.m_Brush, this.m_Rect);
                    //在画布上绘制图像
                    this.m_Graphics.DrawImage((Image)this.m_arryImage[index], this.m_Rect);
                    //将图像绘制到窗体
                    this.m_objGraphics.DrawImage(this.m_Bitmap, this.m_Rect);                if ( (index + 1) == this.m_ImageCount)
                        index = 0;
                    else
                        index++;                 System.Threading.Thread.Sleep(1000);
                }// end while
            }// end void        protected override void OnSizeChanged(EventArgs e)
            {
                this.m_Rect = new Rectangle(0, 0, this.Width, this.Height);            if (this.m_Graphics != null)
                {
                    this.m_Graphics.Dispose();
                    this.m_Graphics = null;
                }// end if            //更改画布大小
                if (this.m_Bitmap != null)
                {
                    this.m_Bitmap.Dispose();
                    this.m_Bitmap = null;
                }// end if
                this.m_Bitmap = new Bitmap(this.Width, this.Height);
                this.m_Graphics = Graphics.FromImage(this.m_Bitmap);
                base.OnSizeChanged(e);
            }
        }
    }
      

  14.   

    参考下如下的代码(不知道我有没有理解楼主的意思):
    namespace backgroundImage
    {
    public partial class Form1 : Form
    {
    private Image image = Image.FromFile("d:\\a.jpg");
    private Rectangle rect = new Rectangle(10, 10, 100, 100);
    public Form1()
    {
    InitializeComponent();
    } //显示图
    private void button1_Click(object sender, EventArgs e)
    {
    Graphics g = this.CreateGraphics();
    g.DrawImage(image, rect);
    }
    //添空图的显示
    private void button2_Click(object sender, EventArgs e)
    {
    Graphics g = this.CreateGraphics();
    g.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);
    }
    }
    }
      

  15.   

    harvesthouhao() ( ) 信誉:90    Blog 
    -----------------------
    这样的问题还问啊,就是在Paint事件里进行绘制不就可以了!
      

  16.   

    你把我的方法放到窗体的Paint事件里面去,就可以解决这个问题...
      

  17.   

    TO:kmblack1(black) and hbxtlhx(平民百姓)很感谢您们的热心帮忙!<详细原因>
    在我这个窗体的ClientRectangle(客户区)里面布置了N个图片的绘制区域(Rectangle)用来绘制透明背景的PNG矢量图,在这些区域之下还要绘制一个背景图(格式为BMP)!<程序运行的时候>
    除了背景图以外!N个绘制区域每秒钟都有可能在变化,显示新的图片。
    (注意:显示图片是不规律的,并且不可能在同一时间有两个区域都要显示新图)<举例说明>
    在这里为了说明问题!我就拿N个绘制区域里面的其中一个区域来举例一下吧!比如就命名为:r1如果r1区域要显示新的图片,我不可能重绘N个图片区域,这样实在太耗费资源了。所以我只想把r1区域原来的图片清除掉或者变成透明也可以,然后再向r1区域绘制新的图片。而其他的N个区域和背景图都不受到影响,依然的正常显示...详细情况就是这样!表达能力不好!请见谅!希望您们能够理解我的意思...^o^
      

  18.   

    Rectangle r1 = new Rectangle(50, 50, 0, 0)private void PaintImage(Image img)
    {
       Graphics graphics = this.CreateGraphics();
       graphics.FillRectangle(new SolidBrush(Color.Transparent), r1);//填充透明区域
       r1.Size = img.Size;
       graphics.DrawImage(img, r1);
    }PaintImage(Image.FromFile(@"C:\test.png"));虽然在每次绘制之前,先填充一层透明颜色!可是效果不理想!有时候图片根本不出现,有时候还依然会显示上次的图片的某一部分(残留部分)...
      

  19.   

    如果r1区域要显示新的图片,我不可能重绘N个图片区域,这样实在太耗费资源了。所以我只想把r1区域原来的图片清除掉或者变成透明也可以,然后再向r1区域绘制新的图片。
    --------------------
    这和重绘区域在性能上有什么区别吗?"清除掉"或"透明"不也是太耗费资源吗?
    这点我不理解了.
      

  20.   

    如果每次r1区域要显示新图的时候,都要重绘所有的区域包括背影图的话,这样的效率太低了,何况每1秒都有某一个区域在变化...我的机子:内存1G,CPU 3.2都被拖得很慢...
    如果这样的程序在性能低一点的机器上跑一转!我想不用多久。机子就会死掉所以我才能想到,某一个区域须要变化的时候就对它单独做处理...
      

  21.   

    Graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);在这里画的背景图,只会取this.BackgroundImage中的rect指定的数据,并绘制到窗体的rect指定的区域,所用的资源降到了最小,这是按背景恢复的较好的方法了(我认为),
    如果有其它的方法,哪个能保证恢复背景且用的资源能少呢?怎么会少了呢?
      

  22.   

    我知道这行代码的意思!
    Graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);我心想的疑问也跟您一样。所以我只好不断的查阅资料和请教别人
      

  23.   

    明白你的意思了,不绘图肯定是不行的,可以在其它事件中,采取局部绘制的办法,
    指定要绘制的区域,
    image你要自己算,这个image可能是一张图片的局部,也可能是几张重叠图像局部,你只要把这一部分算出来绘到已经有图上就可以了,一层一层的叠起来,不过这种方法控制太复杂了,具体算法你自己考虑吧
    g.DrawImage(image, new Rect(0,0,50,50));
      

  24.   

    MSDN里有个WinCE的游戏编程示例和你说的差不多,是绘制足球移动的,每次就只绘球这一部份,你查一下,好像微软网站上也有
      

  25.   

    http://www.microsoft.com/china/msdn/library/NetFramework/netcompactframework/Vsdnnetcompnetcfgaming.mspx?mfr=true
      

  26.   

    http://www.microsoft.com/china/msdn/library/NetFramework/netcompactframework/Vsdnnetcompnetcfgaming.mspx?mfr=true
      

  27.   

    Graphics类的DrawString方法如何控制文字的方法???
    就相当于把文字旋转或反转...
    C#能不能实现???
      

  28.   

    TO: hbxtlhx and kmblack1 很感谢你们,虽然问题还不能真正的解决掉,但是距离成功也差不多啦谢谢您们给我各个方面的建议...^0^