于双缓冲技术的GDI无闪烁绘图

合集下载

+MFC+GDI双缓冲避免图形闪烁

+MFC+GDI双缓冲避免图形闪烁

// TODO: Add your specialized creation code here SetTimer(1,10,NULL); return 0; } 利用定时器直接进行 10 毫秒的屏幕刷新,这样效果会出现不停的闪烁的情况. 解决方法利用双缓冲,首先触发 WM_ERASEBKGND,然后修改返回 TRUE; 定义变量: CBitmap *m_pBitmapOldBackground ; CBitmap m_bitmapBackground ; CDC m_dcBackground; //绘制背景 if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_h Object == NULL)) {
MemDC.CreateCompatibleDC(NULL); //这时还不能绘图,因为没有地方画 ^_^ //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的 大小 MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight); //将位图选入到内存显示设备中 //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上 CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); //先用背景色将位图清除干净,这里我用的是白色作为背景 //你也可以用自己应该用的颜色 MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255)); //绘图 MemDC.MoveTo(……); MemDC.LineTo(……);
} 说到这里可能又有人要说了 , 为什么一个简单图形看起来没有复杂图形那么闪呢? 这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉 害一些,但是闪烁频率要低。 那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁 是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间的 差异很小所以看起来不闪 。 如果不信 , 可以在动画的每一帧中间加一张纯白的帧 , 不闪才怪呢。 2、如何避免闪烁 在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉 MFC 提 供的背景绘制过程了。实现的方法很多, * 可以在窗口形成时给窗口的注册类的背景刷付 NULL * 也可以在形成以后修改背景 static CBrush brush(RGB(255,0,0)); SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRU SH)brush); * 要简单也可以重载 OnEraseBkgnd(CDC* pDC)直接返回 TRUE. 这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变 得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图 形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存 中绘制好 , 然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去 (这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便 用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为 内存中最终的图形与屏幕显示图形差别很小 (如果没有运动 , 当然就没有差别) , 这样看起来就不会闪。 3、如何实现双缓冲 首先给出实现的程序,然后再解释,同样是在 OnDraw(CDC *pDC)中: CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备

C#环境下GDI+绘图效率研究

C#环境下GDI+绘图效率研究

C#环境下GDI+绘图效率研究作者:温铭毅来源:《中国科技博览》2015年第05期[摘要]本文在简单介绍GDI和GDI+的基础上,指出GDI+在绘制动画时效率不足的劣势,并对三种不同的GDI+动画绘图方式进行了详细的阐述;最后实现了一个GDI+界面绘图程序,比较和验证了三种不同方式的绘图性能。

实验表明,使用双缓冲和bitblt结合的方式,可以有效的解决直接绘制方式的闪烁问题,提高绘图效率。

[关键词]GDI+;动态绘图;双缓冲;bitblt中图分类号:P631.84 文献标识码:A 文章编号:1009-914X(2015)05-0134-011.引言GDI是微软公司的著名的二维图形引擎,GDI+则是微软公司为了提高显示效果而推出的一种新型图形引擎。

GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

GDI+是Windows XP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。

顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。

作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离.从而使开发人员编写设备无关的应用程序变得非常容易。

Microsoft Windows GDI+服务分为以下3个主要部分:(1)二维矢量图形。

矢量图形由图元组成,而图元则由一系列坐标系统的点集组成。

VC中的GDI双缓冲绘图

VC中的GDI双缓冲绘图

CBitmap* m_pOldBmp;
ATL程序中,可在atlgdi.h找到基于ATL程序的内存DC:
class CMemoryDC : public CDC { public: // Data members HDC m_hDCOriginal; RECT m_rcPaint; CBitmap m_bmp; HBITMAP m_hBmpOld; // Constructor/destructor CMemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL) {


双缓冲绘图原理

普通绘图操作
物理DC绘图 操作 屏幕

双缓冲绘图操作
物理DC绘图 操作 屏幕
内存DC
实现过程

1. 2. 3. 4. 5. 6.
创建兼容DC 创建兼容位图 用兼容DC关联兼容位图 使用兼容DC绘图 将兼容DC拷贝到物理DC上 回收兼容位图和兼容DC,防止资源泄露
实现代码
CPaintDC dc(this);
// 绘图区域 CRect rectClient; GetClientRect(&rectClient);
// 创建兼容DC
CDC dcMem; dcMem.CreateCompatibleDC(&dc); // 创建兼容位图,使兼容DC与之关联,否则兼容DC则是一个1*1的单色位图 CBitmap bitmap;
SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top);
} ~CMemoryDC() {
::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY); SelectBitmap(m_hBmpOld);

一种基于自定义剪切区集合的MFC程序GDI绘图优化方法-浙江中控技术股份有限公司

一种基于自定义剪切区集合的MFC程序GDI绘图优化方法-浙江中控技术股份有限公司

一种基于自定义剪切区集合的MFC程序GDI绘图优化方法罗幸明,徐伟强浙江中控技术股份有限公司,浙江杭州,310053摘要:传统MFC程序GDI绘图仅考虑屏幕刷新闪烁的优化,而对于绘图内容本身的优化考虑有限。

常规应用下,GDI绘图本身确实不会成为程序的性能瓶颈,但在高分辨率、复杂画面的绘制显示时,这个问题就不得不考虑了。

通常我们会使用系统剪切区进行优化控制,但是实际应用发现当分辨率或者画面复杂度大于一定程度后,该优化的性能提升有限。

鉴于此,本文提出了一种简单可行的基于自定义剪切区集合判断的MFC程序GDI绘图优化方法,可以有效解决高分辨率、复杂画面的GDI绘图性能问题。

