一、GDI简介
1)什么是设备上下文
2)设备上下文类型
3)常见的GDI对象
4)windows坐标系
5)GDI绘图步骤
二、获取DC的3种方法
1)获取DC的3种方法
2)PAINTSTRUCT结构
3)BeginPaint函数
4)EndPaint函数
5)GetDC函数
6)GetWindowDC函数
7)三种方式的区别
8)代码实例
#include<windows.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_PAINT: { //1.使用BeginPaint,它能将无效区域变成有效(如果存在无效区域,系统会一直发送WM_PAINT) /*PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 0, 0, L"你好啊!", lstrlen(L"你好啊!")); EndPaint(hWnd, &ps);*/ //2.使用GetDC获取客户区DC,它并不能将无效区域变成有效,所以WM_PAINT一直发送,文字一直闪烁 /* HDC hdc = GetDC(hWnd); TextOut(hdc, 0, 0, L"你好啊!", lstrlen(L"你好啊!")); ReleaseDC(hWnd, hdc); //return 0; //去掉之后交给默认DefWindowProc处理WM_PAINT消息,会调用BeginPaint,EndPaint */ } break; case WM_NCPAINT: { //3.获取整个窗口的DC,包括标题栏,工具条等 HDC hdc = GetWindowDC(hWnd); RECT r = {0,0,400,20}; HBRUSH brh = CreateSolidBrush(RGB(255, 0, 0)); FillRect(hdc, &r, brh); DeleteObject(brh); ReleaseDC(hWnd, hdc);//释放掉DC return true; }break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
三、绘图函数
1)创建画笔
2)选择一个对象到数据上下文
3)画直线
4)画矩形
5)创建画刷
6)DeleteObject函数
7)GetStockObject函数
8)画椭圆
9)画饼图
10)写入字符串
11)SetBkColor函数
12)SetBkMode函数
13)DrawText函数
14)SetTextAlign函数
15)代码实例
①绘制直线、矩形、椭圆、饼图
#include<windows.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_PAINT: { PAINTSTRUCT ps; //获取设备上下文句柄 HDC hdc = BeginPaint(hWnd, &ps); //创建画笔 HPEN hPen = CreatePen(PS_DASHDOT, 1, RGB(255, 0, 0)); //将笔选入到设备上下文(使用这支笔) SelectObject(hdc, hPen); //1.画直线(两个点) MoveToEx(hdc, 100, 100, NULL); LineTo(hdc, 200, 100); //创建画刷 HBRUSH hBsh = CreateSolidBrush(RGB(0, 255, 0)); //将画刷选入到设备上下文(使用这支画刷) SelectObject(hdc, hBsh); //2.画矩形(正方形) Rectangle(hdc, 200, 200, 400, 400); //获取透明画刷 HGDIOBJ hBsh2 =GetStockObject(NULL_BRUSH); SelectObject(hdc, hBsh2); Rectangle(hdc, 100, 100, 200, 150); //3.画椭圆(圆形) Ellipse(hdc, 200, 200, 400, 400); Ellipse(hdc, 100, 100, 200, 150); //4.画饼图 /* //饼图产生的步骤分解 Ellipse(hdc, 500, 100, 800, 400); //从圆心到第一个点的连线 MoveToEx(hdc, 650, 250, NULL); LineTo(hdc,1000, 300); //从圆心到第二个点的连线 MoveToEx(hdc, 650, 250, NULL); LineTo(hdc, 400, 400); */ Pie(hdc, 500, 100, 800, 400, 1000, 300,400, 400); //删除GDI对象 DeleteObject(hPen); DeleteObject(hBsh); EndPaint(hWnd, &ps); } break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 1000, 700, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
②写入字符串
#include<windows.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_PAINT: { PAINTSTRUCT ps; //获取设备上下文句柄 HDC hdc = BeginPaint(hWnd, &ps); //改变文本的背景色 SetBkColor(hdc, RGB(255, 0, 0)); //设置文本背景模式 SetBkMode(hdc, TRANSPARENT);//透明 //设置文本的颜色 SetTextColor(hdc, RGB(255, 0, 0)); //设置文本的参考点 SetTextAlign(hdc, TA_TOP); //1.界面上画文本 TextOut(hdc,250, 200, L"你好啊,这是画的文本!", lstrlen(L"你好啊,这是画的文本!")); //2.在矩形范围中画文本 RECT r = {250,400,300,500}; Rectangle(hdc, r.left, r.top, r.right, r.bottom); DrawText(hdc, L"你好啊,这是画的文本!", lstrlen(L"你好啊,这是画的文本!") , &r, DT_BOTTOM|DT_SINGLELINE); EndPaint(hWnd, &ps); } break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 1000, 700, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
四、双缓冲绘制技术
1)什么是双缓冲绘制技术
2)步骤
3)CreateCompatiableDC函数
4)CreateCompatiableBitmap函数
5)BitBlt函数
6)StretchBlt函数
7)代码实例
#include<windows.h> #include<CommCtrl.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); //1.创建兼容内存DC,此时它的大小时1X1,很小,不能绘制 HDC hMemDC=CreateCompatibleDC(hdc); //2.创建兼容位图,提供绘画区域 HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, 100, 100); //3.把兼容位图选到兼容内存DC中,此刻DC的大小与位图一致,可以绘制 SelectObject(hMemDC, hMemBmp); //4.在兼容内存DC上进行绘图操作 SetTextColor(hMemDC, RGB(255, 0, 0)); TextOut(hMemDC, 0, 0, L"双缓冲技术绘制!", lstrlen(L"双缓冲技术绘制!")); Rectangle(hMemDC, 30, 30, 80, 80); //5.把内存DC中的图像一次性画到窗口DC上 //不拉伸 BitBlt(hdc, 0, 0, 100, 100, hMemDC, 0, 0, SRCCOPY); //拉伸(目标矩形大于源矩形) StretchBlt(hdc, 0, 0, 400, 400, hMemDC, 0, 0,100,100, SRCCOPY); //压缩(目标矩形小于源矩形) StretchBlt(hdc, 0, 0, 50, 50, hMemDC, 0, 0, 100, 100, SRCCOPY); //释放资源 DeleteDC(hMemDC); DeleteObject(hMemBmp); EndPaint(hWnd, &ps); } break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
五、绘制位图
1)什么是位图
2)位图绘制的步骤
3)LoadImage函数
4)SetStrechBltMode函数
5)代码实例
#include<windows.h> #include<CommCtrl.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); //1.创建内存兼容DC(1px X 1px) HDC hMemDC = CreateCompatibleDC(hdc); //2.加载位图资源 HBITMAP hBmp= (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 800, 800, LR_LOADFROMFILE); //3.把位图选入到兼容内存DC SelectObject(hMemDC, hBmp); //添加水印 TextOut(hMemDC, 100, 100, L"乱涂乱画", lstrlen(L"乱涂乱画")); //设置图像拉伸模式 //SetStretchBltMode(hdc, COLORONCOLOR);//删除多余像素 SetStretchBltMode(hdc, HALFTONE); //4.将兼容DC中的图像一次性拷贝到窗口DC上 //BitBlt(hdc, 0, 0, 800, 800, hMemDC, 0, 0, SRCCOPY); //完整显示 StretchBlt(hdc, 0, 0, 400, 400, hMemDC, 0, 0, 800,800,SRCCOPY); //5.释放DC与位图资源 DeleteObject(hBmp); DeleteDC(hMemDC); EndPaint(hWnd, &ps); } break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }