BeginPaint和GetDC有什么区别?【转】
转自:http://hi.baidu.com/d_b_mike/blog/item/ec8820d0fb9127d5572c84a9.html
这是个windows编程问题。
第一种情况显示出来的字很正常。
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:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
//Create a DC that matches the device
HDC hdcMem = CreateCompatibleDC(hdc);
//Load the bitmap
HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);
//Select the bitmap into to the compatible device context
HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);
//Get the bitmap dimensions from the bitmap
BITMAP bmp;
GetObject(hBmp,sizeof(BITMAP),&bmp);
//Get the window area
RECT rc;
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);
//Restore original bitmap selection and destroy the memory DC
SelectObject(hdcMem,hOldSel);
DeleteDC(hdcMem);
EndPaint(hWnd,&ps);
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);
//Create a DC that matches the device
HDC hdcMem = CreateCompatibleDC(hdc);
//Load the bitmap
HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);
//Select the bitmap into to the compatible device context
HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);
//Get the bitmap dimensions from the bitmap
BITMAP bmp;
GetObject(hBmp,sizeof(BITMAP),&bmp);
//Get the window area
RECT rc;
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);
//Restore original bitmap selection and destroy the memory DC
SelectObject(hdcMem,hOldSel);
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;
//获取屏幕显示DC
hdc = BeginPaint (hWnd, &ps);
//创建内存DC
HDC hdcMem = CreateCompatibleDC(hdc);
//创建一个bmp内存空间
HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);
//将bmp内存空间分配给内存DC
HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);
//这是使用者需要绘制的画面,全部往内存DC绘制
Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
DrawMenuButton(hdcMem);
//将内存DC的内容复制到屏幕显示DC中,完成显示
BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY);
//清除资源
SelectObject(hdcMem,hOldSel);
DeleteDC(hdcMem);
EndPaint(hWnd,&ps);
转载于:https://www.cnblogs.com/cdfyanghua/archive/2009/10/11/1580835.html
BeginPaint和GetDC有什么区别?【转】相关推荐
- BeginPaint和GetDC有什么区别
windows编程问题 第一种情况显示出来的字很正常. case WM_PAINT: gdc = BeginPaint (hwnd, &ps); TextOut (gdc, 0, 0, s, ...
- VC绘制位图--BeginPaint()与GetDC()的区别
//======================================================================== //TITLE: // EVC绘制位图--B ...
- BeginPaint和GetDC的区别
BeginPaint和GetDC的区别 代码 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Gr ...
- Beginpaint 与 GetDC 的区别
InvalidateRect是一个函数,该函数向指定的窗体更新区域添加一个矩形,然后窗体跟新区域的这一部分将被重新绘制. BeginPaint.EndPaint是比较"被动"的,只 ...
- BeginPaint EndPaint 与GetDC ReleaseDC的区别
1. 绘图一般在WM_PAINT消息里面绘图, 一般用BeginPaint( HWND hwnd, LPPAINTSTRUCT lpPaint) 与BOOL EndPaint( HWND hWnd ...
- BeginPaint和GetDC
使用方法: BeginPaint hdc = BeginPaint (hwnd, &ps): // 使用GDI函数 EndPaint (hwnd, &ps); GetDC hdc = ...
- Win32中BeginPaint和GetDC的使用
这是正确的方式,重要的事情说三遍 WM_PAINT: {...hdc = BeginPaint(hWnd, &ps);//hdc = GetDC(hWnd); ... } 1.单独使用GetD ...
- java getdc_GetWindowDC-BeginPaint-GetDC 区别详解
1. BeginPaint和EndPaint用在WM_PAINT消息处理当中:GetDC可以在处理非WM_PAINT消息时获取设备描述表句柄. 2. BeginPaint返回的设备描述表句柄只能在PA ...
- 可视化GDI操作题目
1.GDI是什么的英文缩写? Graphics Device Interface 2.什么是设备的无关性? 操作系统屏蔽了硬件设备的差异 3.GDI的主要任务是什么?起到什么样的作用? 主要任务:负责 ...
最新文章
- 数据结构:基数排序(Radix sort)
- 微软为什么要“杀死”小娜?
- hibernate 表关系映射详解之继承关系
- 如何掌握java API的方法
- 企业实战_13_MyCat清除冗余数据
- 应用程序_构建应用程序12 条参考准则
- Java编写敏感词过滤程序
- google 搜索接口
- 为什么 MongoDB 索引选择B-树,而 Mysql 选择B+树(精干总结)
- VM虚拟机Ubuntu系统鼠标闪烁通用解决办法
- Wi-Fi:802.11 物理层和发射机测量概述
- 「Android基于MQTT实现消息通知」
- android 跳转腾讯地图导航,Android 跳转到百度、高德、腾讯地图导航
- 微信小程序 canvas 分享图片 生成图片
- android目录结构
- U盘在自己电脑读不出来,但其它电脑的可以读,别的u盘在自己电脑又可以识别的解决方法
- linux显卡驱动安全模式,Win7怎么在安全模式下安装显卡驱动?
- 使用 Amazon SageMaker JumpStart 更轻松地在组织内共享 ML 模型和笔记本
- 教训总结(持续更新中)
- 通用Windows驱动程序设计原则DCHU
热门文章
- opencv-api contourArea
- java自定义按钮代码_用于短代码的WP Tiny MCE帖子编辑器上的自定义按钮
- mysql proxy 读写分离_mysql-proxy 实现读写分离
- Java基础学习总结(153)——HashMap、Hashtable、ConcurrentHashMap的原理与区别
- Java设计模式学习总结(11)——结构型模式之装饰器模式
- 生产上线发现重大Bug的思考
- 计算机基础知识背诵口诀,内部资料--教育基础知识背诵口诀(一遍记住)
- java中的static类_再议Java中的static关键字
- saslauthd mysql_Postfix,saslauthd,mysql,smtp身份验证问题
- app头像上传vue_当前GitHub上排名前十的热门Vue项目