Paul M Watt系列文章要点翻译<一>:Guide to WIN32 Paint for Beginners
来源:互联网 发布:淘宝价格变化 编辑:程序博客网 时间:2024/06/07 10:22
本文英文原版见http://www.codeproject.com/Articles/1988/Guide-to-WIN-Paint-for-Beginners
1.介绍
略
2.Device Context设备上下文
浅显的说,DC是用来绘制的画布。同时,DC也是操作系统的资源,用来在显示器上绘制图形的画笔、画刷和字体等等均属于DC范畴。DC是Windows系统图形设备接口的抽象层,对于开发者而言,它屏蔽了显示设备的具体实现细节。通过使用并初始化不同的DC,可以使用相同的代码和方法在屏幕、打印机、甚至内存位图上进行绘制。相比于直接操作视频卡、打印机驱动而言,这种方式对于开发者而言更加简洁高效。
DC分为三大类:
- Client DC 客户区DC:一个特定的窗口拥有一个客户区DC,对于开发者而言对于目标窗口具有对客户区DC的访问权限。客户区DC对于开发者而言也是使用最为频繁和重要的DC。当产生WM_PAINT消息时,客户区DC就可以获得;
- Window DC 窗口DC:一个特定的窗口拥有一个窗口DC,该DC允许开发者绘制窗口的任何部分,包括窗口边框及标题。当WM_NCPAINT消息产生时,窗口DC就可以获得;
- Memory DC 内存DC:该DC只存在于内存中,不和窗口绑定。该DC也是唯一一种能操作用户定义位图的DC。内存DC在缓存图像、后台缓冲、复杂图形绘制上极为有效;
- General Device DC 一般设备DC:绘图仪、打印机、监视器采用该DC。
3.Obtaining a Client Device Context获得客户区设备上下文
在使用Win32 Paint API时,经常需要获取一个DC句柄。任何一种类型的DC关于其描述均存储在一个HDC中。
对于MFC框架或WTL框架而言,DC的基类是CDC,CDC持有HDC。CPaintDC和CClientDC则继承自CDC类,它们具有各自特殊的用途。
3.1 BeginPaint获取Client DC
BeginPaint是一种普遍的创建DC的方式,但是该函数只能在WM_PAINT消息句柄中使用!这是因为BeginPaint会使窗口无效或过期的区域有效,当某一窗口存在无效区域时,WM_PAINT消息会产生通知窗口重绘此无效区域。如果在WM_PAINT句柄函数之外调用BeginPaint,任何无效的窗口去将变得有效,此时将不会有WM_PAINT消息产生!对于像subclass控件的人而言,存在一些副作用。
此外,当调用BeginPaint时,如果有必要的话Windows会产生WM_ERASEBKGND和WM_NCPAINT消息。如果在WM_PAINT之外调用BeginPaint,你地窗口边框可能不会正常更新。
调用BeginPaint的示例:
PAINTSTRUCT ps;HDC hdc;hdc = ::BeginPaint(hWnd, &ps);释放由BeginPaint获得的Client DC的函数是EndPaint。BeginPaint将调用HideCursor将鼠标指针隐藏,EndPaint在结束绘制后将鼠标指针再设成可见。如果在调用BeginPaint后不调用EndPaint将会隐藏鼠标指针。
调用EndPaint的示例:
::EndPaint(hWnd, &ps);对于MFC和WTL框架而言,Client DC的获取和释放是在CPaintDC类的构造和析构函数中自动完成的。在栈上创建一个CPaintDC对象的实例,该DC也会自动销毁。CPaintDC的构造和析构函数代码如下。
CPaintDC::CPaintDC(CWnd* pWnd){ ... if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps))) AfxThrowResourceException();}CPaintDC::~CPaintDC(){ ... ::EndPaint(m_hWnd, &m_ps); Detach();}
3.2 GetDC/GetDCEx获取Client DC
另外一种获取客户区DC的方式是通过调用GetDC/GetDCEx。GetDCEx还允许设置一个裁剪区域,这样GetDCEx将不会绘制这些裁剪区域。
GetDC在WM_PAINT句柄函数之外使用很频繁。当需要绘制一些图形时,可以通过GetDC获取DC,这些图形往往不是目标窗口所具有的永久性的图形。比如,在Zoom in和Zoom out操作时用鼠标拉出的像橡皮筋一样的选择区域框,还比如选择一个窗口中的多个对象时的效果,这些图形或效果并不是永久存在的。
通过调用GetDC获得DC和释放DC的一个示例:
HDC hdc;hdc = GetDC(hWnd);...::ReleaseDC(hWnd, hdc);GetDC和ReleaseDC封装在MFC和WTL框架的CClientDC类中。
CClientDC::CClientDC(CWnd* pWnd){ ... if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd()))) AfxThrowResourceException();}CClientDC::~CClientDC(){ ... ::ReleaseDC(m_hWnd, Detach());}
4.使用DC
使用DC非常方便,下面是采用不同的GDI函数使用DC 的示例:
Rectangle(hdc, 100, 100, 200, 300);Ellipse(hdc, 100, 100, 200, 300);TCHAR szMessage[] = "Paint Beginner";UINT nLen = _tcslen(szMessage);TextOut(hdc, 100, 325, szMessage, nLen);对于CPaintDC而言:
CPaintDC dc;dc.Rectangle(10, 10, 150, 200);对于ClientDC而言:
CClientDC dc;dc.Rectangle(10, 10, 150, 200);
5.例程
该例子程序使用了两种获取DC的方式1.BeginPaint:用户在WM_PAINT消息句柄中绘制客户区
2.GetDC:用于绘制鼠标按下左键拖动时的橡皮筋效果
在绘制橡皮筋效果时,采用了DC模式的概念,将DC模式设置为R2_NOT后,第二次相同的绘制操作将会完全清除第一次的绘制操作,从而消除第一次的绘制!
在绘制橡皮筋效果时,采用了DC模式的概念,将DC模式设置为R2_NOT后,第二次相同的绘制操作将会完全清除第一次的绘制操作,从而消除第一次的绘制!
void DrawRubberBand(HWND hWnd){ HDC hdc; //C: Get a client DC. hdc = ::GetDC(hWnd); //C: Set the current drawing mode to XOR, this will allow us // to add the rubber band, and later remove it by sending the // exact same drawing command. ::SetROP2(hdc, R2_NOT); //C: Select a NULL Brush into the DC so that no fill is performed. ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); //C: Get the current shape mode. HMENU hMenu = ::GetMenu(hWnd); HMENU hShapeMenu = ::GetSubMenu(hMenu, 1); if (::GetMenuState(hShapeMenu, ID_SHAPE_RECTANGLE, MF_BYCOMMAND) & MF_CHECKED) { ::Rectangle( hdc, ptStart.x, ptStart.y, ptCurrent.x, ptCurrent.y ); } else { ::Ellipse( hdc, ptStart.x, ptStart.y, ptCurrent.x, ptCurrent.y ); } //C: Release the DC. ::ReleaseDC(hWnd, hdc);}具体可研究一下代码。
0 0
- Paul M Watt系列文章要点翻译<一>:Guide to WIN32 Paint for Beginners
- Hacking for beginners_A hacking guide for beginners
- Hacking for beginners_A hacking guide for beginners
- Absolute Beginner's Guide to Microsoft® Office 2003系列翻译(一)
- A guide to Matlab for Beginners and Experienced Users——学习笔记【1】
- A guide to Matlab for Beginners and Experienced Users——学习笔记【2】
- Git for beginners: The definitive practical guide
- Chapter 0 – UVM Guide for Beginners
- Simple guide to forks in GitHub and Git文章翻译
- Google Developing for Android系列文章翻译
- (翻译)Simple MEF Application for Beginners
- Dynamic Range Compression- Basic Tutorial Guide for Beginners
- Beginners guide to accessing SQL Server through C#
- Beginners guide to accessing SQL Server through C#
- Beginners Guide to Getting Started with AS3 (Without Learning Flex)
- PHP This! A Beginners Guide To Learning Object Oriented PHP
- Unity for Absolute Beginners(一)
- 开始翻译Windows Phone 8 Development for Absolute Beginners教程
- 内存DDR预读取
- 珍惜现在
- 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)
- QQ使用了什么通讯协议?为什么要这样做?为什么采用 UDP 协议,而不采用 TCP 协议实现?
- php 帕斯卡命名转换成下划线分割命名
- Paul M Watt系列文章要点翻译<一>:Guide to WIN32 Paint for Beginners
- Activity启动模式详解
- 深入理解django的Urls分发
- js获取img路径src
- android翻页动画
- 每周linux学习(1) --- 杂文
- 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现)
- (转) android MediaPlayer API 详解
- dup and dup2剖析