上两篇分别介绍了GDI+Flat编程是什么,意义和实现方法,以及对WM_PAINT,子类化和GDI编程中的DC做了简单介绍。今天,我们来看看用GDI+Flat如何进行绘图,在开始之前,首先给大家介绍一种新的颜色,ARGB颜色!
想必大家都知道RGB()宏,一种颜色占8位,用RGB宏可以更直观的生成类似0x00??????这样的整数,但是一个int有32位,处了红绿蓝三种颜色以外还有8位没有使用呢,其实,如果把这8位当作颜色的透明度,那就是ARGB颜色了。
没错,GDI+是使用的ARGB颜色,也就是说,通过GDI+可以很方便的实现透明,GDI+Flat也不例外。
GDI+是对GDI的封装吗,GDI不支持透明并不是绝对的,GDI+其实就是取了某一像素点的颜色,通过ARGB颜色中的透明度和ARGB中的颜色进行一定的运算,算出了一个新颜色,再用他封装GDI绘制的。
不过,好像并没有ARGB宏,不过不要紧,用0x??000000和RGB宏做位或运算,或者直接用十六进制:0x????????。
下面,进入重点:
使用设备上下文创建Graphics对象
我在上一篇里就已经说过了GDI+不再像GDI那样使用设备上下文了,但是GDI+是GDI的封装,作为GDI+的平面API,还真是离不开设备上下文,在GDI+Flat中,我们需要使用设备上下文创建Graphics对象,具体的方法是:
创建Graphics:GdipCreateFromHDC
销毁Graphics:GdipDeleteGraphics
还是和以前一样,我们必须自己声明GDI+Flat函数,自己定义GDI+Flat的数据结构。自己动手,丰衣足食。~~
我们把这两个函数自己声明出来!不用那些GDI+类的东西!只用C和Win32的最基本的数据类型!
extern "C" int WINAPI GdipCreateFromHDC(HDC hdc,int* graphics); extern "C" int WINAPI GdipDeleteGraphics(int graphics);
GdipCreateFromHDC的第一个参数是设备上下文,第二个参数是一个指针,用于接受graphics对象。
GdipDeleteGraphics的参数是要销毁的graphics对象。
返回值:0成功,非0失败
画笔
还是和以前一样,我们必须自己声明GDI+Flat函数,自己定义GDI+Flat的数据结构。自己动手,丰衣足食。~~
对于画笔的创建和销毁,其实是GDI+调用的GDI+Flat的这两个函数:GdipCreatePen1和GdipDeletePen
我们把这两个函数自己声明出来!不用那些GDI+类的东西!只用C和Win32的最基本的数据类型!
extern "C" int WINAPI GdipCreatePen1(unsigned int argb_color, float width, int unit, int** pen); extern "C" int WINAPI GdipDeletePen(int* pen);
GdipCreatePen1:创建画笔
参数1:ARGB颜色
参数2:画笔宽度
参数3:单位(0到6分别代表:UnitWorld = 0,UnitDisplay= 1,UnitPixel= 2,UnitPoint= 3,UnitInch= 4,UnitDocument= 5,UnitMillimeter= 6 )MSDN:https://msdn.microsoft.com/en-us/library/ms534405(v=vs.85).aspx
反正我只知道2是像素。
参数4:指向一个画笔的指针,用于接收返回的画笔,画笔是int*
GdipDeletePen:销毁画笔
参数:要销毁的画笔
返回值:0成功,非0失败
之后我们就可以通过画笔画图了,这里只介绍画矩形和画直线:
画矩形:GdipDrawRectangle
画直线:GdipDrawLine
还是和以前一样,我们必须自己声明GDI+Flat函数,自己定义GDI+Flat的数据结构。自己动手,丰衣足食。~~
我们把这两个函数自己声明出来!不用那些GDI+类的东西!只用C和Win32的最基本的数据类型!
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);
参数没啥好说的,一个Graphics对象,然后是画笔,最后四个是坐标
例子:
case WM_PAINT: HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); int graphics; GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象 GdipCreatePen1(0x60FF2015, 1, 2, &pen);//创建画笔 GdipDrawRectangle(graphics, pen, 20, 20, 120, 120);//画矩形 GdipDrawLine(graphics, pen, 50, 60, 170, 340);//画直线 GdipDeletePen(pen);//销毁画笔 GdipDeleteGraphics(graphics);//销毁Graphics对象 EndPaint(hwnd, &ps); return 0;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。
效果图:(看出来透明了吗)
完整源码:
</pre><pre class="cpp" name="code">#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); int token; int* pen; //************************************************************* 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对象 GdipCreatePen1(0x60FF2015, 1, 2, &pen);//创建画笔 GdipDrawRectangle(graphics, pen, 20, 20, 120, 120);//画矩形 GdipDrawLine(graphics, pen, 50, 60, 170, 340);//画直线 GdipDeletePen(pen);//销毁画笔 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);//其他消息交给系统处理 }