天天看點

GdiplusFlat(1)GDI+平面API:用GDI的思想進行GDI+程式設計

本文由CSDN使用者zuishikonghuan所作,轉載請注明出處:http://blog.csdn.net/zuishikonghuan/article/details/46982559

堅信GdiplusFlat比Gdiplus好!我要在資料匮乏的GdiplusFlat上打下一片天地!沒有api文檔?我去百度找,就算把那些其他不支援GDI+類的語言中用GdiplusFlat的例子翻出來看,頭檔案裡函數和結構沒有聲明?我自己聲明!實在不行?我把你們這些GdiplusFlat函數一個個從dll裡load進來直接動态調用!!

GDI+(Gdiplus)想必大家都不陌生,MSDN給出的解釋是

Windows GDI+ is a class-based API for C/C++ programmers. It enables applications to use graphics and formatted text on both the video display and the printer. Applications based on the Microsoft Win32 API do not access graphics hardware directly. Instead, GDI+ interacts with device drivers on behalf of applications. GDI+ is also supported by Microsoft Win64.

其實,這個GDI+是對GDI的進一步封裝,GDI是Windows的圖形裝置接口,是以Win32API的形式提供的,完全是按照面向過程的思想使用的,而GDI+不一樣,GDI+一開始就是提供的面向對象的程式設計方式,即提供的是GDI+類!在一個偶然的機會下,我知道了GDI+類的實作是調用的gdiplus.dll中的API,也就是說,GDI+是有API版本的,那麼這個API版本,就是GdiplusFlat(GDI+平面API)!

這是微軟的解釋:

Windows GDI+ exposes a flat API that consists of about 600 functions, which are implemented in Gdiplus.dll and declared in Gdiplusflat.h. The functions in the GDI+ flat API are wrapped by a collection of about 40 C++ classes. It is recommended that you do not directly call the functions in the flat API. Whenever you make calls to GDI+, you should do so by calling the methods and functions provided by the C++ wrappers. Microsoft Product Support Services will not provide support for code that calls the flat API directly.

注意:如果使用GDI+平面API,微軟不提供産品支援!!甚至這些平面API都沒有文檔化!!MSDN隻是給了聲明和簡單說明

但這麼做的意義無疑是巨大的,那就是用GDI的思想進行GDI+程式設計,不知道其他人怎麼想,反正我學了GDI後不願意使用GDI+的模式程式設計,同時GDI+明顯偏向MFC,對于用慣了C++的Win32SDK程式設計的我,實在是不敢恭維。而GDI+平面API,也就是GdiplusFlat,他無疑回歸了Win32的懷抱,而且GDI+類是對GDI+平面API的抽象和封裝,無疑用GDI+類的程式效率不及GDI+平面API! 下面,看看如何使用GdiplusFlat程式設計GDI+平面API

第一步:建立一個Win32工程,進入stdafx.h,删除一下代碼

#define WIN32_LEAN_AND_MEAN             //  從 Windows 頭檔案中排除極少使用的資訊
           

如果願意也可以把這個删除:

#include "targetver.h"
           

将工程主檔案中的所有内容删除,改為:

#include "stdafx.h"
#include <Windows.h>//windows頭檔案
#include <gdiplus.h>//GDI+頭檔案
#include <gdiplusflat.h>//GDI+Flat頭檔案
#pragma comment(lib,"gdiplus.lib")//這個非常重要
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{

}
           

為什麼說這個#pragma comment(lib,"gdiplus.lib")非常重要呢?因為我們是調用GDI+的API,不bird那什麼難用的GDI+類,但是那些函數就算自己聲明了,編譯時會出錯,至于說原因,願意研究的可以看看我寫的這篇文章 http://blog.csdn.net/zuishikonghuan/article/details/46375803中介紹的簡單編譯原理知識(紅字)

然後開啟GDI+ 想必大家都知道應該用Gdiplus命名空間裡的GdiplusStartupInput,但是那是GDI+用的,不是GDI+Flat用的!! 我們自己定義一個GdiplusStartupInput!用C和Win32的最基本的資料類型!不鳥那GDI+類!!

typedef struct _GdiplusStartupInput{
	unsigned int GdiplusVersion;
	unsigned int DebugEventCallback;
	BOOL SuppressBackgroundThread;
	BOOL SuppressExternalCodecs;
}GdiplusStartupInput;
           

然後就是調用GdiplusStartup,還是沒有!好, 我們自己聲明出來,隻要gdiplus.dll中有的API, 因為連接配接了gdiplus.lib,就不信不能用!!

extern "C" int WINAPI GdiplusStartup(int* token,GdiplusStartupInput *input,int *output);
           

 注意三點: 1。調用約定WINAPI不能少,至于說為什麼,32位Win32API都是标準調用!不加标準調用編譯出來的符号不一樣沒法和gdiplus.lib連接配接,同時就算動态調用dll裡的API不加标準調用會出現堆棧錯誤。 2。不要用那些GDI+類的東西!隻用C和Win32的最基本的資料類型! 3。extern "C"不能少,不然C++不采用标準函數符号修飾約定。

然後就可以用了

int token;
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	GdiplusStartupInput StartupInput;
	StartupInput.GdiplusVersion = 1;
	GdiplusStartup(&token, &StartupInput,NULL);
}
           

然後就是關閉了, 一樣,我們自己聲明

extern "C" void WINAPI GdiplusShutdown(int token);
           

完整代碼:

#include "stdafx.h"
#include <Windows.h>
#include <gdiplus.h>
#include <gdiplusflat.h>
#pragma comment(lib,"gdiplus.lib")//very important

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);

int token;
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	//GDI+開啟
	GdiplusStartupInput StartupInput = {0};
	StartupInput.GdiplusVersion = 1;
	GdiplusStartup(&token, &StartupInput,NULL);
	//在這裡盡情地GDI+Flat程式設計吧
	//GDI+關閉
	GdiplusShutdown(token);//可以把這個寫在消息循環後面,程式退出就銷毀,或者在不需要GDI+時調用,比如GDI+視窗的WM_DESTROY消息裡調用
}
           

下面我會逐漸講GDI+Flat程式設計!相信比GDI+更棒!!  

繼續閱讀