在使用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事件中绘制窗口

            this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_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);


源码:
                                                                                                                                                                                                             
                                                                                                     
Form1.cs:
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的更多相关文章

  1. C#-gdi绘图,双缓冲绘图,Paint事件的触发

    一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1  绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...

  2. c# GDI画图 双缓冲画图分析

    双缓冲绘图分析  1.Windows 绘图原理  我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...

  3. VC双缓冲画图技术介绍

    双缓冲画图,它是一种主要的图形图像画图技术.首先,它在内存中创建一个与屏幕画图区域一致的对象,然后将图形绘制到内存中的这个对象上,最后把这个对象上的图形数据一次性地拷贝并显示到屏幕上. 这样的技术能够 ...

  4. Win32双缓冲画图原理

    网上有许多文章讲述了如何使用Visual C++程序实现双缓冲,都是用C++面向对象语言写的,可能对很多没有接触过面向对象语言的C语言初学者来说理解起来有些困难,并且有些好心人也只是把源代码贴上去,不 ...

  5. MFC中利用GDI+进行双缓冲作图的有关设置

    这里只是在遇到实际问题的时候提出的一种解决方法,用以处理闪屏问题. 首先要做的是对GDI的一个设置问题: 在应用程序类中添加一个保护权限数据成员 class C...App: {... private ...

  6. WinForm之GDI手动双缓冲技术

    private void button1_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(this.picturebox.Wid ...

  7. GDI+实现双缓冲绘图方法一

    private void Form5_MouseMove(object sender, MouseEventArgs e) { int intOX = rectDrawArea.X; int intO ...

  8. C# GDI+双缓冲技术

    我想有很多搞图形方面的朋友都会用到双缓冲技术的时候,而且有的时候她的确是个头疼的问题.最近我也要用双缓冲技术,程序怎么调试都不合适,当要对图形进行移动时,总是会出现闪烁抖动.在网上找了些资料,说得都不 ...

  9. 简单的GDI+双缓冲的分析与实现

    为什么要使用双缓冲绘制 在进行多图元绘制的时候: 因为是要一个一个画上去,所以每画一个图元,系统就要做一次图形的绘制操作,图形的重绘是很占用资源的,特别当需要重绘的图形数量很多的时候,所造成的消耗就特 ...

随机推荐

  1. 【Cocos2d-X开发学习笔记】第28期:游戏中音乐和音效的使用

    本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010 UI在游戏中占有很重要的地位,但吸引玩家的除了这 ...

  2. Swift - 使用Auto Layout和Size Classes实现页面自适应弹性布局

    在过去只有iphone4的时候,可以在代码里将一个可视单元的位置写死,这样是没问题的,但随着iPhone5,6的发布,屏幕尺寸有了越来越多种可能.这就要求App的UI控件具有在不同屏幕尺寸的设备上具有 ...

  3. OO的ALV隐藏工具栏的form

    OO的ALV隐藏工具栏: ***展示数据 CALL METHOD gr_alvgrid->set_table_for_first_display EXPORTING is_variant = g ...

  4. 如何将自定义标签封装成一个Jar包

    当我们在一个web应用中开发好一些自定义标签的时候,这些自定义标签通常有标签处理器Java类,和一个描述这些标签tld文件,如果我们想在以后别的web工程中还能用上这些标签,可以将这些自定义标签封装在 ...

  5. TCP/IP协议的编写《转载》

    基于HHARM9-EDU的TCP/IP(UDP)协议的实现 原文网址:http://blog.csdn.net/lhj0503/article/details/3323788 摘 要:嵌入式技术的发展 ...

  6. [置顶] window.open()你真的会了吗?

    一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法: window.open(pageURL,name, ...

  7. IE浏览器上传文件时本地路径变成”C:\fakepath\”的问题

    在使用<input id="file_upl" type="file" />控件上传文件时,有时会需要获取文件本地路径展示给客户,这时可以通过这样的 ...

  8. byte为什么要与上0xff(转)

    无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...

  9. bat执行java程序的脚本解析

    使用java执行带Package的class文件java package1.package2.className  或java -cp .  package1.package2.className - ...

  10. A Very Easy Triangle Counting Game

    题意:在圆上取n个点,相邻两个点之间连线,(注意,n和1相邻),然后所有点对(i ,i+2)相连,问能形成的不同的三角形有多少个? 思路:找规律 n=3,cnt=1; n=4,cnt=8; n=5 c ...