基于IOS双缓冲绘图技术的研究
- 格式:pdf
- 大小:199.90 KB
- 文档页数:3
如何实现双缓冲双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。
双缓冲实现过程如下:1、在内存中创建与画布一致的缓冲区2、在缓冲区画图3、将缓冲区位图拷贝到当前画布上4、释放内存缓冲区(1)在内存中创建与画布一致的缓冲区CDC dc;//这是窗口的DC,假设已加载好CDC MemDC; //创建内存中的一个临时dc- MemDC, MemDC用来向窗口绘图的“草稿”//随后建立与屏幕显示兼容的内存显示设备MemDC.CreateCompatibleDC(&dc); //这时还不能绘图,因为没有地方画 ^_^//创建的临时空白bitmap作为“画布”,至于位图的大小,可以用窗口的大小CBitmap MemBitmap;MemBitmap.CreateCompatibleBitmap(&dc,nWidth,nHeight);//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); //将上面创建的临时“画布”MemBitmap与MemDC连接,注意此处的MemBitmap为一个空白临时画布,可以在这个空白画布上自绘图,也可以在这个画布上加载图片//先用背景色将位图清除干净,这里我用的是白色作为背景//你也可以用自己应该用的颜色MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));(2)在缓冲区画图MemDC.MoveTo(……);MemDC.LineTo(……);(2)'在第(2)步中,如果不是自绘图,而是加载一个位图,则需要再定义一个临时dc- MemDC2,用来将位图加载到上面建立的空白画布MemDC中CBitmap p1;//这是要画的位图,假设已加载好CDC MemDC2;MemDC2.CreateCompatibleDC(&dc);MemDC2.SelectObject(&p1);// MemDC2与图片链接//在这里,p1保存的是要加载到临时空白画布上的图片,MemDC2是与p1链接的dc(3)将缓冲区位图拷贝到当前画布(屏幕)上dc.BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);(3)’如果是位图的话首先,将与MemDC2链接的位图p1拷贝到临时空白画布MemDC中MemDC.BitBlt(x,y,width,height,& MemDC2,0,0,SRCCOPY); //向草稿绘制第一张图片,x,y,width,height请自行设置其次,将草稿绘制到屏幕上dc.BitBlt(0,0,width,height,&MemDC,0,0,SRCCOPY);(4)释放内存缓冲区//绘图完成后的清理MemBitmap.DeleteObject();MemDC.DeleteDC();MemDC2.DeleteDC();下面是一个不使用和使用双缓存的例子使用双缓存//CPoint ptCenter;//CRect rect, ellipseRect;//GetClientRect(&rect); //获得窗口客户区的大小//ptCenter = rect.CenterPoint(); //获得矩形的中心点,目的是为了确定后面同心圆图像的圆心//CDC dcMem; // 创建用于缓冲作图的内存DC对象dcMem//CBitmap bmp; // 创建内存中存放临时图像的位图对象bmp//dcMem.CreateCompatibleDC(pDC); // 依附窗口DC(窗口对象为pDC),创建兼容内存DC(就是创建一个内存DC,所有图形先画在这上面)//bmp.CreateCompatibleBitmap(&dcMem, rect.Width(), rect.Height());// 在兼容内存DC上,创建兼容位图//dcMem.SelectObject(&bmp); // 将位图选入内存DC//dcMem.FillSolidRect(rect, pDC->GetBkColor());// 按照原有背景色填充客户区,否则会成为黑色,同时也使内存DC的背景色保持一致//// 绘图操作//for (int i = 60; i > 0; --i)//{// ellipseRect.SetRect(ptCenter, ptCenter);// ellipseRect.InflateRect(i * 5, i * 5);// dcMem.Ellipse(ellipseRect); // 在内存DC上绘图,做同心圆图像//}//pDC->BitBlt(0, 0, rect.Width(), rect.Height(),// &dcMem, 0, 0, SRCCOPY); // 将内存DC上的图像复制到前台pDC,即实际屏幕对象pDC//dcMem.DeleteDC(); // 删除内存DC//bmp.DeleteObject(); // 删除内存位图不使用双缓存CPoint ptCenter;CRect rect,ellipseRect;GetClientRect(&rect);ptCenter = rect.CenterPoint();for(int i=60;i>0;i--){ellipseRect.SetRect(ptCenter,ptCenter);ellipseRect.InflateRect(i*5,i*5);pDC->Ellipse(ellipseRect);}下面的例子是加载两幅图片CBitmap p1,p2;//这是要画的位图,假设已加载好CDC dc;//这是窗口的DC,假设已加载好//创建两个临时dc,dc1为向窗口绘图的“草稿”,dc2为与源位图连接的dc(实际上dc2也可以用别的方法代替,这只是我的癖好)CDC dc1,dc2;dc1.CreateCompatibleDC(&DC);dc2.CreateCompatibleDC(&DC);//创建一个临时bitmap作为“画布”,与dc1连接CBitmap bm;CBitmap *Oldbm1,Oldbm2bm.CreateCompatibleBitmap(pDC,width,height); //长度宽度设置成与绘图面积一样大dc1.SelectObject(&bm);dc2.SelectObject(&p1);//dc2与第一张图片链接dc1.BitBlt(x,y, width,height,&dc2,0,0,SRCCOPY); //向草稿绘制第一张图片,x,y,width,height请自行设置dc2.SelectObject(&p2);//dc2与第一张图片链接dc1.BitBlt(x,y, width,height,&dc2,0,0,SRCCOPY); //向草稿绘制第二张图片//将草稿转移至窗口dc.BitBlt(0,0, width,height,&dc1,0,0,SRCCOPY);//清理工作...。
卡马克卷轴算法研究摘要与关键词中文摘要对于J2ME框架下的手机游戏程序的开发,其地图滚动的重绘有多种算法,由于手机性能的限制和开发周期等其他非技术条件,需要根据情况灵活选择所需的技术。
但在及其苛刻条件下,如系统CPU资源不足,地图块尺寸较小等,会造成屏幕闪耀,帧数过低等情况,严重影响到游戏体验。
在开发中如此类问题无法绕过以及避免(指通过修改策划方案,以及程序使用的技术框架),则需要考虑使用地图缓冲绘制技术,卡马克卷轴就是一种最经典的地图缓冲绘制技术。
可有效的改善在地图绘制中的屏幕闪耀,帧数过低等情况。
English AbstractFor J2ME Mobile Phone Games under the framework of the development process, and its rolling redraw the map has a variety of algorithms, because of restrictions on mobile phone performance and development cycle and other non-technical conditions required under the circumstances required the flexibility to choose technologies. However, in its harsh conditions, such as system CPU resources are insufficient, and a smaller block size, etc., will cause the screen shine, low frames, etc., seriously affecting the gaming experience. At the development of such a category can not bypass the problem and to avoid (referring to the adoption of amendments to planning programs, as well as the technology used in the framework of the procedure), you need to consider the use of map rendering buffer, scroll Carmack is one of the most classic map buffer rendering. Can effectively improve the mapping of the screen shine, frames are too low and so on.关键词●卡马克卷轴:一种经典的地图缓冲绘制技术。
1创建画笔,画刷void CGraphView::OnDraw(CDC* pDC){CGraphDoc* pDoc = GetDocument( );ASSERT_V ALID(pDoc);// TODO: add draw code for native data here// 使用画笔第一步:创建一支新画笔CPen pen(PS_SOLID, 1, RGB(255,0,0));CPen pen(PS_DASHDOT, 1, RGB(255,0,0));//第二步:选择新画笔到设备环境中,同时保存旧画笔CPen * pOldPen = pDC->SelectObject(&pen);// 使用画刷第一步:创建一支新画刷CBrush brush(RGB(255,0,0)); //创建实体画刷CBrush brush(HS_CROSS, RGB(255,0,0)); //创建阴影模式画刷//第二步:选择新画刷到设备环境中,同时保存旧画刷CBrush * pOldBrush = pDC->SelectObject(&brush);// 常用的绘图函数////绘制一个彩色点pDC->TextOut(20, 20, "点");pDC->SetPixel(100, 40, RGB(255,0,0));//绘制直线pDC->TextOut(320, 20,"线段");pDC->MoveTo(400, 40);pDC->LineTo(500, 40);//绘制折线pDC->TextOut(20, 170, "折线");POINT polyline[4]={{240,240},{80,120},{240,120},{80,240}}; pDC->Polyline(polyline,4);//绘制矩形pDC->TextOut(320, 170, "矩形");pDC->Rectangle(390, 110, 600, 230);//绘制椭圆pDC->TextOut(20, 320, "椭圆");pDC->Ellipse(80, 260, 280, 380);//绘制多边形pDC->TextOut(320, 320, "多边形");POINT polygon[3]={{380,330},{530,260},{500,360}};pDC->Polygon(polygon,3);//第三步:恢复设备环境的旧画笔,以便释放新画笔// pDC->SelectObject(pOldPen);//第三步:恢复设备环境的旧画刷,以便释放新画刷// pDC->SelectObject(pOldBrush);}2创建字体的两种方法第一种创建字体的方法:使用CreateFont函数,如下定义:CFont::CreateFontBOOL CreateFont( int nHeight, //字体的高度int nWidth, //字体的宽度int nEscapement, //字体显示的角度int nOrientation, //字体的角度int nWeight, //字体的磅数BYTE bItalic, //斜体字体BYTE bUnderline, //带下划线的字体BYTE cStrikeOut, //带删除线的字体BYTE nCharSet, //所需的字符集BYTE nOutPrecision, //输出的精度BYTE nClipPrecision, //裁减的精度BYTE nQuality, //逻辑字体与输出设备的实际//字体之间的精度BYTE nPitchAndFamily, //字体间距和字体集LPCTSTR lpszFacename //字体名称);例子:font.CreateFont(12, // nHeight0, // nWidth0, // nEscapement0, // nOrientationFW_NORMAL, // nWeightFALSE, // bItalicFALSE, // bUnderline0, // cStrikeOutANSI_CHARSET, // nCharSetOUT_DEFAULT_PRECIS, // nOutPrecisionCLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQualityDEFAULT_PITCH | FF_SWISS, // nPitchAndFamily "Arial"); // lpszFacename一般只修改几项。
[Winodows图形编程]初识双缓冲技术为完成PaintBoardDemo(本人设计的一个基于.NET Framework的WinForm的画图程序),过程中遇到的技术难点之一就是就是要显示任何图形绘制过程中的轨迹,也即需要在pictureBox控件的MouseMove事件中添加相应的Graphics对象的DrawXX Methods.在设计之初,仅仅能够在MouseMove事件中写出一行代码:g.DrawLine(new Pen(Color.Red),ptLast.X,ptLast.Y,e.X,e.Y)(ptLast为Point类型的全局变量,用以保存MouseDown事件的坐标)。
可想而知,鼠标的每一次Move就将触发MouseMove事件,即执行一次g.DrawLine(画一条直线)。
因此程序运行的结果就是,画板上显示了绘制过程中的所有轨迹,如下图,显然,这是与我们的设计目的相不符的。
经过对Bitmap与Graphics的学习及经过同学开导,终于解决了不显示绘制过程中多余轨迹的问题。
基本实现的思想可以总结如下:1.建立一个位图对象,即Bitmap _bitmapTemp,和一个Graphics对象用来实现一系列绘制操作,即Graphics g(_bitmapTemp,g均为全局变量)。
2.在主窗体的Shown事件中,对_bitmapTemp和g进行初始化:_bitmapTemp=new Bitmap(pictureBox.Width,pictureBox.Height);//初始化位图大小和pictureBox一致Graphics.FromImage(_bitmapTemp).FillRectangle(Brushes.White,0,0,pictureBox.Width,pictureB ox.Height);//并且将位图_bitmapTemp以白色填充全部区域,以作绘制之用。
g=pictureBox.CreateGraphics();//实例化g对象,表明以后对g的所有绘制操作均在pictureBox之上。
测井曲线绘图显示算法总结——双缓冲技术复杂的开发测井工程图件因含有大量的图像元素,要经过大量的比例关系换算、坐标系的转换和复杂的坐标映射才能将像素在正确的位置显示出来。
巨幅、需滚屏显示的测井曲线,其运算量更大,如按常规滚屏的方法直接在应用程序的窗口绘制全图,由于开始绘制曲线像素所需的大量图元计算时间和结束像素绘制时间之间有一个延迟,而经常会出现图像的刷新速度慢、图像重叠和闪烁、花屏等现象。
应用双缓冲技术,首先在内存中绘制整个测井曲线,在滚屏显示过程中将内存中相应位块的图像剪贴到显示区域,就能克服上述问题,连续地显示曲线,进而将内存中的设备相关图像转换成设备无关的、标准格式的图像进行保存。
在Windows中,应用程序在下面情况下会发出WM_PAINT消息请求绘图:(1)当创建窗体或改变窗体大小时;(2)在程序中使用Invalidate等函数来指定更新区域时;(3)执行其它会影响客户区的操作时;Windwos接收WM_PAINT消息后,就会执行OnPaint函数进行窗口的重绘工作,Windows自身所提供的绘图机制中,重绘窗口分两步进行:首先,Windows要发送WM_ERASEBKGND消息到窗口来通知窗口擦除背景,当窗口接收到WM_ERASEBKGND消息后,会调OnEraseBkgnd函数来进行处理,这会导致用窗口的背景色填充整个窗口。
上述背景重绘之后,接着实现窗口图形的重绘。
如果不断有WM_PAINT消息请求绘图,就总会有窗口背景重绘和图形重绘交替出现。
即造成屏幕图形闪烁有两种情况,屏幕背景刷新与测井图形刷新。
(1)针对背景刷新引起的闪烁,采用了不进行背景重绘的方法来消除。
可以采取如下方法实现不执行系统默认的擦除背景操作:①把系统缺省的背景刷子设置为NULL,那么窗体就不会在刷新屏幕时擦除背景。
可以在重载后窗体的PreCreateWindow函数中实现。
②重载OnEraseBkgnd函数,并在实现该函数时不调用基类函数。
1.1MIDlet低级界面开发技术及应用实例(第2部分)1.1.1双缓冲技术1、双缓冲技术可以解决动画编程中有可能出现的屏幕闪烁问题(1)双缓冲技术是计算机动画的一项传统技术当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象。
因此,为了解决动画编程中有可能出现的屏幕闪烁问题。
而造成屏幕闪烁的主要原因在于,画面在显示的同时程序又在改变它,于是画面闪烁。
(2)双缓冲即在内存中创建一个与屏幕绘图区域一致的对象在内存中开辟一片区域作为后台画面,程序对它更新、修改,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度同时程序修改的将不是正在被显示的图像。
当然还有其他方法可以解决屏幕闪烁问题,但使用双缓冲技术是一种值得推荐的解决方案。
(3)为什么要应用双缓冲常规的图像或者图形创建都是直接在paint()方法中不断调用图形绘制方法。
这样,每画一个图形,系统就会做一次图形的绘制操作,而图形的重绘是很占用系统资源的。
当需要重绘的图形数量很多的时候,所造成的系统开发就特别大,造成我们看到的那种刷新缓慢的情况。
而应用双缓冲技术后,所有的单个图形的绘制都不是真正地调用显示系统来“画”的,所以不会占用显示系统的开销。
2、双缓冲的实现原理双缓冲是基于“空间换时间”,以防止屏幕上的图像单独出现所可能造成的闪烁现象,而改变为一次性地出现。
把电脑屏幕看作一块黑板。
首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕后,再一次性地把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。
采取这种方法不仅可以提高绘图速度,也能够极大地改善绘图的效果,但缺点是消耗内存。
因此,如果设备已经支持双缓冲技术,最好不要再应用它。
3、应用双缓冲的技术实现要点使用双缓冲技术的基本是因为图像会不断改变(为可变图像), 而这个改变并不需要立即反应到屏幕上,操作者只需要看到最后的变化结果。
使用双缓冲的图形可以减少或消除重绘显示图面时产生的闪烁。
使用双缓冲时,更新的图形首先被绘制到内存的缓冲区中,然后,此缓冲区的内容被迅速写入某些或所有显示的图面中。
显示图形的重写相对简短,这通常可以减少或消除有时在更新图形时出现的闪烁。
使用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绘图函数使用的都是逻辑坐标(逻辑范围)**************************************系统默认情况下物理范围和逻辑范围是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做的画图程序,当所画的图形大于屏幕时,在拖动滚动条时屏幕就会出现严重的闪烁,为了解决这一问题,就得使用双缓冲来解决。