1.GDI绘图对象 - 画笔
(1)作用
线的颜色、线型、线粗
(2)使用
a.创建句柄
HPEN CreatePen( int fnPenStyle, //画笔的样式
int nWidth, //画笔的粗细
COLORREF crColor); //画笔的颜色
成功,返回画笔句柄
画笔样式:PS_SOLID - 实线,可支持多个像素宽,其他线型只能是一个像素宽,其他像素则全是实线
PS_DASH - 虚线
PS_DOT - 点线
PS_DASHDOT - 虚线和一个点交替出现
PS_DASHDOTDOT - 虚线和两个点交替出现
b.将画笔应用到DC中
HGDIOBJ SelectObject( HDC hdc, //绘图设备句柄
HGDIOBJ hgdiobj); //GDI绘图对象句柄,画笔句柄
成功,返回原来的GDI绘图对象句柄(注意保存原来DC的画笔)。
c.绘图
d.取出DC中的画笔
将原来的画笔用SelectObject函数放入到设备DC中,就会将我们创建的画笔取出。
e.释放画笔
BOOL DeleteObject( HGDIOBJ hObject);
只能删除不被DC使用的画笔,所以释放前必须将画笔从DC中取出
2.GDI绘图对象 - 画刷
(1)作用
封闭图形的填充颜色、图案
(2)使用
a.创建画刷
//创建实心画刷(给封闭图形填充单一颜色)
HBRUSH CreateSolidBrush( COLORREF crColor);
//创建阴影画刷
HBRUSH CreateHatchBrush( int fnStyle, //阴影线样式
COLORREF clrref); //阴影线颜色
//创建位图画刷
HBRUSH CreatePatternBrush(HBITMAP hbmp);
b.将画刷应用到DC中
c.绘图
d.将画刷从DC中取出
SelectObject
e.删除画刷
DeleteObject
(4)其他
可以使用GetStockObject函数获取系统维护的画刷、画笔等,如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的画刷。
GetStockObjcct返回的画刷不需要DeleteObject
HGDIOBJ GetStockObject( int fnObject );
4.GDI绘图对象 - 位图
(1)位图相关
光栅图形:记录图像中每一个点的颜色等信息
矢量图形:记录图像算法、绘图指令等
(2)使用
a.在资源中添加位图资源
b.从资源中加载位图LoatBitmap
c.创建一个与当前DC相匹配的DC(内存DC)
HDC CreateCompatibleDC( HDC hdc);//当前DC句柄,可以为NULL(使用屏幕DC)
返回创建好的DC句柄
d.将位图放入匹配的DC中
SelectObject
e.成像(1:1)
BOOL BitBlt( HDC hdcDest, //目的DC
int nXDest, //目的左上角X坐标
int nYDest, //目的左上角Y坐标
int nWidth, //目的宽度
int nHeight, //目的高度
HDC hdcSrc, //源DC
int nXSrc, //源左上角X坐标
int nYSrc, //源左上角Y坐标
DWORD dwRop); //成像方法,SRCCOPY
f.取出位图
SelectObject
g.释放位图
DeleteObject
h.释放匹配的DC
DeleteDC
i.其他
使用获取位图信息
int GetObject( HGDIOBJ hgdiobj, //绘图对象句柄
int cbBuffer, //缓冲区大小
LPVOID lpvObject); //缓冲区地址
(3)缩放
BOOL BitBlt( HDC hdcDest, //目的DC
int nXDest, //目的左上角X坐标
int nYDest, //目的左上角Y坐标
int nWidth, //目的宽度
int nHeight, //目的高度
HDC hdcSrc, //源DC
int nXSrc, //源左上角X坐标
int nYSrc, //源左上角Y坐标
int nWidth, //源宽度
int nHeight, //源高度
DWORD dwRop); //成像方法,SRCCOPY
相关示例代码:

