VC2003“项目/*属性”菜单项,打开项目的属性页窗口,先选“所有配置”,再选“配置属性/链接器/输入”项,在右边上部的“附加依赖项”栏的右边,键入GdiPlus.lib 后按“应用”钮,最后按“确定”钮关闭对话框。 在需要用到GDI+的文件头加上下面两句
并在该类的初始化函数CGDIPlusDemoApp::InitInstance() 中加入以下代码来对GDI+进行初始化: GdiplusStartupInput gdiplusStartupInput; 注意:这两个语句必须加在应用程序类的InitInstance函数中的
上面是所需步骤..
封装在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+的初始化与清除 函数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)几何辅助类 (1)Point[F](点) <!--[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](大小) <!--[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](矩形) <!--[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则没有对应的浮点数版类(但却有结构)。 |
|