GdiplusFlat(5)画图片

本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处: http://blog.csdn.net/zuishikonghuan/article/details/47278905

在上两篇篇中,我们说到了通过GdipCreateFromHDC函数将HDC(设备上下文句柄)装换成GDI+的Graphics对象,并讲到了画笔和画刷的使用,这一篇就来讲讲如何利用GDI+Flat来画图片。

还是和以前一样,我们必须自己声明GDI+Flat函数,自己定义GDI+Flat的数据结构。自己动手,丰衣足食。~~

对于画图片,其实是GDI+调用的GDI+Flat的这几个函数:GdipLoadImageFromFile、GdipLoadImageFromStream、GdipGetImageDimension、GdipDrawImageRect和GdipDisposeImage

我们把这两个函数自己声明出来!不用那些GDI+类的东西!只用C和Win32的最基本的数据类型!

//画图片
extern "C" int WINAPI GdipLoadImageFromFile(WCHAR* filename, int** image);
extern "C" int WINAPI GdipLoadImageFromStream(LPSTREAM stream, int** image);
extern "C" int WINAPI GdipGetImageDimension(int* image, float* width, float* height);
extern "C" int WINAPI GdipDrawImageRect(int graphics, int* image, float x, float y, float width, float height);
extern "C" int WINAPI GdipDisposeImage(int* image);


先不解释这几个函数的具体使用方法,先来看看我们如何通过GDI+Flat画出一张图片。

流程如下:

GdiplusFlat(5)画图片_第1张图片

原谅博主的绘图水平吧,,,

下面具体说说这几个函数的用法

GdipLoadImageFromFile:从文件加载图片对象

参数1:Unicode字符:文件名称

参数2:指向一个Image对象的指针,用于接收返回的Image对象,Image对象是int*

GdipLoadImageFromStream:从内存流中加载图片对象

参数1:内存流对象指针

参数2:指向一个Image对象的指针,用于接收返回的Image对象,Image对象是int*

GdipGetImageDimension:计算图片大小

参数1:一个Image对象

参数2:一个指向float类型变量的指针,用于接收图片宽度

参数3:一个指向float类型变量的指针,用于接收图片高度

GdipDrawImageRect:绘制图片

参数1:要把图片绘制到的Graphics对象

参数2:一个Image对象

参数3,4:图片左上角的坐标,坐标相对于DC的左上角

参数5,6:要绘制的宽度、高度

GdipDisposeImage:销毁Image对象

参数:要销毁的Image对象

以上函数的返回值:0成功,非0失败

关于GdipLoadImageFromStream从内存流中创建Image对象:

使用GlobalAlloc,GlobalLock,GlobalUnlock,CreateStreamOnHGlobal,GlobalFree等函数创建和处理内存流。但是GDI+Flat没有提供可以直接使用RC资源进行绘图的函数,对于这个问题,我想到过两种解决方案:

1.将图片追加写到PE文件(程序自身)的尾部,这样图片就超出了PE结构了,PE文件加载时数据不会装入内存,程序运行时读取自身,把图片读入到内存流中,用GdipLoadImageFromStream创建Image对象。

2.将图片以RC资源的形式写入程序,使用LoadImage函数获取句柄,创建内存场景,在内存设备上下文中用GDI(不是GDI+)绘图,用时再进行DC复制。缺陷:不支持png图片

具体例子(从D:\1.png绘图)

case WM_PAINT:
		HDC hdc;
		PAINTSTRUCT ps;
		hdc = BeginPaint(hwnd, &ps);

		int graphics;

		float x, y;
		GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象
		GdipLoadImageFromFile(L"D:\\1.png", &image);//创建Image对象
		GdipGetImageDimension(image, &x, &y);//计算图片宽度和高度
		GdipDrawImageRect(graphics, image, 20, 20, x, y);//画图片
		GdipDisposeImage(image);//销毁图片,释放资源
		GdipDeleteGraphics(graphics);//销毁Graphics对象
		
		EndPaint(hwnd, &ps);
		return 0;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。


效果图:

GdiplusFlat(5)画图片_第2张图片

完整源码:

#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);
//画图片
extern "C" int WINAPI GdipLoadImageFromFile(WCHAR* filename, int** image);
extern "C" int WINAPI GdipLoadImageFromStream(LPSTREAM stream, int** image);
extern "C" int WINAPI GdipGetImageDimension(int* image, float* width, float* height);
extern "C" int WINAPI GdipDrawImageRect(int graphics, int* image, float x, float y, float width, float height);
extern "C" int WINAPI GdipDisposeImage(int* image);

int token;
int* pen;
int* brush;
int* linebrush;
int* image;

//*************************************************************
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;

		float x, y;
		GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象
		GdipLoadImageFromFile(L"D:\\1.png", &image);//创建Image对象
		GdipGetImageDimension(image, &x, &y);//计算图片宽度和高度
		GdipDrawImageRect(graphics, image, 20, 20, x, y);//画图片
		GdipDisposeImage(image);//销毁图片,释放资源
		if (0){//这是上几篇的代码,用if0作废
			//画笔
			GdipCreatePen1(0x60FF2015, 1, 2, &pen);//创建画笔
			GdipDrawRectangle(graphics, pen, 20, 20, 120, 120);//画矩形
			GdipDrawLine(graphics, pen, 50, 60, 170, 340);//画直线
			GdipDeletePen(pen);//销毁画笔
			//画刷
			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消息我已经处理了,你那儿凉快哪儿玩去吧。
	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);//其他消息交给系统处理
}






你可能感兴趣的:(Win32,api,Desktop,GDI+,gdiplus)