关键词:自定义剪切区、MFC、GDI、绘图One Optimizing Design Based On Custom Clipping Region Sets Of MFC Programs Drawing With GDILuo Xingming,Xu WeiqiangZhejiang SUPCON Co.,Ltd, Hangzhou, Zhejiang, 310053Abstract:When drawing with GDI of traditional MFC programs,the most considering things is the screen flashing problems but not drawing itself.Normally drawing performance will not be the choke point,but it really will be when screen resolution is high enough or graphics is complex enough.It is usual to resolve this problem by using system clipping region,but after some industial practice we found that the benefits from this optimizing is limited.Based on this situation,this paper presents a simple effective and practical optimizing design based on custom clipping region sets which can effectivly improve drawing performance of complex graphics in industrial field. Keyword:Custom Clipping Region Sets, MFC, GDI, Drawing基金项目“石化、轨道交通行业分布式综合监控系统(SCADA)研发及应用示范”资助1.GDI概述GDI(Graphics Device Interface)是Windows操作系统的传统图形子系统,负责与设备无关的图形绘制,Win32 API为应用程序提供了丰富的绘图函数和功能,而MFC又对他们进行了C++类的封装。

gdi双缓冲绘图

gdi双缓冲绘图

gdi双缓冲绘图.txt30生命的美丽,永远展现在她的进取之中;就像大树的美丽,是展现在它负势向上高耸入云的蓬勃生机中;像雄鹰的美丽,是展现在它搏风击雨如苍天之魂的翱翔中;像江河的美丽,是展现在它波涛汹涌一泻千里的奔流中。

以下是最简单的双缓冲代码,注释的地方很重要:CRect rect;static BOOL bColor=false;GetClientRect(&rect);CDC dcMem;dcMem.CreateCompatibleDC(pDC); //创建与视图的设备相兼容的内存设备,新的设备不具有与原设备相同的设备属性与背景色.CBitmap bmp;bmp.CreateCompatibleBitmap(pDC,rect.right,rect.bottom); //创建一个与视图兼容的位图,只有根据原设备来创建位图,才能从设备中获取像素点组成位图,因为双缓冲需要保留原设备中已有的图像,因此需要调用这个方法CBitmap* pOldBmp=dcMem.SelectObject(&bmp); //选择位图,只是修改了设备属性,并没有真正绘图.if(bColor){dcMem.SelectStockObject(WHITE_PEN);}else{dcMem.SelectStockObject(BLACK_PEN);}bColor=!bColor;for(int i=0;i<rect.Width();i++) {dcMem.MoveTo(i,0);dcMem.LineTo(i,rect.bottom);}pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); //将在内存中绘制好的图像重新显示到视图中,pDC与dcMem不必兼容.dcMem.SelectObject(pOldBmp);pOldBmp->DeleteObject();双缓冲技术绘图当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。

双缓冲

双缓冲
三、双缓冲图形刷新技术的原理
双缓冲图形刷新技术顾名思义是采用双缓存实现的。传统的绘图方式实际上是一种单缓冲。在windows中每一种设备都在内存中有一个设备描述表与其对应,这个设备描述表实际上就是一个内存缓冲区。传统的绘图中我们是将图形绘制在设备描述表缓冲区中,然后由gdi自动的将设备描述表中的图像拷贝到显存中进行显示。这样一个自动的拷贝过程屏蔽了传统的绘图方式是单缓冲的实质,使我们感觉到我们是在直接操纵显存一样。双缓冲图形刷新技术在内存中有两片缓存,除了设备描述表以外还有一个需要手动建立的与设备描述表缓冲区(前端缓冲区)相兼容的后备缓冲区。绘图过程中,首先将图形绘制在后备缓冲区中,然后在手动的将后备缓冲区中的图像拷贝到前端缓冲区中,再由gdi自动将前端缓冲区中的图像拷贝到显存完成图形的显示过程。
//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//绘图
MemDC.MoveTo(……);
MemDC.LineTo(……);
//将后备缓冲区中的图形拷贝到前端缓冲区
1、编写一个刷新速度很慢的应用程序,可以设计为通过点击鼠标来进行屏幕刷新。通过该试验可以发现即使屏幕的刷新速度很慢,但是在每次刷新的时候仍然存在屏幕的问题,只是闪烁不是很明显。
2、编写一个刷新速度很快的应用程序,并在程序中应用双缓冲图形刷新技术。通过该试验可以发现虽然屏幕刷新速度很快,但是采用了双缓冲图新刷新技术以后,屏幕不存在闪烁。
CBitmap MemBitmap;
//建立与屏幕设备描述表(前端缓冲区)兼容的内存设备描述表句柄(后备缓冲区)

使用双缓存来解决GDI下的闪烁问题

使用双缓存来解决GDI下的闪烁问题

