您的位置:首页 > 编程语言 > C语言/C++

在C语言Windows应用程序中使用GDI+

2009-11-10 22:32 399 查看
GDI+是C++中常用的一种图形图像工具,VB、Delphi等语言也移植了GDI+,.net的诸多语言甚至完全采用GDI+作为绘制其界面。
在Winsows系统下,几乎所有的API都是直接针对C语言的,除C/C++可直接使用这些API外,其它各种语言都必须移植这些API方法,而唯独GDI+,微软提供的Gdiplus头文件,从类型定义到方法接口,都是针对C++写的,这就使得C语言没法使用这些面向对象的方法,即使是GDI+提供的原始API,如果不重新定义其参数中众多的数据类型,C语言也是没法使用的。
也许是因为C语言不适合编写Windows界面应用程序,所以至今没有发现GDI+的C版本(可能有,但我没发现)。因为我是一个业余编程爱好者,平时喜欢摆弄下C/C++、Delphi等,所以用了一些时间,在GDI+的C++版本基础上进行改编了一个C语言的GDI+版本,在改写的过程中,我才知道没发现GDI+的C版本的一个可能的原因是:C++版本中的众多的重载函数,缺省参数,用C来写却是头都大了,不知道用什么函数名才好(考虑GDI+使用了这些年,新的函数名不应与原函数名偏离太远)。
对于改写的GDI+ C版本,作如下说明:
一、函数命名,采用下面的几个原则来进行:
1、尽量按C++版本的GDI+类名作为各种GDI+对象函数名的前缀。如C++原先的Graphics类的函数,前缀都冠以Graphics;对那些原本类名很长的类适当进行了一些简化,如StringFormat函数的前缀简化为StrFormat、ImageAttributes函数的前缀为ImageAttr、LinearGradientBrush函数的前缀为LineBrush、PathGradientBrush函数的前缀为PathBrush等等。
2、C++版本各个类的构造函数和析构函数命名为xxxxCreate和xxxxDelete,其中的xxxx为前缀,如原ImageAttributes类的构造、析构函数名称分别为ImageAttrCreate和ImageAttrDelete等;对于多个构造函数的类,以一个常用的函数命名为xxxxCreate,其余的命名为xxxxFrom****。
3、对原先的重载函数,以最常用的保留原函数名,其余的冠以一些简单的后缀语义区分;对某些以浮点类型和整数类型作为参数类型的取整数类型为准,浮点类型函数后面加F后缀进行区分。
4、GDI+ C版本和C++版本一样,直接在头文件中写成FORCEINLINE类型的函数,我测试过VS2005和BCB6及以上版本,VS对FORCEINLINE宏支持为inline函数,而BCB则临时编译为C函数。总之,不需要预先编译静态库。
二、使用GDI+的C++版本一样,C版本使用前必须使用GdiplusStartup进行初始化,使用完毕也应用GdiplusShutdown进行释放,因为C++的GdiplusStartup的input参数是个类类型,默认构造函数已经进行了参数的初始化,而C版本必须调用MakeGdiplusStartupInput函数进行input参数的初始化,为了减少麻烦,我另写了2个没有参数的函数Gdiplus_Startup和Gdiplus_Shutdown替代。
三、同GDI+的C++版本一样,使用C版本的应用程序也必须包含Gdiplus的静态连接库Gdiplus.lib。注意:不同的C编译器,其Gdiplus.lib是不同的,如VS就不能使用BCB提供的(或者***的)静态库,反过来也一样。
四、GDI+ C版本写成后,使用VS2005和BCB6和BCB2010作了一些主要的应用测试,这些测试代码我会放到我的BLOG上,可作为参考,请随时注意我的BLOG文章,我的BLOG地址为http://blog.csdn.net/maozefa

下面是一个简单的C语言Windows程序框架代码,以后写的GDI+测试代码都使用这个框架:

// Application.h

#ifndef	__APPLICATION_H
#define	__APPLICATION_H

#include <Windows.h>
#include "../../include/Gdiplus_c.h"

typedef void (*CreateWindowEvent)(void);
typedef CreateWindowEvent	DestroyWindowEvent;
typedef	void (*PaintWindowEvent)(HDC DC);
typedef void (*CommandEvent)(WORD NotifyCode, WORD itemID, HWND ctlHandle);

extern HINSTANCE hInstance;
extern int CmdShow;
extern HWND Handle;

extern CreateWindowEvent CreateProc;
extern DestroyWindowEvent DestroyProc;
extern PaintWindowEvent PaintProc;
extern CommandEvent CommandProc;

void InitApplication(HINSTANCE hInst, int cmdShow, BOOL isDoubleBuffer);
int RunApplication(LPTSTR caption, int width, int height);

#endif


// Application.c

#include "Application.h"

#define	WNDCLASSNAME	TEXT("Maozefa_Form")

HINSTANCE hInstance;
int CmdShow;
HWND Handle = NULL;