#include "stdafx.h" HINSTANCE g_hInstance = 0; //接收当前程序实例句柄 int g_kind = 0;//标志量 void OnCommand(HWND hWnd, WPARAM wParam) { g_kind = LOWORD(wParam); switch (LOWORD(wParam)) { case ID_PT: case ID_LINE: case ID_RECT: case ID_ELL: case ID_ARC: case ID_BMP: InvalidateRect(hWnd, NULL, TRUE); break; } } void DrawPoint(HDC hdc) { for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { SetPixel(hdc, i, j, RGB(i, j, 0)); } } } void DrawLine(HDC hdc) { MoveToEx(hdc, 100, 100, NULL); LineTo(hdc, 300, 300); LineTo(hdc, 0, 300); LineTo(hdc, 100, 100); } void DrawRec(HDC hdc) { Rectangle(hdc, 100, 100, 300, 300); RoundRect(hdc, 300, 100, 500, 300, 200, 200); } void DrawEll(HDC hdc) { Ellipse(hdc, 100, 100, 300, 300); Ellipse(hdc, 300, 100, 600, 300); } void DrawArc(HDC hdc) { SetArcDirection(hdc, AD_CLOCKWISE);//顺时针取弧 Arc(hdc, 100, 100, 300, 300, 100, 100, 300, 300); } void DrawBmp(HDC hdc) { //1.添加位图资源 //2.加载位图 HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); //动态获取位图的信息 BITMAP bmpInfo = { 0 }; GetObject(hBmp, sizeof(bmpInfo), &bmpInfo); //3.创建一个与当前DC相匹配的DC //创建了一个内存DC,同时在内存中构建了一个虚拟区域 //本质是:创建了一个内存DC,同时申请相应大小的一块内存 HDC hMemdc = CreateCompatibleDC(hdc); //4.将位图放入匹配的DC中 //将图片送给内存DC后,内存DC会立即将图片在虚拟区域中 绘制出来 //本质是:将图片的数据扔到内存DC找到的那块内存中 HGDIOBJ nOld = SelectObject(hMemdc, hBmp); //5.成像 //将内存中图片的数据一次性拷贝到显存中 BitBlt(hdc, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, hMemdc, 0, 0, SRCCOPY); //缩放成像 StretchBlt(hdc, 100, 100, 96, 96, hMemdc, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY); //6.取出位图 SelectObject(hMemdc, nOld); //7.释放位图 DeleteObject(hBmp); //8.释放匹配的DC DeleteDC(hMemdc); } void OnPaint(HWND hWnd) { PAINTSTRUCT pt = { 0 }; HDC hdc = BeginPaint(hWnd, &pt); //当前DC,在窗口中画图 HPEN hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0)); HGDIOBJ nOldPen = SelectObject(hdc, hPen); //创建绿色实心画刷 //HBRUSH hBrush = CreateSolidBrush(RGB(0, 255, 0)); //创建绿色水平垂直线阴影画刷 HBRUSH hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0)); //得到透明画刷 //HGDIOBJ hBrush = GetStockObject(NULL_BRUSH); //HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); //HBRUSH hBrush = CreatePatternBrush(hBmp); HGDIOBJ nOldBrush = SelectObject(hdc, hBrush); switch (g_kind) { case ID_BMP: DrawBmp(hdc);//绘制位图 break; case ID_ARC: DrawArc(hdc);//绘制弧线 break; case ID_ELL: DrawEll(hdc);//绘制圆 break; case ID_RECT: DrawRec(hdc);//绘制矩形 break; case ID_LINE: DrawLine(hdc);//绘制直线 break; case ID_PT: DrawPoint(hdc);//绘制点 break; } SelectObject(hdc, nOldPen); DeleteObject(hPen); SelectObject(hdc, nOldBrush); DeleteObject(hBrush); EndPaint(hWnd, &pt); } //窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_PAINT: OnPaint(hWnd); break; case WM_COMMAND: OnCommand(hWnd, wParam); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } //注册窗口类 BOOL Register(LPSTR lpClassName, WNDPROC wndProc) { WNDCLASSEX wce = { 0 }; wce.cbSize = sizeof(wce); wce.cbClsExtra = 200; wce.cbClsExtra = 200; wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3); wce.hCursor = NULL; wce.hIcon = NULL; wce.hIconSm = NULL; wce.hInstance = g_hInstance; wce.lpfnWndProc = wndProc; wce.lpszClassName = lpClassName; wce.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wce.style = CS_HREDRAW | CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce); if (0 == nAtom) { return FALSE; } return TRUE; } //创建主窗口 HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName) { HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL); return hWnd; } //显示窗口 void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } //消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; Register("Main", WndProc); HWND hWnd = CreateMainWindow("Main", "window"); Display(hWnd); Message(); return 0; }
运行结果:
(1)虚线画笔
(2)横竖线画刷
(3)位图成像和缩放