。 引 言
在 进 行 图 形 图 像 处 理 的 软 件 中 , 般 的 图形 处 理 程 序 需 一 要 大 量 的绘 图操 作 , 要 解 决绘 图 的 效 率 和 效 果 问题 : 者 表 首 前 现 在 性 能 方 面 , 否 有 延 迟 , 个 小 小 的 交 互 操 作 是 否 要 等 上 是 一 几秒才 能看到 结果 ;后者表现 在软件 中 的图像是否 闪烁? 比 如 , O D a 中 加 入 如 下 代 码 就 可 看 到 闪烁 。 在 nr w0
维普资讯
第 2 卷 第 1 期 7 7
VO .ቤተ መጻሕፍቲ ባይዱ7 12
计 算 机 工 程 与 设计
Co u e n ie r ga d De in mp trE gn e i n sg n
20 年 9 06 月
S pt 0 6 e .2 0
N O. 7 1
摘 要 : 图形 图 像 处 理 过 程 中 , 在 当显 示 绘 制 的 图像 时 , 时 会 出现 闪 烁 的 情 况 。本 丈从 窗 口 、 口 、 有 视 坐标 系统 的 基 本 概 念 和 关 系 出 发 , 要 讲 解 了如 何 使 用 双 缓 存 来 解 决 GD 下 的 闪 烁 问题 此 方 法 已经 应 用 于 项 目地 质 资料 解 释 系统 中对 井 曲 线 的 主 I
De l g wi ik r r b e a o t a i t f c e o lm b u n hl p GD1 t o b eb fe i g h d u l u r wi n
HAN — a_ S o S Li I HIHa —U n .
(.Colg f nomainS in e n eh oo y 1 l eo Ifr t ce c dT c n lg ,Not s Unv ri ,Xi n7 0 6 ,Chn ; 2 e o a r Wet ies y h t 10 9 a ia .De at n f pr me t o

使用GDI在窗口上画出一个图片

使用GDI在窗口上画出一个图片
dc = getdc(窗口句柄)
memhdc = createcompitabledc(dc)
selectobject(memhdc,图片句柄)
BitBlt(hDc,0,0,100,24,memdc,0,0,SRCCOPY)
===============================
Dim img As Long, img_W As Long, img_H As Long
GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
GdipGetImageWidth img, img_W
GdipGetImageHeight img, img_H
注意咯 第三~第六个参数是原来图片中要截取的部分;第七~第十呢则是画到哪里以及画出来多大的设置。
(4)贴图刷
贴图刷子 跟其它刷子一样 我们需要创建刷子 另外我们需要先初始化图片:)
来看代码:
Dim img As Long, textureBrush As Long
GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
'GdipDisposeImage img
当然 这里面载入长宽是可选的。
最后呢 别忘记释放Image,否则内存突然没了可不要找我~
(2)来自资源文件:GdipLoadImageFromStream
这个函数主要是用来从资源文件(RES)载入图像的,怎么载入呢?我们来看函数,函数是从Stream载入,但是我们VB6没有集成Stream对象,从RES读取出来(LoadResData)也只是返回Byte()。不过很好,OLE提供了一个函数能够将Byte()变为一个IStream对象——我们需要这个API

C#使用BufferedGraphics实现GDI+双缓冲绘图

C#使用BufferedGraphics实现GDI+双缓冲绘图

使用双缓冲的图形可以减少或消除重绘显示图面时产生的闪烁。

使用双缓冲时,更新的图形首先被绘制到内存的缓冲区中,然后,此缓冲区的内容被迅速写入某些或所有显示的图面中。

显示图形的重写相对简短,这通常可以减少或消除有时在更新图形时出现的闪烁。

使用C# GDI+绘图,实现双缓冲绘图有几种方法,在这篇文章中,将介绍其中的一种——使用BufferedGraphics实现GDI+双缓冲绘图。

下面的代码示例演示如何使用BufferedGraphics对象绘制以下图形,这些图形使用几种类型的缓冲实现。

单击窗体将启动或停止一个计时器,该计时器将引起绘制更新。

绘制更新使您可以观察双缓冲的效果。

右击窗体将循环使用下列绘制模式:∙对于Form,直接绘制到Handle。

∙对使用OptimizedDoubleBuffer控件样式的OnPaint方法进行重写,以进行绘制∙对于不使用OptimizedDoubleBuffer控件样式的窗体方法,重写OnPaint方法以进行绘制。

在每种模式下都将绘制文本,以标识当前模式并描述按下每个鼠标按钮时发生的行为。

