C#-gdi画图,双缓冲画图,Paint事件的触发---ShinePans
在使用gdi技术画图时,有时会发现图形线条不够流畅,或者在改变窗口大小时会闪烁不断的现象.(Use DoubleBuffer to solve it!)
1.线条不流畅:窗口在重绘时自身重绘与图形重绘之间存在时间差,导致二者图像显示不协调
2.改变窗口大小不流畅:重绘时自身背景颜色与图形颜色频繁交替,造成视觉上的闪烁
以下,用四个图形样例解决问题 :贝塞尔曲线,圆形,矩形,不规则图形
思路:首先用Bitmap类的构造方法创建一个位图实例,然后通过调用Graphics类的FromImage方法创建画布对象,最后调用Grapgics类的DrawImage方法来实如今窗口上绘制图形.
public Bitmap(int width,int height); //width 定义位图的宽度 height 定义位图的高度
Bitmap lacalBitmap =new Bitmap(CilentRectangle.Width,CilentRectangle.Height); //创建一个与窗口工作区大小同样的位图实例
public static Graphics FromImage(Image image);// image:Image类的子类的实例引用
Bitmap localBitmap=new Bitmap(CilentRectangle.Width,CilentRectangle.Height) //创建位图实例
public void DrawImage(Image image,int x,int y); // image:要绘制的图像 x:绘制的图像的左上角 x坐标 y:左上角y坐标
Graphics g=e.Graphics;//获取窗口画布
g.DrawImage(localBitmap,0,0); //在窗口中绘制出内存中的图像
实现:因为Paint被 .net隐藏,我们须要在窗口代码中加上自己的Paint事件中绘制窗口
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(388, 325);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.Text = "双缓冲技术画图";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.ResumeLayout(false);
}
this.Paint+=new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D; namespace DoubleBuffer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void Form1_Paint(object sender, PaintEventArgs e)
{
Bitmap localBitmap = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
//创建位图实例
Graphics bitmapGraphics = Graphics.FromImage(localBitmap);
bitmapGraphics.Clear(BackColor);
bitmapGraphics.SmoothingMode = SmoothingMode.AntiAlias;
PaintImage(bitmapGraphics);
Graphics g = e.Graphics;//获取窗口画布
g.DrawImage(localBitmap, 0, 0); //在窗口的画布中绘画出内存中的图像
bitmapGraphics.Dispose();
localBitmap.Dispose();
g.Dispose();
}
private void PaintImage(Graphics g)
{
//画图
GraphicsPath path = new GraphicsPath(new Point[]{ new Point(100,60),new Point(350,200),new Point(105,225),new Point(190,ClientRectangle.Bottom),
new Point(50,ClientRectangle.Bottom),new Point(50,180)}, new byte[]{
(byte)PathPointType.Start,
(byte)PathPointType.Bezier,
(byte)PathPointType.Bezier,
(byte)PathPointType.Bezier,
(byte)PathPointType.Line,
(byte)PathPointType.Line});
PathGradientBrush pgb = new PathGradientBrush(path);
pgb.SurroundColors = new Color[] { Color.Green, Color.Yellow, Color.Red, Color.Blue, Color.Orange, Color.LightBlue };
g.FillPath(pgb, path);
g.DrawString("双缓冲画图", new Font("宋体", 18, FontStyle.Bold), new SolidBrush(Color.Red), new PointF(110, 20));
g.DrawBeziers(new Pen(new SolidBrush(Color.Green),2),new Point[] {new Point(120,100),new Point(120,120),new Point(120,100),new Point(120,150)});
g.DrawArc(new Pen(new SolidBrush(Color.Blue), 5), new Rectangle(new Point(120, 170), new Size(60, 60)), 0, 360);
g.DrawRectangle(new Pen(new SolidBrush(Color.Orange), 3), new Rectangle(new Point(240, 260), new Size(90, 50)));
} }
}
Form1设计:
namespace DoubleBuffer
{
partial class Form1
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理全部正在使用的资源。
/// </summary>
/// <param name="disposing">假设应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
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(388, 325);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.Text = "双缓冲技术画图";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.ResumeLayout(false); } #endregion
}
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms; namespace DoubleBuffer
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
当变化窗口时,会导致图像出现变形,可把窗口属性中的ResizeReDrae 设置为 true
=
C#-gdi画图,双缓冲画图,Paint事件的触发---ShinePans的更多相关文章
- C#-gdi绘图,双缓冲绘图,Paint事件的触发
一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1 绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...
- c# GDI画图 双缓冲画图分析
双缓冲绘图分析 1.Windows 绘图原理 我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...
- VC双缓冲画图技术介绍
双缓冲画图,它是一种主要的图形图像画图技术.首先,它在内存中创建一个与屏幕画图区域一致的对象,然后将图形绘制到内存中的这个对象上,最后把这个对象上的图形数据一次性地拷贝并显示到屏幕上. 这样的技术能够 ...
- Win32双缓冲画图原理
网上有许多文章讲述了如何使用Visual C++程序实现双缓冲,都是用C++面向对象语言写的,可能对很多没有接触过面向对象语言的C语言初学者来说理解起来有些困难,并且有些好心人也只是把源代码贴上去,不 ...
- MFC中利用GDI+进行双缓冲作图的有关设置
这里只是在遇到实际问题的时候提出的一种解决方法,用以处理闪屏问题. 首先要做的是对GDI的一个设置问题: 在应用程序类中添加一个保护权限数据成员 class C...App: {... private ...
- WinForm之GDI手动双缓冲技术
private void button1_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(this.picturebox.Wid ...
- GDI+实现双缓冲绘图方法一
private void Form5_MouseMove(object sender, MouseEventArgs e) { int intOX = rectDrawArea.X; int intO ...
- C# GDI+双缓冲技术
我想有很多搞图形方面的朋友都会用到双缓冲技术的时候,而且有的时候她的确是个头疼的问题.最近我也要用双缓冲技术,程序怎么调试都不合适,当要对图形进行移动时,总是会出现闪烁抖动.在网上找了些资料,说得都不 ...
- 简单的GDI+双缓冲的分析与实现
为什么要使用双缓冲绘制 在进行多图元绘制的时候: 因为是要一个一个画上去,所以每画一个图元,系统就要做一次图形的绘制操作,图形的重绘是很占用资源的,特别当需要重绘的图形数量很多的时候,所造成的消耗就特 ...
随机推荐
- 南京三星面试准备3--数组&基础数据结构
1.用递归颠倒一个栈. void PushToBottom(stack<int> &mystack,int num) { if(mystack.size()==0) { mysta ...
- Matlab图像处理系列2———空间域平滑滤波器
注:本系列来自于图像处理课程实验,用Matlab实现最主要的图像处理算法 本文章是Matlab图像处理系列的第二篇文章.介绍了空间域图像处理最主要的概念----模版和滤波器,给出了均值滤波起和中值滤波 ...
- Linux账号管理(一)
整理自<鸟哥的Linux私房菜>,整理者:华科小涛http://www.cnblogs.com/hust-ghtao/ 管理员的工作中,相当重要的一环就是“管理账号”.因为整个系统都是你在 ...
- VC++ WIN32 sdk实现按钮自绘详解 之二(关键是BS_OWNERDRAW和WM_DRAWITEM)
网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Wi ...
- 发掘ListBox的潜力(二):鼠标拖放插入点提示
鼠标拖放插入点提示 鼠标拖放是Windows常见的操作,比如拷贝文件就可用拖放方式进行.在我们编写的应用程序中,有时为了方便用户操作需要支持鼠标拖放.对于大部分的VCL控件只要鼠标将DragMode设 ...
- 爬虫总结_java
基于webmagic的爬虫项目经验小结 大概在1个月前,利用webmagic做了一个爬虫项目,下面是该项目的一些个人心得,贴在这里备份: 一.为什么选择webmagic? 说实话,开源的爬虫框架已经很 ...
- 手动配置S2SH三大框架报错(一)
十二月 08, 2013 9:24:51 下午 org.apache.catalina.core.AprLifecycleListener init 严重: An incompatible versi ...
- 五种情况下会刷新控件状态(刷新所有子FWinControls的显示)——从DFM读取数据时、新增加子控件时、重新创建当前控件的句柄时、设置父控件时、显示状态被改变时
五种情况下会刷新控件状态(刷新控件状态才能刷新所有子FWinControls的显示): 在TWinControls.PaintControls中,对所有FWinControls只是重绘了边框,而没有整 ...
- Mysql 和Oracle rows 区别
mysql> explain select t1.* from t2 ,t1 where t2.id=t1.id and t2.id<3;\ +----+-------------+--- ...
- HOW TO: How to import UUID function into Postgre 9.3
1. Open a command console and go to the directory where you installed Postgre server. e.g. D:\Progra ...