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

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

时间: 2024-10-19 04:28:33

C#-gdi绘图,双缓冲绘图,Paint事件的触发---ShinePans的相关文章

C#-gdi画图,双缓冲画图,Paint事件的触发---ShinePans

在使用gdi技术画图时,有时会发现图形线条不够流畅,或者在改变窗口大小时会闪烁不断的现象.(Use DoubleBuffer to solve it!)                                                                                                                                                                              

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

private void Form5_MouseMove(object sender, MouseEventArgs e) { int intOX = rectDrawArea.X; int intOY = rectDrawArea.Y; rectDrawArea.X = e.X; rectDrawArea.Y = e.Y; Debug.WriteLine(rectDrawArea.ToString()); //Invalidate(); MyDrawFun(); } private void

GDI双缓冲绘图

一.简介 在进行复杂图形绘制时,若直接在屏幕DC上进行绘制,则会出现明显的闪烁.闪烁产生的原因是当绘制的图形较为 复杂时,图形绘制过程中就被刷新到屏幕上,导致结果断断续续地显示出来.双缓冲绘图的原理是在另开辟一块内存用于绘制,当所有绘制工作完成后将内存数据一 次性拷贝到屏幕上. 双缓冲绘图步骤: 创建兼容DC(CreateCompatibleDC) 创建兼容位图(CreateCompatibleBitmap) 将兼容位图选入兼容DC(SelectObject) 在兼容DC中进行绘制工作 将兼容D

C#绘图双缓冲

C#绘图双缓冲 C#双缓冲解释: 简单说就是当我们在进行画图操作时,系统并不是直接把内容呈现到屏幕上,而是先在内存中保存,然后一次性把结果输出来,如果没用双缓冲的话,你会发现在画图过程中屏幕会闪的很厉害,因为后台一直在刷新,而如果等用户画完之后再输出就不会出现这种情况,具体的做法,其实也就是先创建一个位图对象,然后把内容保存在里面,最后把图呈现出来. GDI+的双缓冲问题 一直以来的误区:.net1.1 和 .net 2.0 在处理控件双缓冲上是有区别的. .net 1.1 中,使用:this.

C# - 双缓冲绘图技术

双缓冲绘图,是指先在内存中进行各种绘图操作,在将内存中绘制好的图形取出显示在控件上,这样可以避免窗口闪烁的现象. 根据上述原理,我们可以自行实现双缓冲绘图,示例代码如下: private void Paint() { // tempImage -> 临时位图 // tempGraphics -> 临时位图的绘图对象 // viewGraphics -> 显示控件的绘图对象 using (Bitmap tempImage = new Bitmap(pictureBox1.ClientSiz

VC双缓冲绘图技术介绍

VC双缓冲绘图技术介绍 双缓冲绘图,它是一种基本的图形图像绘图技术.首先,它在内存中创建一个与屏幕绘图区域一致的对象,然后将图形绘制到内存中的这个对象上,最后把这个对象上的图形数据一次性地拷贝并显示到屏幕上.这种技术能够大大地提高绘图的速度,减少卡顿和闪屏的问题. 我们为什么要使用双缓冲技术来进行绘图? 在应用程序开发中,当图像信息数据量很大时,绘图可能需要几秒钟甚至更长的时间,这时,应用程序可能会出现卡顿的现象.另外,如果窗体在响应WM_PAINT消息的同时也要进行复杂的图形处理,那么窗体在重

Qt使用双缓冲绘图时报错:pure virtual method called

这个问题折磨了我将近四个小时. 起始原因是想写一个双缓冲绘图的画板,大概看了一下网上的教程,理解双缓冲绘图的思想后,没有完全参照网上的步骤,想着用自己的思路实现一下.(其实和网上的教程也没有太大差别) 然后就出现问题了,出现问题的关键的代码如下: void MainWindow::Paint() { if(curShape == none) return; int x1 = lastPoint.x(); int y1 = lastPoint.y(); int w = endPoint.x() -

MFC双缓冲绘图解决界面闪烁问题

一:为什么会产生界面闪烁? 解释这个之前,我们需要明白的是在MFC里面绘图的消息响应机制,大概的就是如果我们要在某一个 东西上面绘图,比如对话框,单文档等等,就必须先得到图形DC的句柄(handle),然后在指定句柄的基础上进行图形操作,也就是MFC常用的CDC *DC = this->getDC();其中的this就是你想画图的目标. MFC里在消息响应的过程中,WM_PAINT被转变为OnDraw()(单文档 Single Document)或是OnPaint()(对 话框Dialog)之类

简单的 &quot;双缓冲&quot; 绘图的例子(研究一下)

所谓双缓冲就是先画到内存画布(如: TBitmap), 然后再转帖到目的地. 譬如下面小程序: procedure TForm1.FormCreate(Sender: TObject); begin   Timer1.Interval := 100;   Color := clWhite; end; procedure TForm1.Timer1Timer(Sender: TObject); begin   Canvas.Pen.Color := Random($FFFFFF);   Canva