using System;using ponentModel;using System.Drawing;using System.Windows.Forms;namespace BufferingExample{public class BufferingExample : Form{private BufferedGraphicsContext context;private BufferedGraphics grafx;private byte bufferingMode;private string[] bufferingModeStrings ={ "Draw to Form without OptimizedDoubleBufferring control style","Draw to Form using OptimizedDoubleBuffering control style","Draw to HDC for form" };private System.Windows.Forms.Timer timer1;private byte count;public BufferingExample() : base(){// Configure the Form for this example.this.Text = "User double buffering";this.MouseDown += newMouseEventHandler(this.MouseDownHandler);this.Resize += new EventHandler(this.OnResize);this.SetStyle( ControlStyles.AllPaintingInWmPaint | erPaint, true );// Configure a timer to draw graphics updates.timer1 = new System.Windows.Forms.Timer();timer1.Interval = 200;timer1.Tick += new EventHandler(this.OnTimer);bufferingMode = 2;count = 0;// Retrieves the BufferedGraphicsContext for the// current application domain.context = BufferedGraphicsManager.Current;// Sets the maximum size for the primary graphics buffer// of the buffered graphics context for the application// domain. Any allocation requests for a buffer larger// than this will create a temporary buffered graphics// context to host the graphics buffer.context.MaximumBuffer = new Size(this.Width+1,this.Height+1);// Allocates a graphics buffer the size of this form// using the pixel format of the Graphics created by// the Form.CreateGraphics() method, which returns a// Graphics object that matches the pixel format of the form.grafx = context.Allocate(this.CreateGraphics(),new Rectangle( 0, 0, this.Width, this.Height ));// Draw the first frame to the buffer.DrawToBuffer(grafx.Graphics);}private void MouseDownHandler(object sender, MouseEventArgs e){if( e.Button == MouseButtons.Right ){// Cycle the buffering mode.if( ++bufferingMode > 2 )bufferingMode = 0;// If the previous buffering mode used// the OptimizedDoubleBuffering ControlStyle,// disable the control style.if( bufferingMode == 1 )this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );// If the current buffering mode uses// the OptimizedDoubleBuffering ControlStyle,// enabke the control style.if( bufferingMode == 2 )this.SetStyle( ControlStyles.OptimizedDoubleBuffer, false );// Cause the background to be cleared and redraw.count = 6;DrawToBuffer(grafx.Graphics);this.Refresh();}else{// Toggle whether the redraw timer is active.if( timer1.Enabled )timer1.Stop();elsetimer1.Start();}}private void OnTimer(object sender, EventArgs e){// Draw randomly positioned ellipses to the buffer.DrawToBuffer(grafx.Graphics);// If in bufferingMode 2, draw to the form's HDC.if( bufferingMode == 2 )// Render the graphics buffer to the form's HDC.grafx.Render(Graphics.FromHwnd(this.Handle));// If in bufferingMode 0 or 1, draw in the paint method.elsethis.Refresh();}private void OnResize(object sender, EventArgs e){// Re-create the graphics buffer for a new window size.context.MaximumBuffer = new Size(this.Width+1,this.Height+1);if( grafx != null ){grafx.Dispose();grafx = null;}grafx = context.Allocate(this.CreateGraphics(),new Rectangle( 0, 0, this.Width, this.Height ));// Cause the background to be cleared and redraw.count = 6;DrawToBuffer(grafx.Graphics);this.Refresh();}private void DrawToBuffer(Graphics g){// Clear the graphics buffer every five updates.if( ++count > 5 ){count = 0;grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, this.Width, this.Height);}// Draw randomly positioned and colored ellipses.Random rnd = new Random();for( int i=0; i<20; i++ ){int px = rnd.Next(20,this.Width-40);int py = rnd.Next(20,this.Height-40);g.DrawEllipse(new Pen(Color.FromArgb(rnd.Next(0, 255),rnd.Next(0,255), rnd.Next(0,255)), 1),px, py, px+rnd.Next(0, this.Width-px-20), py+rnd.Next(0, this.Height-py-20));}// Draw information strings.g.DrawString("Buffering Mode:"+bufferingModeStrings[bufferingMode], new Font("Arial", 8), Brushes.White, 10, 10);g.DrawString("Right-click to cycle buffering mode", new Font("Arial", 8), Brushes.White, 10, 22);g.DrawString("Left-click to toggle timed display refresh", new Font("Arial", 8), Brushes.White, 10, 34);}protected override void OnPaint(PaintEventArgs e){grafx.Render(e.Graphics);}[STAThread]public static void Main(string[] args){Application.Run(new BufferingExample());}}}。

使用双缓存来解决GDI下的闪烁问题

使用双缓存来解决GDI下的闪烁问题

使用双缓存来解决GDI下的闪烁问题
韩丽娜;石昊苏
【期刊名称】《计算机工程与设计》
【年(卷),期】2006(27)17
【摘要】在图形图像处理过程中,当显示绘制的图像时,有时会出现闪烁的情况.本文从窗口、视口、坐标系统的基本概念和关系出发,主要讲解了如何使用双缓存来解决GDI下的闪烁问题.此方法已经应用于项目地质资料解释系统中对井曲线的修改和显示部分,实践证明,这种方法是可行的.
【总页数】3页(P3258-3260)
【作者】韩丽娜;石昊苏
【作者单位】西北大学,信息科学技术学院,陕西,西安,710069;咸阳师范学院,计算机科学系,陕西,咸阳,712100;西北政法学院,信息网络中心,陕西,西安,710063
【正文语种】中文
【中图分类】TP311.11
【相关文献】
1.在GDI+中使用双缓存 [J], 申晓
2.基于双缓存技术解决某模拟系统实时显示屏幕闪烁的方法 [J], 董燕;周燕明;崔卫兵
3.基于双缓存技术解决某模拟系统实时显示屏幕闪烁的方法 [J], 董燕;周燕明;崔卫兵
4.VC6.0下使用GDI+为应用程序添色彩 [J], 费之茵
5.基于双缓存技术解决某模拟系统实时显示屏幕闪烁的方法 [J], 董燕;周燕明;崔卫兵
因版权原因,仅展示原文概要,查看原文内容请购买。

GDI+测井曲线绘图中效率提升的研究

GDI+测井曲线绘图中效率提升的研究

GDI+测井曲线绘图中效率提升的研究作者:王宇飞赵正文李瑶来源:《数字技术与应用》2013年第03期摘要:GDI+提供了快速、简单、有效的程序开发方式。

大量测井原始数据生成测井曲线时,绘制对象的增加严重制约了GDI+的绘图效率。

双缓冲技术的使用,可以有效避免图形的闪烁;使用内存中已有图形,可以减少测井曲线的绘制过程,显著提高图形绘制效率。

关键词:测井曲线双缓冲内存图形绘图效率中图分类号:P631.84 文献标识码:A 文章编号:1007-9416(2013)03-0083-021 前言GDI(Graphics Device Interface,图形设备接口)的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

通过GDI众多函数,软件开发人员不需要关心设备驱动及具体硬件设备,就可以将应用程序的输出转化为硬件设备上的输出,实现程序与硬件设备的隔离,方便开发工作。

GDI+是GDI的升级版本,在GDI的基础上进行了了大量的优化和改进工作,使得它的易用性更好。

GDI其中的一个好处就是用户不必知道任何关于数据怎样在设备上绘制图像的细节,GDI+更好地拓展了这一优点,GDI是一个中低层API,用户必须需要知道设备情况,而GDI+是一个高层的API,用户可以不必知道设备情况,GDI+的体系结构如图1。

此外,GDI+不但在功能上比GDI强大很多,而且在代码编写方面也要显得更加简单方便,这将使得其很快成为Windows图形图像程序开发的首选。

2 测井曲线绘制中存在问题测井是油田勘探与开发过程中确定和评价油、气层的重要方法之一,是解决地质问题的重要手段。

通过测井能直接为石油地质和工程技术人员提供各项资料和数据,以指导油田生产。

然而,通过测井设备测量出的大多是一系列离散或连续的数值型数据,同时这也是它们在数据库中的存储形式,即使经验丰富的测井解释人员要想在几百甚至几千米井深的海量测井数据中获得解释结论也是相当困难的,不利于测井数据发挥其功用。

于双缓冲技术的GDI无闪烁绘图

于双缓冲技术的GDI无闪烁绘图


Flickerfree GDI + drawing based on double buffering
JIANG Jianguo , WEN Shaoying, ZHANG Ruinan
( School of Mathematies, Liaoning Normal University, Dalian Liaoning 116029 , China)
基于双缓冲技术的 GDI + 无闪烁绘图
江建国 ,温少营,张瑞楠
( 辽宁师范大学 数学学院, 辽宁 大连 116029 ) ( * 通信作者电子邮箱 jjgbox@ sina. com)
*
要: 图形闪烁是使用 GDI + 编写 Windows 窗体应用程序时经 常 遇 到的 一 个 问题。 在 深 入 分析 窗 体重 绘 模型 阐述了图形闪烁的本质原因。利用. NET框架 中 内 置 的 双 缓 冲 技术, 提出了 两 种 GDI + 无 闪烁 绘 图方 法。 以 基础上, 模拟时钟程序为例, 说明了这两种方法都非常简便且有效。 关键词: 双缓冲; 无闪烁绘图; 图形闪烁; GDI + ; . NET框架; 模拟时钟 中图分类号: TP391. 41 文献标志码: A
this. SetStyle( ControlStyles. OptimizedDoubleBuffer | ControlStyles. UserPaint | ControlStyles. AllPaintingInWmPaint, true) ;
向 Windows 窗体注册一个名为 MyPaintHandler 的 Paint 事件 处理程序, 将重绘窗体的代码添加到方法 MyPaintHandler 中:

双缓冲技术实现VC绘图共28页文档

双缓冲技术实现VC绘图共28页文档

********************所有的GDI绘图函数使用的都是逻辑坐标(逻辑范围)**************************************系统默认情况下物理范围和逻辑范围是1:1 的对应关系*******************1. 首先定义类成员:CDC *m_pDC;CDC MemDC;CBitmap MemBitmap;CBitmap *pOldbitmap;LONG xRange; // 逻辑范围,x方向宽度LONG yRange; // 逻辑范围,y方向高度LONG nWidht; // 物理范围,x方向宽度LONG nHeight; // 物理范围,y方向高度2. 在类初始化函数中:m_pDC = this->GetDC(); // 获取设备上下文句柄CWnd *wnd = GetDlgItem(IDC_SHOWGRAPH); // 获取界面上显示图形的ID控件的句柄wnd->GetWindowRect(&rect); // 获取显示/画图区域大小(物理范围)ScreenToClient(&rect); // 转换为客户区坐标nWidth = rect.Width(); // 显示/画图区域x方向物理宽度nHeight = rect.Height(); // 显示/画图区域y方向物理高度3. 在自定义函数中,设置视口与窗口的比例关系:m_pDC->SetMapMode(MM_ANISOTROPIC); // 注意MM_ANISOTROPIC和MM_ISOTROPIC的区别m_pDC->SetWindowExt(XRange,-yRange); // 设定窗口尺寸范围,画图使用的逻辑范围,实现放大或是缩小,坐标方向↑和→为正向m_pDC->SetViewportExt(nWidth,nHeight); // 设定视口尺寸范围,客户区实际图形显示的区域范围,大小固定m_pDC->SetViewportOrg(rect.left,rect.bottom); //设定画图的逻辑原点坐标(0,0)在物理坐标的(rect.left,rect.bottom)点上4. 在自定义函数中,双缓冲技术的使用:MemDC.CreateCompatibleDC(m_pDC);// 创建内存兼容设备上下文MemBitmap.CreateCompatibleBitmap(m_pDC,xRange,yRange); // 创建内存兼容画布,大小由逻辑范围决定pOldbitmap =MemDC.SelectObject(&MemBitmap); // 将画布选入内存设备上下文MemDC.FillSolidRect(0,0,xRange,yRange,RGB(123,213,132)); // 对内存中的画布填充背景颜色,否则是默认的黑色// 画图操作,如画一条对角直线MemDC.MoveTo(0,0);MemDC.LineTo(xRange*0.9,yRange*0.9);// 将内存中的画图区域拷贝到界面的控件区域上去// 第1和第2个参数若是0时,则从物理坐标的(rect.left,rect.bottom)点上开始按上述指定的方向贴图m_pDC->BitBlt(0,0,xRange,yRange,&MemDC,0,0,SRCCOPY);5. 在类的析构函数中:MemDC.SelectObject(pOldbitmap);bitmap.DeleteObject();this->ReleaseDC(m_pDC);6. 至此,就完成了双缓冲及坐标缩放绘图的功能用VC做的画图程序,当所画的图形大于屏幕时,在拖动滚动条时屏幕就会出现严重的闪烁,为了解决这一问题,就得使用双缓冲来解决。

利用双缓存技术解决GDI画图的刷新问题

利用双缓存技术解决GDI画图的刷新问题

利用双缓存技术提高GDI+的绘图效果摘要在进行图像处理的软件中,一般的图形处理程序需要大量的绘图操作,首要解决的就是绘图的效率和效果问题:前者表现在性能方面,是否有延迟,一个小小的交互操作是否要等上几秒才能看到结果;后者表现在重新绘制或刷新的过程中出现闪烁?本文主要介绍GDI+程序中引用双缓冲技术以解决重绘时出现的闪烁问题—提高绘图效果。

关键字:GDI+;双缓存;快速;缓存位图;效果引言在使用GDI+的实际的绘图中,绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面重新刷新一次以维持窗口正常显示。

这样的效率非常低,不仅达不到性能要求,而且还可能会出现闪烁的现象。

刷新过程中会导致所有图元重新绘制,而各个图元的重绘操作并不会导致Paint事件发生,因此窗口的每一次刷新只会调用Paint事件一次。

窗口刷新一次的过程中,每一个图元的重绘都会立即显示到窗口,因此整个窗口中,只要是图元所在的位置,都在刷新,而刷新的时间是有差别的,闪烁现象自然会出现。

所以说,此时导致窗口闪烁现象的关键因素并不在于Paint事件调用的次数多少,而在于各个图元的重绘。

根据以上分析可知,当图元数目不多时,窗口刷新的位置也不多,窗口闪烁效果并不严重;当图元数目较多时,绘图窗口进行重绘的图元数量增加,绘图窗口每一次刷新都会导致较多的图元重新绘制,窗口的较多位置都在刷新,闪烁现象自然就会越来越严重。

特别是图元比较大绘制时间比较长时,闪烁问题会更加严重,因为时间延迟会更长。

1、双缓存技术为了解决画图的效率问题,我们引进了双缓存技术,双缓冲技术早在GDI的程序开发中,就已经开始使用。

在普通的绘图模式下,图像处理程序是按照设计的顺序,将被绘制的元素一个接一个地在目标设备上进行绘制。

何谓“双缓冲”?它的基本原理就是:先在内存中开辟一块虚拟画布,然后将所有需要画的图形先画在这块“虚拟画布”上,最后在一次性将整块画布画到真正的窗体上。

VC6屏幕绘图(GDI)基础

VC6屏幕绘图(GDI)基础

VC6屏幕绘图(GDI)基础在VC6中,屏幕绘图是通过设备环境(Device Context)实现的,它是GDI的的关键元素。

一、设备环境获取的一些函数:WINUSERAPI HDC WINAPI GetDC(HWND hWnd); //获取窗口的设备环境WINUSERAPI HDC WINAPI GetWindowDC( HWND hWnd);WINGDIAPI HDC WINAPI CreateCompatibleDC(HDC);二、设备环境的坐标:(1)、设备坐标:指的是显示设备或者打印设备坐标系下的坐标。

这种坐标以设备上的像素点为坐标单位,通常情况下,它的原点在窗口客户区的左上角。

(2)、逻辑坐标:指的是各种映射模式下的坐标。

(3)、物理坐标:指的是开发人员自定义的坐标。

三、设备环境的颜色COLORREF数据类型,用8位十六进制值0x00bbggrr表示一个RGB(红、绿、蓝)值,每个颜色分量的最大值为0xff。

获取一个COLORREF变量的各分量颜色值的宏:BYTE GetRValue(DWORD rgb); //取得红色分量值BYTE GetGValue(DWORD rgb); //取得绿色分量值BYET GetBValue(DWORD rgb); //取得蓝色分量值COLORREF RGB(BYTE red,BYTE green,BYTE blue);四、使用GDI对象定义GDI对象后,要用SelectObject()函数把定义的GDI对象选择用在当前的环境中。

例如:HDC hdc;HBRUSH hbr;hdc=GetDC(hwnd);hbr=CreateSolidBrush(RGB(255,0,0));SelectObject(hdc,hbr);五、使用画刷画刷(HBRUSH)可以用来填充指定区域的特性。

画刷通常包括填充颜色、填充图案、填充样式3种属性。

//创建实心画刷HBRUSH CreateSolidBrush(COLORREF );//创建填充画刷HBRUSH CreateHatchBrush(int index,COLORREF );//创建用位图作为填充的画刷HBRUSH CreatePatternBrush(HBITMAP );填充画刷参数index 指定的填充样式如下:HS_BDIAGONAL //从左到右往下的45度斜线HS_CROSS //十字线HS_DIAGCROSS //45度交叉线HS_FDIAGONAL //从左到右往上的45度斜线HS_HORIZONTAL //水平线HS_VERTICAL //垂直线位图填充参数hbmp 一般由下面函数获取://创建单色位图HBITMAP CreateBitmap(int width,int height,UINT nc,UINT colorbits,CONST VOID *bitmapdata); //连接图像HANDLE LoadImage(HINSTANCE hinstance,LPCTSTR imagename,UINT imagestyle,int width,int height,UINT );图1、自定义位图填充图像int bit[]={0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,};int bit1[]={0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,};0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a, };void patternbitmap(int x,int y,int width,int height,int psw,int psh,int pattern[],int bits){HDC hdc;hdc=GetDC(m_hwnd);HBITMAP hbmp=CreateBitmap(psw,psh,1,bits,pattern);HBRUSH hp=CreatePatternBrush(hbmp);SelectObject(hdc,hp);Rectangle(hdc,x,y,x+width,y+height);DeleteObject(hbmp);DeleteObject(hp);DeleteDC(hdc);}patternbitmap(50,50,100,100,8,8,bit,32);patternbitmap(200,50,100,100,8,8,bit1,32);patternbitmap(350,50,100,100,8,8,bit2,32);上面代码是图1的数据定义和实现过程。

GDI+绘图闪烁解决方法

GDI+绘图闪烁解决方法

GDI+绘图闪烁解决⽅法闲着没事,准备做⼀个类似于TeeChart的⾃定义控件,结果第⼀步的绘图就把我给难倒了,虽然早就知道GDI绘图的闪烁问题很坑,但是却没有想到如此之坑,折腾了两天,才找到解决⽅法。

⾸先在窗体加载的时候,加⼊双缓存,说实话以前⼀直没觉得这个双缓存有什么⽤,不过这次总算是有了点⼉效果。

DoubleBuffered = true;SetStyle(ControlStyles.OptimizedDoubleBuffer |ControlStyles.ResizeRedraw |ControlStyles.AllPaintingInWmPaint, true);下⾯是⼀个例⼦,我准备画⼀个简单的坐标系。

这个⽅法会获得⼀个⾃定义的位图,将这个位图直接赋值给窗体的背景图⽚,或者PictureBox控件也可以。

///<summary>///绘制界⾯///</summary>private Bitmap DrawGDI(){var bmp = new Bitmap(Width, Height);var pen = new Pen(Color.Black, 1.0f);Graphics g = Graphics.FromImage(bmp);var p1 = new Point(20, 10);var p2 = new Point(20, Height - 25);var p3 = new Point(Width - 10, Height - 25);g.DrawLines(pen, new[] { p1, p2, p3 });g.DrawString("0", Font, Brushes.Black, 10, Height - 20);return bmp;}我这⾥是直接在重绘⽅法⾥⾯给背景图⽚直接赋值了。

///<summary>///重绘///</summary>protected override void OnPaint(PaintEventArgs e){BackgroundImage = DrawGDI();base.OnPaint(e);}做完这些之后,我惊讶的发现GDI绘制出的图居然不闪了。

闪烁问题

闪烁问题

设置双缓冲减少窗体闪烁2009年05月15日星期五下午 10:18如何:通过对窗体和控件使用双缓冲来减少图形闪烁更新:2007 年 11 月对于大多数应用程序,.NET Framework 提供的默认双缓冲将提供最佳效果。

默认情况下,标准 Windows 窗体控件是双缓冲的。

可以通过两种方法对窗体和所创作的控件启用默认双缓冲。

一种方法是将DoubleBuffered属性设置为 true,另一种方法是通过调用SetStyle 方法将OptimizedDoubleBuffer标志设置为 true。

两种方法都将为窗体或控件启用默认双缓冲并提供无闪烁的图形呈现。

建议仅对已为其编写所有呈现代码的自定义控件调用SetStyle方法。

------------------------------------------------------------------------------------------------------------------------------------什么是闪烁闪烁可以这样定义:当后面一幅图像以很快的速度画在前面一幅图像上时,在后面图像显示前,你可以很快看到前面那一个图像,这样的现象就是闪烁。

我认为,闪烁会让使用者对程序很不满,原因是:如果用户接口编码如此糟糕,那么程序的其他部分呢,如何能相信数据的正确性呢?一个具有平滑,快速相应的程序会给用户带来信心,这个道理很简单。

程序出现闪烁可以由多种形式造成,最常见的原因是窗口大小发生改变时,其内容重画造成闪烁。

仅仅画一次这是一个黄金法则,在任何计算机(Windows或者你使用的任何操作系统)上处理画法逻辑都需要遵循,即永远不要将同一像素画两次。

一个懒惰的程序员常常不愿意在画法逻辑上投入过多精力,而是采用简单的处理逻辑。

要避免闪烁,就需要确保不会出现重复绘制的情况发生。

现在,WIndows和计算机还是很笨的,除非你给他们指令,否则他们不会做任何事情。

Qt双缓冲绘图

Qt双缓冲绘图

双缓冲绘图在Qt4中,所有的窗口部件默认都使用双缓冲进行绘图。

使用双缓冲,可以减轻绘制的闪烁感。

在有些情况下,用户要关闭双缓冲,自己管理绘图。

下面的语句设置了窗口部件的Qt::WA_PaintOnScreen属性,就关闭了窗口部件的双缓冲.mywidget->setAttribute(Qt::WA_PaintOnScreen);由于Qt4不再提供异或笔,组合模式QPainter::CompostionMode_Xor()并不是异或笔,Qt4只提供了QRubberBand实现矩形和直线的绘图反馈。

因此要实现在绘图中动态反馈必须使用其他方法。

程序中使用双环冲来解决这个问题。

在绘图过程中,一个缓冲区绘制临时内存,一个缓冲区保存绘制好的内容,最后进行合并。

在交互绘图过程中,程序将图像缓冲区复制到临时缓冲区,并在临时缓冲区上绘制,绘制完毕在将结果复制到图像缓冲区,如果没有交互复制,则直接将图像缓冲区绘制显示到屏幕上。

Qt组件中的双缓冲无闪烁绘图闪烁首先,要想把闪烁减弱,请设置组件的背景模式为NoBackground. setBackgroundMode(NoBackground);其次,重载组件的paintEvent()函数,如下改写:void MyWidget::paintEvent(QPaintEvent *e){QRect ur=e->rect();//得到组件尺寸QPixmap pix(ur.size());//以此为参数创建一个位图变量pix.fill(this,ur.topLeft());//填充位图QPainter p(&pic);//以位图为参数创建一个QPainter 对象p.translate(-ur.x(),-ur.y());//在QPainter 上绘画//......//Drawingp.End();//绘画完毕bitBlt(this,ur.topLeft().&pix);//把位图贴到组件上//注从qt4开始,bitBlt函数不在使用,取而代之的是drawPixmap。

航行训练模拟器陆标定位功能的模拟与实现

航行训练模拟器陆标定位功能的模拟与实现

航行训练模拟器陆标定位功能的模拟与实现肖剑波;胡大斌;胡锦晖【摘要】结合船舶航行操作训练实际,在视景仿真系统中开发陆标定位功能,介绍潜艇航行训练系统的组成及功能.针对某型船舶所用方位仪对陆标定位功能进行模拟罗经功能设计,基于GDI+的方式实现罗经的模拟开发.基于实际地形高程数据对地形场景进行建模,并依据电子海图等相关数据对助航标志和地貌特征等进行定位.通过实验比较分析,船舶训练模拟器中的方位定位结果符合真实地形数据,可以满足船员方位定位训练的需求.【期刊名称】《浙江交通职业技术学院学报》【年(卷),期】2012(013)004【总页数】4页(P14-17)【关键词】陆标定位;模拟训练;罗经;地形【作者】肖剑波;胡大斌;胡锦晖【作者单位】海军工程大学船舶与动力学院,武汉430033;海军工程大学船舶与动力学院,武汉430033;海军工程大学船舶与动力学院,武汉430033【正文语种】中文【中图分类】TP391.90 引言航行训练模拟器是一种典型的人在回路仿真,人作为一个环节参与到仿真系统中,通过对仿真系统提供的各种信息进行判断和决策,从而进行模拟操纵和控制,以实现船员训练、方案论证、海事分析等目的[1]。

利用目力能见范围内的陆岸、岛上固定物标测定舰 (船)位的方法,称为陆标定位。

陆标定位是舰船沿岸航行时保证航行安全的主要手段[2-3]。

方位定位是利用罗经观测物标方位确定舰位的方法,其观测方便迅速,在海图上标绘容易,因而是沿岸航行时最常用的方法。

在海船船员适任评估项目“航海仪器的正确使用”中,“方位仪的正确使用”是其中一项很重要的实训项目,也是驾驶员必须熟练掌握的基本技能之一[4]。

本文结合船舶航行操作训练实际,在视景仿真系统中开发陆标定位功能,介绍了船舶航行训练系统的组成及功能。

针对某型船舶所用方位仪对陆标定位功能进行了模拟罗经功能设计,基于GDI+的方式实现了罗经的模拟开发。

为保证系统中方位定位的准确性,基于实际地形高程数据对地形场景进行建模,并依据电子海图等相关数据对助航标志和地貌特征等进行定位。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*
Abstract: Graphics flickering is an intractable common problem when programming Windows forms applications by using GDI + . On the basis of profound analysis on the model of form redrawing, the essentials of graphics flickering were explained in this paper. Two flickerfree GDI + drawing methods were proposed based on double buffering built in the . NET framework. To take analog clock as an example, it is shown that these two methods are very easytouse and effective. Key words: double buffering; flickerfree drawing; graphics flickering; GDI + ; . NET framework; analog clock
基于双缓冲技术的 GDI + 无闪烁绘图
江建国 ,温少营,张瑞楠
( 辽宁师范大学 数学学院, 辽宁 大连 116029 ) ( * 通信作者电子邮箱 jjgbox@ sina. com)
*
要: 图形闪烁是使用 GDI + 编写 Windows 窗体应用程序时经 常 遇 到的 一 个 问题。 在 深 入 分析 窗 体重 绘 模型 阐述了图形闪烁的本质原因。利用. NET框架 中 内 置 的 双 缓 冲 技术, 提出了 两 种 GDI + 无 闪烁 绘 图方 法。 以 基础上, 模拟时钟程序为例, 说明了这两种方法都非常简便且有效。 关键词: 双缓冲; 无闪烁绘图; 图形闪烁; GDபைடு நூலகம் + ; . NET框架; 模拟时钟 中图分类号: TP391. 41 文献标志码: A

Flickerfree GDI + drawing based on double buffering
JIANG Jianguo , WEN Shaoying, ZHANG Ruinan
( School of Mathematies, Liaoning Normal University, Dalian Liaoning 116029 , China)
0
引言
在编写图形应用程序时, 经常会发现程序所绘制的图形
在屏幕 上 不 停 地 闪 烁, 这是一个比较难以解决的编程问 题
[1 ]
双缓冲 技 术 在 编 程 界 应 用 已 经 有 好 多 年 了 。 在 早 期 Win32 编程年代, 使用 C 语言调用 GDI 编写图形应用程序, 就 为了使用双缓存技术消除 经常会遇到图形闪烁问题 。 那时, 图形闪烁, 往往需要额外编写一些较高技巧的代码; 后来, 随 着面向对象开发技术的成熟与流行, 双缓冲技术在一些面向 [5 ] DirectX[3,6] 对象风格的图形库中得到了支持, 如 OpenGL 、 等图形库。一些面向对象风格的应用程序框架也都为双缓冲 X 窗 口 系 统[8] 、 如 ET + + 、 技术提 供 了 不 同 程 度 的 支 持, [9 - 10 ] [11 - 12 ] [1 , 4 ] MFC 、 Java 、 . NET 等。 [4 ] 虽然 . NET 框架中内置了双缓冲技术 , 但是我们发现, 很多. NET程序员在开发 Windows 窗体应用程序时, 仍不能正 确地使用双缓冲技术消除图形闪烁 。 许多 . NET 程序员还是 这不但增加了实现 使用传统的手工编码方式来实现双缓冲, 难度, 而且有时还会引入其他的一些编程问题 。 造成 . NET 程 序员不正确使用双缓冲技术的主要原因有两个: 一个是没有 正确地理解 Windows 窗 体 重 绘 模 型; 另 一 个 就 是 没 有 掌 握 . NET框架中内置的双缓冲技术 。 本文通过研究 Windows 窗体重绘模型, 以及 . NET 框架中 来探讨如何在 Windows 窗 与双缓冲技术密切相关的一些类, 体应用 程 序 中 使 用 双 缓 冲 技 术 来 消 除 图 形 闪 烁 。 在 分 析 Windows 窗体重绘模型基础上, 阐述引起图形闪烁的本质原 因; 提出两种基于双缓冲技术的 GDI + 无闪烁绘图方法: 一种 是控件默认的双缓冲绘图, 另一种是自定义双缓冲绘图 。 以 模拟时钟为例, 详细地说明如何在实际的项目开发过程中使 用双缓冲技术消除图形闪烁 。
。绘图密集型应用程序, 如动画、 视频游戏等, 往往会导
致其所绘制的图形出现闪烁 。闪烁使图形具有不可接受的外 会严重地影响用户体验 。 观, 有许多 消 除 图 形 闪 烁 的 方 法, 如 增 量 更 新 ( incremental update ) [2] 、页 面 切 换 ( page flipping ) [3] 、双 缓 冲 ( double buffering) [4] 等。每种方法都有其不同的优缺点, 也都有其不 同的适用范围。增量更新的缺点是不适用于难以判断无效区 域的编程场景, 优点是能在某种程度上提高程序运行效率; 页 面切换的缺点是需要显卡硬件的支持, 优点是运行效率最高; 双缓冲的缺点是需要较多的内存, 优点是适用范围广泛。 在 一般编程场景下, 大多数开发人员还是喜欢使用双缓冲技术 来消除图形闪烁。 双缓冲技术的基本思想是不直接在屏幕的显存( 称为前 端缓冲区) 中绘图, 而是先将图形绘制到一块内存( 称为后端 缓冲区) 中, 然后再将后内存中已绘制好的图形复制到显存 中( 见图 1 ) 。由于所有的绘图操作都是在后端缓冲区内完成 的, 而在屏幕上只执行一次呈现图形操作, 因而能消除由多重 绘制所引起的图形闪烁 。
Journal of Computer Applications 计算机应用,2012,32( S2) : 136 - 139 文章编号: 1001 - 9081 ( 2012 ) S2 - 0136 - 04
ISSN 1001-9081 CODEN JYIIDU
2012-12-31 http: / / www. joca. cn
相关文档
最新文档