VC2005“項目/*屬性”功能表項目,開啟項目的屬性頁面視窗,先選“所有配置”,再選“配置屬性/連結器/輸入”項,在右邊上部的“附加依賴項”欄的右邊,鍵入GdiPlus.lib 後按“應用”鈕,最後按“確定”鈕關閉對話方塊。
在需要用到GDI+的檔案頭加上下面兩句
#include <gdiplus.h>
using namespace Gdiplus;
在應用程式類應用程式類(CGDIPlusDemoApp) 標頭檔中聲明一個成員變數:
ULONG_PTR m_gdiplusToken; // ULONG PTR 為int64 類型
並在該類的初始化函數CGDIPlusDemoApp::InitInstance() 中加入以下代碼來對GDI+進行初始化:
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
注意:這兩個語句必須加在應用程式類的InitInstance函數中的
CWinApp:: InitInstance ();
語句之前,不然以後會造成視圖視窗不能自動重畫、程式中不能使用字型等等一系列問題。
還要在CGDIPlusDemoApp::ExitInstance() 函數(重寫)中加入以下代碼來關閉GDI +:
GdiplusShutdown(m_gdiplusToken);
上面是所需步驟..
MFC使用GDI+編程基礎
封裝在GDI+ API中的各種C++類、函數、常量、枚舉和結構,都被定義在Gdiplus.h標頭檔所包含的一系列標頭檔中。所以,採用MFC進行GDI+編程,必須包含Gdiplus.h標頭檔。
封裝在GDI+類中方法,最後都需要調用GDI+平面API中的相關底層函數,才能完成實際的操作。所以,為了運行GDI+應用程式,在作業系統平台中,必須安裝動態連結程式庫Gdiplus.dll。
該動態連結程式庫所對應的靜態庫檔案為GdiPlus.lib,而且它不是C++和MFC的預設連結庫。所以,必須在項目設定,添加該庫作為連結器輸入的附加依賴項。
因為在Gdiplus.h標頭檔中,將所有的GDI+的類、函數、常量、枚舉和結構等都定義在了命名空間Gdiplus中。所以,一般在GDI+程式中,都必須使用如下的命名空間聲明:
using namespace Gdiplus;
例如:
#include <gdiplus.h>
using namespace Gdiplus;
……
1)GdiPlus.h
/*********************************************************************/
* Copyright (c) 1998-2001, Microsoft Corp. All Rights Reserved.
* Module Name:
* Gdiplus.h
* Abstract:
* GDI+ public header file
/*********************************************************************/
#ifndef _GDIPLUS_H
#define _GDIPLUS_H
struct IDirectDrawSurface7;
typedef signed short INT16;
typedef unsigned short UINT16;
#include <pshpack8.h> // set structure packing to 8
namespace Gdiplus
{
namespace DllExports {
#include "GdiplusMem.h"
};
#include "GdiplusBase.h"
#include "GdiplusEnums.h"
#include "GdiplusTypes.h"
#include "GdiplusInit.h"
#include "GdiplusPixelFormats.h"
#include "GdiplusColor.h"
#include "GdiplusMetaHeader.h"
#include "GdiplusImaging.h"
#include "GdiplusColorMatrix.h"
#include "GdiplusGpStubs.h"
#include "GdiplusHeaders.h"
namespace DllExports {
#include "GdiplusFlat.h"
};
#include "GdiplusImageAttributes.h"
#include "GdiplusMatrix.h"
#include "GdiplusBrush.h"
#include "GdiplusPen.h"
#include "GdiplusStringFormat.h"
#include "GdiplusPath.h"
#include "GdiplusLineCaps.h"
#include "GdiplusMetafile.h"
#include "GdiplusGraphics.h"
#include "GdiplusCachedBitmap.h"
#include "GdiplusRegion.h"
#include "GdiplusFontCollection.h"
#include "GdiplusFontFamily.h"
#include "GdiplusFont.h"
#include "GdiplusBitmap.h"
#include "GdiplusImageCodec.h"
}; // namespace Gdiplus
#include <poppack.h> // pop structure packing back to previous state
#endif // !_GDIPLUS_HPP
2)GDI+的初始化與清除
為了在MFC應用程式中使用採用C++封裝的GDI+ API,必須在MFC項目的應用程式類中,調用GDI+命名空間中的GDI+啟動函數GdiplusStartup和GDI+關閉函數GdiplusShutdown,來對GDI+進行初始化(裝入動態連結程式庫Gdiplus.dll,或鎖定標誌+1)和清除(卸載動態連結程式庫Gdiplus.dll,或鎖定標誌-1)工作。它們一般分別在應用程式類的InitInstance和ExitInstance重載成員函數中調用。
函數GdiplusStartup和GdiplusShutdown,都被定義在GdiplusInit.h標頭檔中:
Status WINAPI GdiplusStartup(
OUT ULONG_PTR *token,
const GdiplusStartupInput *input,
OUT GdiplusStartupOutput *output);
void GdiplusShutdown(ULONG_PTR token);
其中:
<!--[if !supportLists]-->l <!--[endif]-->類型ULONG_PTR,是用無符號長整數表示的指標,被定義在basetsd.h標頭檔中:
typedef _W64 unsigned long ULONG_PTR;
輸出參數token(權標),供關閉GDI+的函數使用,所以必須設定為應用程式類的成員變數(或全域變數,不提倡)。
<!--[if !supportLists]-->l <!--[endif]-->結構GdiplusStartupInput和GdiplusStartupOutput,也都被定義在GdiplusInit.h標頭檔中:
struct GdiplusStartupInput {
UINT32 GdiplusVersion; // Must be 1
DebugEventProc DebugEventCallback; // Ignored on free builds
BOOL SuppressBackgroundThread; // FALSE unless you're prepared to call
// the hook/unhook functions properly
BOOL SuppressExternalCodecs; // FALSE unless you want GDI+ only to use
// its internal image codecs.
GdiplusStartupInput(
DebugEventProc debugEventCallback = NULL,
BOOL suppressBackgroundThread = FALSE,
BOOL suppressExternalCodecs = FALSE) {
GdiplusVersion = 1;
DebugEventCallback = debugEventCallback;
SuppressBackgroundThread = suppressBackgroundThread;
SuppressExternalCodecs = suppressExternalCodecs;
}
};
struct GdiplusStartupOutput {
NotificationHookProc NotificationHook;
NotificationUnhookProc NotificationUnhook;
};
<!--[if !supportLists]-->n <!--[endif]-->GDI+啟動輸入結構指標參數input,一般取預設構造值即可,即(設:無調試事件回調過程、不抑制背景線程、不抑制外部編解碼):
input = GdiplusStartupInput(NULL, FALSE, FALSE);
<!--[if !supportLists]-->n <!--[endif]-->GDI+啟動輸出結構指標參數output,一般不需要,取為NULL即可。
注意,採用MFC進行GDI+ API編程時,在使用任何GDI+的功能調用之前,必須先調用GDI+啟動函數GdiplusStartup來進行初始化GDI+的工作;在完成所有的GDI+功能調用之後,必須調用GDI+關閉函數GdiplusShutdown來進行清除GDI+的工作。
例如:(建立一個名為GdipDraw的MFC單文檔應用程式項目,在項目屬性中添加GdiPlus.lib庫作為連結器輸入的附加依賴項)
// GdipDraw.h
……
class CGdipDrawApp : public CWinApp
{
public:
CGdipDrawApp();
ULONG_PTR m_gdiplusToken;
……
};
// GdipDraw.cpp
……
#include <gdiplus.h>
using namespace Gdiplus;
……
BOOL CGdipDrawApp::InitInstance()
{
// 如果一個運行在 Windows XP 上的應用程式資訊清單指定要
// 使用 ComCtl32.dll 版本 6 或更高版本來啟用可視化方式,
//則需要 InitCommonControlsEx()。否則,將無法建立視窗。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 將它設定為包括所有要在應用程式中使用的
// 公用控制項類。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
/*注意:下面這兩個語句必須加在CWinApp:: InitInstance ();語句之前,不然以後會造成視圖視窗不能自動重畫、程式中不能使用字型等等一系列問題。*/
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
CWinApp::InitInstance();
……
}
……
int CGdipDrawApp::ExitInstance() // 該函數是自己利用屬性視窗,添加的重寫函數
{
// TODO: 在此添加專用代碼和/或調用基類
GdiplusShutdown(m_gdiplusToken);
return CWinApp::ExitInstance();
}
3)幾何輔助類
在GDI+ API中,定義了許多繪圖的輔助類,常用的有點、大小和矩形等幾何類。它們都是沒有基類的獨立類,被定義在標頭檔GdiplusTypes.h中。下面逐個進行介紹:
(1)Point[F](點)
GDI+中,有兩種類型的點:整數點(對應於Point類)和浮點數點(對應於PointF類)。下面分別加以介紹:
<!--[if !supportLists]-->l <!--[endif]-->整數點類Point:
class Point {
public:
Point() {X = Y = 0;}
Point(const Point &point) {X = point.X; Y = point.Y;}
Point(const Size &size) {X = size.Width; Y = size.Height;}
Point(INT x, INT y) {X = x; Y = y;}
Point operator+(const Point& point) const {return Point(X + point.X, Y + point.Y);}
Point operator-(const Point& point) const {return Point(X - point.X, Y - point.Y);}
BOOL Equals(const Point& point) {return (X == point.X) && (Y == point.Y);}
public:
INT X; // 大寫X、Y
INT Y;
};
其中:
typedef int INT; // 4位元組有符號整數(windef.h)
注意,這裡的點與GDI的區別:
POINT和CPoint:{x; y;} // 小寫x、y
<!--[if !supportLists]-->l <!--[endif]-->浮點數點類PointF:
class PointF {
public:
PointF() {X = Y = 0.0f;}
PointF(const PointF &point) {X = point.X; Y = point.Y;}
PointF(const SizeF &size) {X = size.Width; Y = size.Height;}
PointF(REAL x, REAL y) {X = x; Y = y;}
PointF operator+(const PointF& point) const {return PointF(X + point.X,Y + point.Y);}
PointF operator-(const PointF& point) const {
return PointF(X - point.X, Y - point.Y);
}
BOOL Equals(const PointF& point) {
return (X == point.X) && (Y == point.Y);
}
public:
REAL X;
REAL Y;
};
其中:
typedef float REAL; // 4位元組浮點數(GdiplusTypes.h)
注意,浮點數版的幾何對象和繪圖函數,是GDI+新增的功能,這些在各種工程技術領域都非常有用。因為一般的實際圖形設計,都是基於實數座標的。包括機械(機床/汽車/輪船/飛機等)、建築(房屋/橋樑/道路/堤壩等)和圖形動畫設計(形狀/物體/人物/背景/軌跡等)等設計,都必須使用浮點參數和座標系。
(2)Size[F](大小)
GDI+中,也有兩種類型的大小(尺寸):整數大小(對應於Size類)和浮點數大小(對應於SizeF類)。下面分別加以介紹:
<!--[if !supportLists]-->l <!--[endif]-->整數大小類Size:
class Size {
public:
Size() {Width = Height = 0;}
Size(const Size& size) {Width = size.Width; Height = size.Height;}
Size(INT width, INT height) {Width = width; Height = height;}
Size operator+(const Size& sz) const {
return Size(Width + sz.Width, Height + sz.Height);
}
Size operator-(const Size& sz) const {
return Size(Width - sz.Width, Height - sz.Height);
}
BOOL Equals(const Size& sz) const {
return (Width == sz.Width) && (Height == sz.Height);
}
BOOL Empty() const {return (Width == 0 && Height == 0);}
public:
INT Width; // 不是cx和cy
INT Height;
};
注意,這裡的大小與GDI的區別:
SIZE和CSize:{cx; cy;} // 不是寬和高
<!--[if !supportLists]-->l <!--[endif]-->浮點數大小類SizeF:
class SizeF {
public:
SizeF() {Width = Height = 0.0f;}
SizeF(const SizeF& size) {Width = size.Width; Height = size.Height;}
SizeF(REAL width, REAL height) {Width = width; Height = height;}
SizeF operator+(const SizeF& sz) const {
return SizeF(Width + sz.Width, Height + sz.Height);
}
SizeF operator-(const SizeF& sz) const {
return SizeF(Width - sz.Width, Height - sz.Height);
}
BOOL Equals(const SizeF& sz) const {
return (Width == sz.Width) && (Height == sz.Height);
}
BOOL Empty() const {return (Width == 0.0f && Height == 0.0f);}
public:
REAL Width;
REAL Height;
};
(3)Rect[F](矩形)
GDI+中,也有兩種類型的矩形:整數矩形(對應於Rect類)和浮點數矩形(對應於RectF類)。下面分別加以介紹:
<!--[if !supportLists]-->l <!--[endif]-->整數矩形類Rect:
class Rect {
public:
Rect() {X = Y = Width = Height = 0;}
Rect(INT x, INT y, INT width, INT height);
Rect(const Point& location, const Size& size);
Rect* Clone() const;
VOID GetLocation(OUT Point* point) const;
VOID GetSize(OUT Size* size) const;
VOID GetBounds(OUT Rect* rect) const;
INT GetLeft() const {return X;}
INT GetTop() const {return Y;}
INT GetRight() const {return X+Width;}
INT GetBottom() const {return Y+Height;}
BOOL IsEmptyArea() const{return (Width <= 0) || (Height <= 0);}
BOOL Equals(const Rect & rect) const;
BOOL Contains(INT x, INT y) const;
BOOL Contains(const Point& pt) const;
BOOL Contains(Rect& rect) const;
VOID Inflate(INT dx, INT dy) {
X -= dx; Y -= dy;
Width += 2*dx; Height += 2*dy;
}
VOID Inflate(const Point& point) {Inflate(point.X, point.Y);}
BOOL Intersect(const Rect& rect) {return Intersect(*this, *this, rect);}
static BOOL Intersect(OUT Rect& c, const Rect& a, const Rect& b);
BOOL IntersectsWith(const Rect& rect) const;
static BOOL Union(OUT Rect& c, const Rect& a, const Rect& b);
VOID Offset(const Point& point);
VOID Offset(INT dx, INT dy);
public:
INT X; // 不是left和top
INT Y;
INT Width; // 更不是right和bottom
INT Height;
};
注意,這裡的矩形與GDI的區別:
RECT:{left; top; right; bottom;}; // 不是寬和高
雖然Rect中的(X, Y)等價於RECT的( left, top),但是Rect中的(Width, Height)卻不同於RECT的( right, bottom)。
<!--[if !supportLists]-->l <!--[endif]-->浮點數矩形類RectF:
class RectF {
public:
RectF() {X = Y = Width = Height = 0.0f;}
RectF(REAL x, REAL y, REAL width, REAL height);
RectF(const PointF& location, const SizeF& size);
RectF* Clone() const;
VOID GetLocation(OUT PointF* point) const;
VOID GetSize(OUT SizeF* size) const;
VOID GetBounds(OUT RectF* rect) const;
REAL GetLeft() const;
REAL GetTop() const;
REAL GetRight() const;
REAL GetBottom() const;
BOOL IsEmptyArea() const;
BOOL Equals(const RectF & rect) const;
BOOL Contains(REAL x, REAL y) const;
BOOL Contains(const PointF& pt) const;
BOOL Contains(const RectF& rect) const;
VOID Inflate(REAL dx, REAL dy);
VOID Inflate(const PointF& point);
BOOL Intersect(const RectF& rect);
static BOOL Intersect(OUT RectF& c, const RectF& a, const RectF& b);
BOOL IntersectsWith(const RectF& rect) const;
static BOOL Union(OUT RectF& c, const RectF& a, const RectF& b);
VOID Offset(const PointF& point);
VOID Offset(REAL dx, REAL dy);
public:
REAL X;
REAL Y;
REAL Width;
REAL Height;
};
在GDI的MFC封裝中,也有點、大小和矩形的
<!--[if !supportLists]-->n <!--[endif]-->結構:(windef.h)
typedef struct tagPOINT {LONG x; LONG y;} POINT; // typedef long LONG;
typedef struct tagSIZE {LONG cx; LONG cy;} SIZE;
typedef struct tagRECT {LONG left; LONG top; LONG right; LONG bottom;} RECT;
<!--[if !supportLists]-->n <!--[endif]-->類:(atltypes.h)
class CPoint : public tagPOINT {
public:
CPoint() throw();
CPoint(int initX, int initY) throw();
……
}
class CSize : public tagSIZE {
public:
CSize() throw();
CSize(int initCX, int initCY) throw();
……
}
class CRect : public tagRECT {
public:
CRect() throw();
CRect(int l, int t, int r, int b) throw();
……
}
可見,這幾個類都是從對應的結構派生的。GDI中,之所以有了類還要保留結構,主要是考慮效率和與底層GDI API的相容。
比較可知,GDI和GDI+都有對應的類,不過GDI+沒有對應的結構(但有浮點數版類),而GDI則沒有對應的浮點數版類(但卻有結構)。