在上一篇中,我们说到了通过GdipCreateFromHDC函数将HDC(设备上下文句柄)装换成GDI+的Graphics对象,并讲到了画笔的使用,这一篇就来讲讲画刷。
画刷和画笔差不多,就是画刷是画的实心的图形、
其实画刷有很多种,这里只介绍最常用的两种,分别是单色画刷和线性渐变画刷
还是和以前一样,我们必须自己声明GDI+Flat函数,自己定义GDI+Flat的数据结构。自己动手,丰衣足食。~~
对于画刷的创建和销毁,其实是GDI+调用的GDI+Flat的这几个函数:GdipCreateSolidFill、GdipCreateLineBrush和GdipDeleteBrush
我们把这两个函数自己声明出来!不用那些GDI+类的东西!只用C和Win32的最基本的数据类型!
//画刷 typedef struct _PointF{ float x; float y; }PointF; extern "C" int WINAPI GdipCreateSolidFill(unsigned int argb_color,int** brush); extern "C" int WINAPI GdipCreateLineBrush(PointF* point1, PointF* point2, unsigned int argb_color1,unsigned int argb_color2,int wrapMode,int** lineGradient); extern "C" int WINAPI GdipDeleteBrush(int* brush);
GdipCreateSolidFill:创建单色画刷
参数1:画刷的ARGB颜色
参数2:指向一个画刷的指针,用于接收返回的画刷,画刷是int*
GdipCreateLineBrush:创建线性渐变画刷
参数1:起点坐标,是我上面定义的PointF结构,PointF结构中:x为横坐标,y为纵坐标
参数2:终点坐标,是我上面定义的PointF结构,PointF结构中:x为横坐标,y为纵坐标
参数3:画刷的起点ARGB颜色
参数4:画刷的终点ARGB颜色
参数5:wrapMode 包围模式:WrapModeTile=0,WrapModeTileFlipX=1,WrapModeTileFlipY=2,WrapModeTileFlipXY=3,WrapModeClamp=4
其中0最为常用,为“平铺模式“。MSDN:https://msdn.microsoft.com/en-us/library/ms534407(v=vs.85).aspx
参数6:指向一个画刷的指针,用于接收返回的画刷,画刷是int*
GdipDeleteBrush:销毁画刷
参数:要销毁的画刷
以上三个函数的返回值:0成功,非0失败
通过画刷画图,以画填充矩形为例:
//画填充矩形 extern "C" int WINAPI GdipFillRectangle(int graphics, int* brush, float x, float y, float width, float height);
GdipFillRectangle:画填充矩形
参数1:Graphics对象
参数2:画刷
参数3-6:矩形左上角的x坐标,y坐标,矩形宽度,矩形高度
例子:
<pre class="cpp" name="code"> case WM_PAINT: HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); int graphics; GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象 GdipCreateSolidFill(0x700000FF, &brush);//创建单色画刷 GdipFillRectangle(graphics, brush, 10, 10, 60, 60);//用单色画刷填充矩形 PointF p1; p1 = { 70, 0 }; PointF p2; p2 = { 170, 0 }; GdipCreateLineBrush(&p1, &p2, 0xFFFF0000, 0x400000FF, 0, &linebrush);//创建线性渐变画刷 GdipFillRectangle(graphics, linebrush, 70, 70, 100, 100);//用线性渐变画刷填充矩形 GdipDeleteBrush(brush);//销毁画刷 GdipDeleteBrush(linebrush);//销毁画刷 GdipDeleteGraphics(graphics);//销毁Graphics对象 EndPaint(hwnd, &ps); return 0;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。
效果图:
完整源码:
#include "stdafx.h" #include <gdiplus.h> #include <gdiplusflat.h> #pragma comment(lib,"gdiplus.lib")//very important #include <windows.h> #include <windowsx.h> #pragma comment(lib,"user32.lib") #pragma comment(lib,"gdi32.lib") //GDI+Flat typedef struct _GdiplusStartupInput{ unsigned int GdiplusVersion; unsigned int DebugEventCallback; BOOL SuppressBackgroundThread; BOOL SuppressExternalCodecs; }GdiplusStartupInput; extern "C" int WINAPI GdiplusStartup(int* token, GdiplusStartupInput *input, int *output); extern "C" void WINAPI GdiplusShutdown(int token); extern "C" int WINAPI GdipCreateFromHDC(HDC hdc, int* graphics); extern "C" int WINAPI GdipDeleteGraphics(int graphics); //画笔 extern "C" int WINAPI GdipCreatePen1(unsigned int argb_color, float width, int unit, int** pen); extern "C" int WINAPI GdipDeletePen(int* pen); //画矩形 画直线 extern "C" int WINAPI GdipDrawRectangle(int graphics, int* pen, float x, float y, float width, float height); extern "C" int WINAPI GdipDrawLine(int graphics, int* pen, float x1, float y1, float x2, float y2); //画刷 typedef struct _PointF{ float x; float y; }PointF; extern "C" int WINAPI GdipCreateSolidFill(unsigned int argb_color, int** brush); extern "C" int WINAPI GdipCreateLineBrush(PointF* point1, PointF* point2, unsigned int argb_color1, unsigned int argb_color2, int wrapMode, int** lineGradient); extern "C" int WINAPI GdipDeleteBrush(int* brush); //画填充矩形 extern "C" int WINAPI GdipFillRectangle(int graphics, int* brush, float x, float y, float width, float height); int token; int* pen; int* brush; int* linebrush; //************************************************************* LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); WNDCLASS wc; const TCHAR* AppName = TEXT("MyWindowClass1"); HWND hwnd1; int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) { //GDI+开启 GdiplusStartupInput StartupInput = { 0 }; StartupInput.GdiplusVersion = 1; if (GdiplusStartup(&token, &StartupInput, NULL))MessageBox(0, TEXT("GdiPlus开启失败"), TEXT("错误"), MB_ICONERROR); //这里是在构建窗口类结构 wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc;//窗口回调函数指针 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance;//实例句柄 wc.hIcon = LoadIcon(hInstance, TEXT("ICON_1")); wc.hCursor = LoadCursor(NULL, IDC_ARROW);//默认指针 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);//默认背景颜色 wc.lpszMenuName = NULL; wc.lpszClassName = AppName;//窗口类名 //注册窗口类 if (!RegisterClass(&wc)) { MessageBox(NULL, TEXT("注册窗口类失败!"), TEXT("错误"), MB_ICONERROR); return 0; } //创建窗口 int style = WS_OVERLAPPEDWINDOW; hwnd1 = CreateWindowEx(NULL, AppName, TEXT("窗口标题"), style, 50, 50, 500, 500, 0, LoadMenu(hInstance, TEXT("MENU1")), hInstance, 0); if (hwnd1 == NULL) { MessageBox(NULL, TEXT("创建窗口失败!"), TEXT("错误"), MB_ICONERROR); return 0; } //无边框窗口 SetWindowLong(hwnd1, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); //显示、更新窗口 ShowWindow(hwnd1, nCmdShow); UpdateWindow(hwnd1); //消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } //GDI+关闭 GdiplusShutdown(token);//可以把这个写在消息循环后面,程序退出就销毁,或者在不需要GDI+时调用,比如GDI+窗口的WM_DESTROY消息里调用 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg){ case WM_PAINT: HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); int graphics; GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象 GdipCreateSolidFill(0x700000FF, &brush);//创建单色画刷 GdipFillRectangle(graphics, brush, 10, 10, 60, 60);//用单色画刷填充矩形 PointF p1; p1 = { 70, 0 }; PointF p2; p2 = { 170, 0 }; GdipCreateLineBrush(&p1, &p2, 0xFFFF0000, 0x400000FF, 0, &linebrush);//创建线性渐变画刷 GdipFillRectangle(graphics, linebrush, 70, 70, 100, 100);//用线性渐变画刷填充矩形 if (0){//这是上一篇中画笔的代码,用if0作废 GdipCreatePen1(0x60FF2015, 1, 2, &pen);//创建画笔 GdipDrawRectangle(graphics, pen, 20, 20, 120, 120);//画矩形 GdipDrawLine(graphics, pen, 50, 60, 170, 340);//画直线 GdipDeletePen(pen);//销毁画笔 } GdipDeleteBrush(brush);//销毁画刷 GdipDeleteBrush(linebrush);//销毁画刷 GdipDeleteGraphics(graphics);//销毁Graphics对象 EndPaint(hwnd, &ps); return 0;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。 case WM_CREATE: break; case WM_DESTROY://窗口已经销毁 PostQuitMessage(0);//退出消息循环,结束应用程序 return 0; break; case WM_LBUTTONDOWN://鼠标左键按下 //让无边框窗口能够拖动(在窗口客户区拖动) PostMessage(hwnd, WM_SYSCOMMAND, 61458, 0); break; /*case WM_MOUSEMOVE://鼠标移动 int xPos, yPos; xPos = GET_X_LPARAM(lParam);//鼠标位置X坐标 yPos = GET_Y_LPARAM(lParam);//鼠标位置Y坐标 //不要用LOWORD和HIWORD获取坐标,因为坐标有可能是负的 break;*/ default: break; } return DefWindowProc(hwnd, uMsg, wParam, lParam);//其他消息交给系统处理 }