BeginPaint和GetDC的区别.docx_第1页
BeginPaint和GetDC的区别.docx_第2页
BeginPaint和GetDC的区别.docx_第3页
BeginPaint和GetDC的区别.docx_第4页
BeginPaint和GetDC的区别.docx_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2009-04-22 16:30这是个windows编程问题。BeginPaint和GetDC的区别【转第一种情况显示出来的字很正常。* case WM_PAINT: gdc = BeginPaint (hwnd, &ps);TextOut (gdc, 0, 0, s, strlen (s);EndPaint (hwnd, &ps); break;*第二种情况显示的字不停闪烁。* case WM_PAINT: gdc = GetDC (hwnd); TextOut (gdc, 0, 0, s, strlen (s); ReleaseDC (hwnd, gdc); break;*请教两种函数的作用? BeginPaint() 和EndPaint() 可以删除消息队列中的WM_PAINT消息,并使无效区域有效。GetDC()和ReleaseDC()并不删除也不能使无效区域有效,因此当程序跳出 WM_PAINT 时 ,无效区域仍然存在。系统就回不断发送WM_PAINT消息,于是程序不断处理WM_PAINT消息。 相当于BeginPaint、EndPaint会告诉GDI内部,这个窗口需要重画的地方已经重画了,这样WM_PAINT处理完返回给系统后,系统不会再重发WM_PAINT,而GetDC没有告诉系统这个窗口需要重画的地方已经画过,在你把程序返回给系统后,系统一直以为通知你的重画命令你还没有乖乖的执行或者执行出错,所以在消息空闲时,它还会不断地发WM_PAINT催促你画,导致程序卡死。【无效区域】 : 无效区域就是指需要重画的区域,无效的意思是:当前内容是旧的,过时的。假设A是新弹出的一个对话框或被激活的现有对话框,A对话框置于原来的活动对话框B前面,造成对话框B的部分或全部被覆盖,当对话框A移开或关闭后,使对话框B原来被覆盖的地方重新可见。那部分被覆盖的地方就称为无效区域。 只有当一个窗口消息空闲时,系统才会抽空检查一下这个窗口的无效区域是否为非空(WM_PAINT的优先级是最低的。这也就是为什么系统很忙时窗口和桌面往往会出现变白、刷新不了、留拖拽痕迹等现象的原因),如果非空,系统就发送WM_PAINT。所以一定要用BeginPaint、EndPaint把无效区域设为空,否则WM_PAINT将一直被发送。为什么WINDOWS要提出无效区域的概念? 这是为了加速。 因为BeginPaint和EndPaint用到的设备描述符只会在当前的无效区域内绘画,在有效区域内的绘画会自动被过滤,大家都知道,WIN GDI的绘画速度是比较慢的,所以能节省一个象素就节省一个,不用吝啬,这样可以有效加快绘画速度。 可见BeginPaint、EndPaint是比较“被动”的,只在窗口新建时和被摧残时才重画。而GetDC用于主动绘制,只要你指到哪,它就打到哪。它不加判断就都画上去,无效区域跟它没关系。对话框没被覆盖没被摧残,它很健康,系统没要求它重画,但开发者有些情况下需要它主动重画:比如一个定时换外观的窗口,这时候就要在WM_TIMER处理代码用GetDC。这时候再用 BeginPaint、EndPaint的话,会因为无效区域为空,所有绘画操作都将被过滤掉。*eg:1. PAINTSTRUCT ps;2. HDC hdc = Beginpaint(hwnd, &ps); 3. HDC hdcMem = CreateCompatibleDC(hdc); /Create a DC that matches the device4. HANDLE hBmp = LoadImage(g_hInst_MainWnd, MAKEINTRESOURCE(IDB_MAINWND),5. IMAGE_BITMAP, 0, 0, 0);6. HGDIOBJ hOldSel = SelectObject(hdcMem, hBmp); /Select the bitmap into to the compatible 7. /device context8. BITMAP bmp; /Get the bitmap dimensions from the bitmap9. GetObject(hBmp, sizeof(BIMAP), &bmp);10. RECT rc; /Get the window area11. GetClientRect(hwnd, &rc);12. /Copy the bitmap image from the memory DC to the screen DC13. BitBlt(hdc, rc.left, rc.top, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY);14. SelectObject(hdcMem, hOldSel); /Restore original bitmap selection and destroy 15. /the memory DC16. DeleteDC(hdcMem);17. EndPaint(hWnd, &ps);18. return 0;下面是更加详细的介绍/=/TITLE:/ EVC绘制位图-BeginPaint()与GetDC()的区别/AUTHOR:/ norains/DATE:/ Tuesday 29-August-2006/=1.BeginPaint()和GetDC() 在EVC中绘制位图比较方便,有不少现成的函数可供调用,我们所要注意的只是BeginPaint()或GetDC()的使用即可. 因为代码比较简单,所以不做更多解释. 这是消息循环函数: LRESULT CALLBACK MainWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) . switch(wMsg) case WM_PAINT: OnPaintMainWnd(hWnd,wMsg,wParam,lParam); break; . return DefWindowProc(hWnd,wMsg,wParam,lParam); . 响应WM_PAINT消息的函数,在这里进行位图的绘制: LRESULT OnPaintMainWnd(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd,&ps); HDC hdcMem = CreateCompatibleDC(hdc);/Create a DC that matches the device HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE (IDB_MAINWND),IMAGE_BITMAP,0,0,0); /Load the bitmap /Select the bitmap into to the compatible device context HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp); BITMAP bmp; /Get the bitmap dimensions from the bitmap GetObject(hBmp,sizeof(BITMAP),&bmp); RECT rc; /Get the window area GetClientRect(hWnd,&rc);/Copy the bitmap image from the memory DC to the screen DC BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY); SelectObject(hdcMem,hOldSel);/Restore original bitmap selection and destroy the memory /DC DeleteDC(hdcMem); EndPaint(hWnd,&ps); return 0; 我们都知道BeginPaint()和EndPaint()需要配套使用,并且这两个函数也只能用在WM_PAINT消息的相应函数当中.如果我们在 WM_PAINT的响应函数中将以上两个绘制函数相应替换为GetDC()和ReleaseDC()会有什么结果呢? 即: HDC hdc = BeginPaint(hWnd, &ps); - HDC hdc = GetDC(hWnd); EndPaint(hWnd, &ps); - ReleaseDC(hWnd, hdc); 编译并运行程序,我们发现窗口一片空白,好像没有绘制位图.但其实不尽然,我们采用单步调试,可以发现其实位图已经绘制出来,只不过又被背景颜色抹掉了. 由此可知,如果需要使用GetDC(),我们对消息循环函数必须要加上对WM_ERASEBKGND的处理: LRESULT CALLBACK MainWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) switch(wMsg) case WM_PAINT: OnPaintMainWnd(hWnd, wMsg, wParam, lParam); break; case WM_ERASEBKGND : return 0; . return DefWindowProc(hWnd, wMsg, wParam, lParam); 只要系统不对WM_ERASEBKGND进行默认处理,我们用GetDC()替代BeginPaint()就可以正常使用. 至此我们可以看出BeginPaint(),EndPaint()和GetDC(),ReleaseDC()的区别.前一对只能用在WM_PAINT响应函数中,并且绘制背景时不会被抹掉;后一对随处可用,但如果用在WM_PAINT响应函数中,那么接下来将会被WM_ERASEBKGND消息的响应函数的背景绘制给抹掉.2.绘图闪烁问题 有时候我们大量绘制屏幕时,可能会出现屏幕闪烁问题,这时候可以采用双缓冲的做法.步骤首先是创建一个内存DC,然后往内存DC中绘图,最后把内存DC的内容复制到显示DC中,完成绘制.具体过程并不复杂,结合代码来说明一下. PS:这段代码也是响应WM_PAINT 消息的. PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint (hWnd, &ps); /获取屏幕显示DC HDC hdcMem = CreateCompatibleDC(hdc); /创建内存DC /创建一个bmp内存空间 HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp); /将bmp内存空间分配给内存DC /这是使用者需要绘制的画面,全

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论