GetWindowDC-BeginPaint-GetDC 区别详解

本文详细介绍了GDI绘图函数的基本概念,重点阐述了BeginPaint、EndPaint、GetDC、GetWindowDC函数的使用场景及区别,并深入探讨了设备描述表句柄(HDC)在不同绘图操作中的应用。同时,文章还讲解了CDC、CPaintDCCWindowDCCClientDC类的作用,以及如何正确地使用RECT和CRect结构进行绘图区域的定义和操作。


1. BeginPaint和EndPaint用在WM_PAINT消息处理当中;GetDC可以在处理非WM_PAINT消息时获取设备描述表句柄。 
2. BeginPaint返回的设备描述表句柄只能在PAINTSTRUCT结构中指定的矩形范围内绘图,并使该矩形区域有效;GetDC返回的设备描述表句柄可以在整个窗口客户区上绘图,但不使客户区中任何可能的无效区域变得有效。  

GetWindowDC传回的则是整个窗口的hdc(包括标题栏)

因为存在无效区域,如果是用GETDC来得到地话,程序的 
消息队列中间就会有源源不断地出现WM——PAINT的消息,必须调用VALIDATERECT函 
数,使无效区域变成有效,
但是调用BEGINPAINT中它就自动完成了对后者的调用。

GDI的绘图函数基本上都是有状态的,所有的函数都要求一个HDC类型的句柄。这个HDC的获得有几个途径BeginPaint,GetWindowDC, GetDC.他们的参数都只需要一个HWND就差不多了。记得调用了BeginPaint后要调用EndPaint进行清理,调用GetWindowDC和GetDC后要调ReleaseDC进行清理。在MFC代码中常常遇到的CDC CPaintDC CWindowDC CClientDC。在这里稍作解释。

  CDC :例如用GDI画矩形要Rectangle(hDC,...),而使用CDC则是dc.Rectangle(...),由此可见CDC主要是把原本需要HDC作为参数的GDI函数封装了一下,HDC成了它的一个成员变量

  CPaintDC CWindowDC CClientDC:他们都是从CDC继承,分别是对上面所说的BeginPaint,GetWindowDC, GetDC调用对进行封装(CPaintDC构造时调用BeginPaint,析构时调用EndPaint,其余同理)。

  BeginPaint:一般用在对WM_PAINT的响应函数中使用

  GetWindowDC:可获得整个Window的HDC,而GetDC仅能获得客户区的HDC,区别就在于--

  前者有效地绘制区域是整个窗口(边框、标题栏、客户区的总和)。

  后者有效地绘制区域仅限于客户区。

  两者的坐标系都是相对坐标而非屏幕坐标,原点是(0,0)。即以自己可绘制区域的左上角作为原点。

  这里可以顺带的讲讲RECT了,RECT是一个结构,依次有4个成员left,top,right,bottom用来代表一个矩形区域。CRect从RECT继承,提供了一些常用的操作(例如说位移,缩小等等),其实就是改变4个成员的值。完全不用CRect也可以。许多GDI函数都要求一个RECT作为参数,或者类似的用(x,y,cx,cy)作参数,其实也就是一个RECT变种,用了宽度和高度罢了。

### `GetWindowDC` 与 `GetDC` 的区别 在 Windows API 中,`GetWindowDC` 和 `GetDC` 是用于获取设备上下文(Device Context, DC)的两个关键函数,但它们的使用场景和行为存在显著差异。 `GetWindowDC` 用于获取整个窗口的设备上下文,包括客户区和非客户区(如标题栏、边框等)。该函数返回的 DC 不会受到剪切区域的限制,可以用于绘制整个窗口的任意部分。通常,`GetWindowDC` 在处理 `WM_NCPAINT` 消息时被使用,以实现对非客户区的自定义绘制[^1]。例如: ```cpp HDC hdc = GetWindowDC(hWnd); // 绘制整个窗口区域 ReleaseDC(hWnd, hdc); ``` 相比之下,`GetDC` 仅获取窗口客户区的设备上下文,即仅限于由 `WM_PAINT` 消息更新的区域。该函数返回的 DC 会受到剪切区域的限制,无法绘制非客户区内容。因此,`GetDC` 更适用于客户区的绘制需求,如文本、图形的绘制[^1]。例如: ```cpp HDC hdc = GetDC(hWnd); // 绘制客户区内容 ReleaseDC(hWnd, hdc); ``` 两者的释放方式相同,均需调用 `ReleaseDC` 来释放资源。但它们的使用场景不同:`GetWindowDC` 更适合处理窗口整体绘制(包括非客户区),而 `GetDC` 更适合客户区的局部绘制需求。 ### 相关行为差异 - **客户区 vs 窗口整体**:`GetDC` 仅获取客户区的设备上下文,而 `GetWindowDC` 获取的是整个窗口(包括标题栏、边框)的设备上下文。 - **剪切区域**:`GetDC` 返回的设备上下文会受到剪切区域的限制,仅允许绘制当前需要更新的客户区部分;而 `GetWindowDC` 不受剪切区域限制,可用于绘制整个窗口区域。 - **使用场景**:`GetDC` 通常用于 `WM_PAINT` 消息中绘制客户区内容,而 `GetWindowDC` 常用于 `WM_NCPAINT` 消息中绘制非客户区内容,如自定义边框、标题栏等。 ### 示例代码:`GetWindowDC` 用于非客户区绘制 ```cpp case WM_NCPAINT: { HDC hdc = GetWindowDC(hWnd); RECT rect; GetWindowRect(hWnd, &rect); OffsetRect(&rect, -rect.left, -rect.top); HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0)); // 红色背景 FillRect(hdc, &rect, hBrush); DeleteObject(hBrush); HPEN hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255)); // 蓝色边框 SelectObject(hdc, hPen); RoundRect(hdc, 0, 0, rect.right, rect.bottom, 10, 10); // 圆角边框 DeleteObject(hPen); ReleaseDC(hWnd, hdc); return 0; } ``` 上述代码展示了如何在 `WM_NCPAINT` 消息中使用 `GetWindowDC` 实现非客户区的自定义绘制,包括背景填充和圆角边框绘制。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值