文章目录
- 一、获取指定窗口的设备上下文
- 二、画笔的介绍和使用
- 三、绘制直线
- 四、画刷的介绍和使用
- 五、绘制扇形
- 六、绘制圆形
- 七、绘制文本
一、获取指定窗口的设备上下文
1.GetDC()函数的作用
GetDC() 是 Windows API 中的一个函数,它用于获取指定窗口的设备上下文(Device Context,简称 DC)。设备上下文是 GDI(图形设备接口)用于绘图的关键对象,它封装了与设备(如屏幕或打印机)相关的绘图信息。
函数原型:
HDC GetDC(HWND hWnd);
参数:
- hWnd:指定窗口的句柄。如果 hWnd 为 NULL,则返回整个屏幕的设备上下文(相当于桌面)。否则,返回指定窗口的设备上下文。
返回值:
- 成功:返回指定窗口的设备上下文句柄(HDC)。
- 否则,返回指定窗口的设备上下文。
用法:
GetDC() 主要用于获取窗口的 DC,以便进行绘图操作。一般用于:
- 在窗口客户区绘图(不包括标题栏、菜单栏等)。
- 获取屏幕 DC 进行全屏截图等操作。
2.获取屏幕DC进行截图
在窗口客户区绘图:
#include <windows.h>LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) {case WM_PAINT: {PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps); // 获取DCTextOut(hdc, 50, 50, L"Hello, Windows!", 15); // 绘制文本EndPaint(hWnd, &ps); // 释放DCbreak;}case WM_LBUTTONDOWN: {HDC hdc = GetDC(hWnd); // 获取窗口DCTextOut(hdc, 100, 100, L"Mouse Click!", 12); // 绘制文本ReleaseDC(hWnd, hdc); // 释放DCbreak;}case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}
说明:
- GetDC(hWnd) 直接获取窗口的 DC,不用 BeginPaint(),适用于即时绘图(如鼠标点击)。
- 用完 DC 后,必须调用 ReleaseDC(hWnd, hdc); 释放它,否则会导致资源泄露。
获取屏幕 DC 进行截图:
HDC hScreenDC = GetDC(NULL); // 获取整个屏幕的DC
HDC hMemDC = CreateCompatibleDC(hScreenDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, 1920, 1080);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, 1920, 1080, hScreenDC, 0, 0, SRCCOPY);
ReleaseDC(NULL, hScreenDC);
DeleteDC(hMemDC);
说明:
- GetDC(NULL) 获取整个屏幕的 DC。
- BitBlt() 将屏幕内容拷贝到 hMemDC 进行截图。
- 使用完 DC 后,需要调用 ReleaseDC() 释放它。
注意事项:
- GetDC() 只适用于客户区绘图,如果要绘制整个窗口(包括非客户区,如标题栏),请用 GetWindowDC()。
- 必须调用 ReleaseDC() 释放 DC,GetDC() 分配的 DC 需要 ReleaseDC() 释放,否则会导致资源泄露。
- 与 BeginPaint() 的区别:GetDC() 适用于即时绘图,适合响应鼠标事件等。BeginPaint() 仅在 WM_PAINT 处理时使用,并会自动更新无效区域,适用于窗口重绘。
二、画笔的介绍和使用
CPen 是 MFC(Microsoft Foundation Class) 提供的一个 GDI(图形设备接口)对象,用于在 Windows 应用程序中创建和管理画笔(Pen)。画笔用于绘制直线、边框、曲线 等图形元素。
1. CPen 类的基本介绍
CPen 继承自 CGdiObject,用于定义画笔的颜色、线条样式和宽度,并可以与 CDC(设备上下文)一起使用进行绘图。
2. CPen 的构造函数
CPen(int nPenStyle, int nWidth, COLORREF crColor);
参数说明:
- nPenStyle:线条样式,如 实线、虚线、点线 等(见下表)。
- nWidth:线条宽度(像素)。
- crColor:颜色,使用 RGB(r, g, b) 指定。
3. 线条样式 (nPenStyle)
4. CPen 的使用
(1)创建和使用画笔
void CMyView::OnDraw(CDC* pDC) {// 创建一个红色、2 像素宽的实线画笔CPen pen(PS_SOLID, 2, RGB(255, 0, 0));// 选择画笔,并保存旧画笔CPen* pOldPen = pDC->SelectObject(&pen);// 画一条直线pDC->MoveTo(50, 50);pDC->LineTo(200, 200);// 恢复旧画笔pDC->SelectObject(pOldPen);
}
说明:
- SelectObject(&pen) 选择新画笔,并返回旧画笔指针(必须恢复)。
- MoveTo(x, y) 移动到起点。
- LineTo(x, y) 画一条直线。
(2)使用 CPen 变量
void CMyView::OnDraw(CDC* pDC) {CPen bluePen(PS_DOT, 3, RGB(0, 0, 255)); // 蓝色点线,3px 宽CPen* pOldPen = pDC->SelectObject(&bluePen);pDC->Ellipse(50, 50, 200, 200); // 画一个椭圆pDC->SelectObject(pOldPen); // 恢复原画笔
}
(3)使用 CreatePen()
void CMyView::OnDraw(CDC* pDC) {CPen pen;pen.CreatePen(PS_DASHDOT, 5, RGB(0, 255, 0)); // 绿色虚点线,5px 宽CPen* pOldPen = pDC->SelectObject(&pen);pDC->Rectangle(100, 100, 300, 300); // 画一个矩形pDC->SelectObject(pOldPen);
}
(4)创建 LOGBRUSH 自定义画笔
void CMyView::OnDraw(CDC* pDC) {LOGBRUSH lb;lb.lbStyle = BS_SOLID; // 纯色填充lb.lbColor = RGB(255, 165, 0); // 橙色lb.lbHatch = 0; CPen pen;pen.CreatePen(PS_SOLID | PS_ENDCAP_ROUND, 10, &lb); // 圆头 10px 画笔CPen* pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(50, 50);pDC->LineTo(300, 50);pDC->SelectObject(pOldPen);
}
5. CPen 使用注意事项
- 必须恢复旧画笔:SelectObject() 之前存储旧画笔,绘制完毕后恢复它,避免影响后续绘图。
- 不要在 OnPaint() 中创建临时 CPen 对象:CPen 对象应在 OnDraw() 或 OnPaint() 内部创建并销毁,避免资源泄漏。
- CPen 对象生存期要合理:如果是临时画笔,直接在 OnDraw() 里使用,不要 new 分配。若 CPen 需要在多个函数中使用,应定义为 成员变量,避免频繁创建销毁。
三、绘制直线
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 画线// 获得设备上下文CDC* pDC = GetDC();// 画笔移动到起始点pDC->MoveTo(m_pOrigin);// 从起点到终点画一条直线pDC->LineTo(point);// 释放设备上下文ReleaseDC(pDC);CWnd::OnLButtonUp(nFlags, point);
}
结果展示:
四、画刷的介绍和使用
CBrush 是 MFC(Microsoft Foundation Classes)提供的 GDI(图形设备接口) 对象之一,用于创建和管理 画刷(Brush)。画刷主要用于填充图形的 内部区域,例如填充矩形、椭圆、圆形、区域等。
1. CBrush 类的基本介绍
CBrush 继承自 CGdiObject,用于定义画刷的 颜色、填充模式和样式,并可与 CDC(设备上下文)一起使用进行绘图。
2. CBrush 的构造函数
CBrush(COLORREF crColor);
CBrush(int nIndex, COLORREF crColor);
CBrush(int nStyle, COLORREF crColor);
CBrush(int nStyle, CBitmap* pBitmap);
参数说明:
- crColor:画刷的颜色(使用 RGB(r, g, b) 指定)。
- nIndex:系统颜色索引(如 COLOR_WINDOW)。
- nStyle:画刷样式(如 HS_DIAGCROSS、HS_HORIZONTAL)。
- pBitmap:用于创建 位图画刷 的 CBitmap 指针。
3. CBrush 画刷样式
4. CBrush 的使用
(1)创建纯色画刷
void CMyView::OnDraw(CDC* pDC) {CBrush brush(RGB(255, 0, 0)); // 创建红色画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 200, 200); // 画填充矩形pDC->SelectObject(pOldBrush); // 恢复旧画刷
}
说明:
- SelectObject(&brush) 选择画刷,并返回原来的画刷(后续需要恢复)。
- Rectangle(x1, y1, x2, y2) 使用画刷填充矩形。
(2)创建带有样式的画刷
void CMyView::OnDraw(CDC* pDC) {CBrush brush(HS_CROSS, RGB(0, 255, 0)); // 绿色十字交叉填充CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Ellipse(50, 50, 200, 200); // 画填充椭圆pDC->SelectObject(pOldBrush);
}
常见 HS_ 样式:
(3)创建 CreateSolidBrush()
void CMyView::OnDraw(CDC* pDC) {CBrush brush;brush.CreateSolidBrush(RGB(0, 0, 255)); // 创建蓝色画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(100, 100, 300, 300); // 填充矩形pDC->SelectObject(pOldBrush);
}
说明:
- CreateSolidBrush(RGB(0,0,255)) 以指定颜色创建画刷。
- 适用于动态创建 画刷的情况。
(4)创建位图填充画刷
void CMyView::OnDraw(CDC* pDC) {CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1); // 加载资源中的位图CBrush brush;brush.CreatePatternBrush(&bitmap); // 创建位图画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 250, 250); // 用位图填充矩形pDC->SelectObject(pOldBrush);
}
说明:
- CreatePatternBrush(&bitmap) 使用位图创建画刷,适用于 纹理填充。
- LoadBitmap(IDB_BITMAP1) 加载 资源位图,IDB_BITMAP1 需要在 资源管理器 中定义。
(5)结合 CPen 和 CBrush 使用
void CMyView::OnDraw(CDC* pDC) {CPen pen(PS_SOLID, 2, RGB(0, 0, 255)); // 蓝色边框CBrush brush(RGB(255, 255, 0)); // 黄色填充CPen* pOldPen = pDC->SelectObject(&pen);CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 200, 200); // 画填充的矩形pDC->SelectObject(pOldPen);pDC->SelectObject(pOldBrush);
}
说明:
- CPen 负责边框颜色,CBrush 负责填充颜色。
- Rectangle(x1, y1, x2, y2) 画出填充的矩形。
5. CBrush 使用注意事项
- 必须恢复旧画刷:SelectObject() 返回旧画刷,需要在绘制完成后恢复它,避免影响后续绘图。
- 不要在 OnPaint() 中创建临时 CBrush:CBrush 应该在 OnDraw() 或 OnPaint() 内部创建并销毁,以避免资源泄露。
- 使用 CreateSolidBrush() 动态创建画刷:如果 CBrush 需要在多个函数中使用,推荐 使用成员变量 避免重复创建。
五、绘制扇形
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CWnd::OnLButtonUp(nFlags, point);
}void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_bDraw) {CClientDC dc(this);dc.MoveTo(m_pOrigin);dc.LineTo(point);m_pOrigin = point;}CWnd::OnMouseMove(nFlags, point);
}
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CWnd::OnLButtonUp(nFlags, point);
}void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_bDraw) {CClientDC dc(this);CPen pen(PS_SOLID, 1, RGB(0, 255, 255));CPen* pOldPen = dc.SelectObject(&pen);dc.MoveTo(m_pOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);}CWnd::OnMouseMove(nFlags, point);
}
六、绘制圆形
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CClientDC dc(this);CPen pen(PS_DASH, 1, RGB(0, 0, 255));CPen* pOldpen = dc.SelectObject(&pen);// 画椭圆//dc.Ellipse(CRect(m_pOrigin, point));// 计算两点之间x坐标的差值long len = point.x - m_pOrigin.x;dc.Ellipse(m_pOrigin.x, m_pOrigin.y, m_pOrigin.x + len, m_pOrigin.y + len);dc.SelectObject(pOldpen);CWnd::OnLButtonUp(nFlags, point);
}
七、绘制文本
void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{CString str(_T("你好我好大家好!"));CClientDC dc(this);CFont font;// 设置字体font.CreatePointFont(200, _T("宋体"));CFont* pOldFont = dc.SelectObject(&font);// 设置文字颜色dc.SetTextColor(RGB(125, 0, 127));// 输出字符串dc.TextOutW(point.x, point.y, str);dc.SelectObject(pOldFont);CWnd::OnLButtonUp(nFlags, point);
}