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对象)的方法?如果没有,那有没有其他的解决方法呢?在线等待!谢谢...
{
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对象)的方法?如果没有,那有没有其他的解决方法呢?在线等待!谢谢...
解决方案 »
- 请教NET的异常问题: FatalExecutionEngineError
- 千分散尽还复来,发贴必高分.........追终为什么..................................................100
- 求助:VS 2005 C# 编写PPC程序时,怎么让光标跳出TextBox,选择控制其它Button控件呢?
- Form1 和 Form2间的传值 怎么做
- 释放资源的问题
- 求助!!!C#中越界问题
- 关于访问浏览器的问题
- 用HTTP访问映射盘问题
- 各位前辈,急求水晶报表打印机CODE128的方法
- 请问C#中"@"号是啥意思?
- C#时间转换问题....
- 请问怎么在C#里用API函数SendMessage来显示标题栏的系统菜单???
public void Invalidate(Rectangle rc);
{
Graphics graphics = this.CreateGraphics();
using(SolidBrush brush = new SolidBrush(this.BackColor))
{
graphics.FillRectangle(brush, rect);
}
}
就是说用Graphics.DrawImage把你的背景图在那个区域画一次就可以了.
用这个重载的方法:
public void DrawImage(Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit);
graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);
{
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,您就清楚我所说的情况了....
{
//先清楚原来的图
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;
}
...
rect = new Rectangle(50, 50, img.Width, img.Height);
graphics.DrawImage(img, rect, rect, GraphicsUnit.Pixel);
...
每次调用方法就先绘制背景图的一部分,然后再绘制新的图片!做一个假象!
可是Graphics绘制图片本来就很耗费资源,加上每次都是两个操作,好现不太现实。
如果我每1秒就要更换图片一次!而且每次的图片都比较大的话,就有可能会把机子拖得很慢。
用双缓冲,假定画布是白色,每次重绘前先把画布绘成白色,然后再绘图.
我做的是鼠标移动图像,每秒不止一次,图像大小是1600*1200 Jpg,原来就是没有限制绘制的次数,太耗CPU了,后来限制每秒绘24次基本上还行
还有就是我发现Invalidate比FillRectangle耗的资源多,所以才用FillRectangle绘画布的
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);
}
}
}
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);
}
}
}
-----------------------
这样的问题还问啊,就是在Paint事件里进行绘制不就可以了!
在我这个窗体的ClientRectangle(客户区)里面布置了N个图片的绘制区域(Rectangle)用来绘制透明背景的PNG矢量图,在这些区域之下还要绘制一个背景图(格式为BMP)!<程序运行的时候>
除了背景图以外!N个绘制区域每秒钟都有可能在变化,显示新的图片。
(注意:显示图片是不规律的,并且不可能在同一时间有两个区域都要显示新图)<举例说明>
在这里为了说明问题!我就拿N个绘制区域里面的其中一个区域来举例一下吧!比如就命名为:r1如果r1区域要显示新的图片,我不可能重绘N个图片区域,这样实在太耗费资源了。所以我只想把r1区域原来的图片清除掉或者变成透明也可以,然后再向r1区域绘制新的图片。而其他的N个区域和背景图都不受到影响,依然的正常显示...详细情况就是这样!表达能力不好!请见谅!希望您们能够理解我的意思...^o^
{
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"));虽然在每次绘制之前,先填充一层透明颜色!可是效果不理想!有时候图片根本不出现,有时候还依然会显示上次的图片的某一部分(残留部分)...
--------------------
这和重绘区域在性能上有什么区别吗?"清除掉"或"透明"不也是太耗费资源吗?
这点我不理解了.
如果这样的程序在性能低一点的机器上跑一转!我想不用多久。机子就会死掉所以我才能想到,某一个区域须要变化的时候就对它单独做处理...
如果有其它的方法,哪个能保证恢复背景且用的资源能少呢?怎么会少了呢?
Graphics.DrawImage(this.BackgroundImage, rect, rect, GraphicsUnit.Pixel);我心想的疑问也跟您一样。所以我只好不断的查阅资料和请教别人
指定要绘制的区域,
image你要自己算,这个image可能是一张图片的局部,也可能是几张重叠图像局部,你只要把这一部分算出来绘到已经有图上就可以了,一层一层的叠起来,不过这种方法控制太复杂了,具体算法你自己考虑吧
g.DrawImage(image, new Rect(0,0,50,50));
就相当于把文字旋转或反转...
C#能不能实现???