// 窗口建立事件过程
CreateWindowEvent CreateProc = NULL;
// 窗口摧毁事件过程
DestroyWindowEvent DestroyProc = NULL;
// 窗口绘制事件过程
PaintWindowEvent PaintProc = NULL;
// 命令事件过程
CommandEvent CommandProc = NULL;

static BOOL DoubleBuffer = FALSE;

BOOL WndPaint(HWND hWnd, HDC DC)
{
	HDC hDC, memDC;
	PAINTSTRUCT ps;
	HBITMAP memBitmap, oldBitmap;
	RECT clientRect;

	if (!PaintProc) return FALSE;
	if (DC) PaintProc(DC);
	else if (DoubleBuffer == FALSE)
	{
		hDC = BeginPaint(hWnd, &ps);
		PaintProc(hDC);
		EndPaint(hWnd, &ps);
	}
	else
	{
		GetClientRect(hWnd, &clientRect);
		hDC = GetDC(hWnd);
		memBitmap = CreateCompatibleBitmap(hDC, clientRect.right, clientRect.bottom);
		ReleaseDC(hWnd, hDC);
		memDC = CreateCompatibleDC(0);
		oldBitmap = SelectObject(memDC, memBitmap);
		hDC = BeginPaint(hWnd, &ps);
		SendMessage(hWnd, WM_ERASEBKGND, (WPARAM)memDC, (LPARAM)memDC);
		WndPaint(hWnd, memDC);
		BitBlt(hDC, 0, 0, clientRect.right, clientRect.bottom, memDC, 0, 0, SRCCOPY);
		EndPaint(hWnd, &ps);
		SelectObject(memDC, oldBitmap);
		DeleteDC(memDC);
		DeleteObject(memBitmap);
	}
	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch (Msg)
	{
		case WM_PAINT:
			if (WndPaint(hWnd, (HDC)wParam))
				return 0;
			break;
		case WM_COMMAND:
			if (CommandProc)
			{
				CommandProc(HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
				return 0;
			}
			break;
		case WM_DESTROY:
			if (DestroyProc)
				DestroyProc();
			PostQuitMessage(0);
			break;
		default:
			break;
	}
	return DefWindowProc(hWnd, Msg, wParam, lParam);
}

void CreateMainWindow(LPTSTR caption, int width, int height)
{
	WNDCLASS WinClass;

	memset(&WinClass, 0, sizeof(WNDCLASS));
	WinClass.style = CS_VREDRAW | CS_HREDRAW;
	WinClass.hInstance = hInstance;
	WinClass.lpfnWndProc = WndProc;
	WinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WinClass.hbrBackground =  (HBRUSH)COLOR_WINDOW;
	WinClass.lpszClassName = WNDCLASSNAME;

	if (!RegisterClass(&WinClass))
		return;

	Handle = CreateWindowEx(WS_EX_CONTROLPARENT,
							WNDCLASSNAME,
							caption,
							WS_CLIPSIBLINGS | WS_VISIBLE | WS_CLIPCHILDREN |
							WS_BORDER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU,
							CW_USEDEFAULT, CW_USEDEFAULT, width, height,
							NULL, NULL, hInstance, NULL);
	if (CreateProc)
		CreateProc();
}

// 运行应用程序
int RunApplication(LPTSTR caption, int width, int height)
{
	MSG msg;

	Gdiplus_Startup();		// 启动Gdiplus

	CreateMainWindow(caption, width, height);
	if (Handle == NULL)
		return -1;

	ShowWindow(Handle, CmdShow);
	UpdateWindow(Handle);
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	Gdiplus_Shutdown();         // 释放Gdiplus
	return (int)msg.wParam;
}

// 应用程序初始化。其中isDoubleBuffer为使用窗口绘制双缓冲
void InitApplication(HINSTANCE hInst, int cmdShow, BOOL isDoubleBuffer)
{
	hInstance = hInst;
	CmdShow = cmdShow;
	DoubleBuffer = isDoubleBuffer;
}


下面是用GDI+函数显示图像的简单例子:

#include "../../SampleCode/comcode/Application.h"

void OnPaint(HDC DC)
{
	PGpBitmap bmp = BitmapFromFile(L"..//..//Media//Source.jpg", FALSE);
	PGpGraphics g = GraphicsCreate(DC);           	// GDI+ 画布
	GraphicsDrawImageXY(g, bmp, 0, 0);
	GraphicsDelete(g);
	ImageDelete(bmp);
}

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	// 这里使用了双缓冲画窗口 */
	InitApplication(hInstance, nCmdShow, TRUE);
	PaintProc = OnPaint;
	return RunApplication(TEXT("C语言Gdiplus演示例子"), 486, 392);
}


下面是BCB2010运行效果图:



五、使用过程中,如有错误,或者你有好的建议,请发送邮件到我的信箱:mao.maozefa@gmail.commaozefa@hotmail.com

GDI+ C语言版本同时GDI+ for VCL版本2010.7.10修改版下载地址:http://download.csdn.net/source/2737743
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: