MFC使用GDI+编程基础

    技术2022-05-11  19

    MFC使用GDI+编程设置 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;

    ……

    1GdiPlus.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

    2GDI+的初始化与清除

    为了在MFC应用程序中使用采用C++封装的GDI+ API,必须在MFC项目的应用程序类中,调用GDI+命名空间中的GDI+启动函数GdiplusStartupGDI+关闭函数GdiplusShutdown,来对GDI+进行初始化(装入动态链接库Gdiplus.dll,或锁定标志+1)和清除(卸载动态链接库Gdiplus.dll,或锁定标志-1)工作。它们一般分别在应用程序类的InitInstanceExitInstance重载成员函数中调用。

    函数GdiplusStartupGdiplusShutdown,都被定义在GdiplusInit.h头文件中:

    Status WINAPI GdiplusStartup(

        OUT ULONG_PTR *token,

        const GdiplusStartupInput *input,

        OUT GdiplusStartupOutput *output);

    void GdiplusShutdown(ULONG_PTR token);

    其中:

    l     类型ULONG_PTR,是用无符号长整数表示的指针,被定义在basetsd.h头文件中:

    typedef _W64 unsigned long ULONG_PTR;

    输出参数token(权标),供关闭GDI+的函数使用,所以必须设置为应用程序类的成员变量(或全局变量,不提倡)。

    l     结构GdiplusStartupInputGdiplusStartupOutput,也都被定义在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;

    };

    n              GDI+启动输入结构指针参数input,一般取缺省构造值即可,即(设:无调试事件回调过程、不抑制背景线程、不抑制外部编解码):

    input = GdiplusStartupInput(NULL, FALSE, FALSE);

    n              GDI+启动输出结构指针参数output,一般不需要,取为NULL即可。

     

    注意,采用MFC进行GDI+ API编程时,在使用任何GDI+的功能调用之前,必须先调用GDI+启动函数GdiplusStartup来进行初始化GDI+的工作;在完成所有的GDI+功能调用之后,必须调用GDI+关闭函数GdiplusShutdown来进行清除GDI+的工作。

    例如:(创建一个名为GdipDrawMFC单文档应用程序项目,在项目属性中添加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中。下面逐个进行介绍:

    1Point[F](点)

    GDI+中,有两种类型的点:整数点(对应于Point类)和浮点数点(对应于PointF类)。下面分别加以介绍:

    l     整数点类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; // 大写XY

        INT Y;

    };

    其中:

    typedef int  INT; // 4字节有符号整数(windef.h

    注意,这里的点与GDI的区别:

    POINTCPoint{x; y;} // 小写xy

     

    l     浮点数点类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+新增的功能,这些在各种工程技术领域都非常有用。因为一般的实际图形设计,都是基于实数坐标的。包括机械(机床/汽车/轮船/飞机等)、建筑(房屋/桥梁/道路/堤坝等)和图形动画设计(形状/物体/人物/背景/轨迹等)等设计,都必须使用浮点参数和坐标系。

    2Size[F](大小)

    GDI+中,也有两种类型的大小(尺寸):整数大小(对应于Size类)和浮点数大小(对应于SizeF类)。下面分别加以介绍:

    l     整数大小类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; // 不是cxcy

        INT Height;

    };

    注意,这里的大小与GDI的区别:

    SIZECSize{cx; cy;} // 不是宽和高

     

    l     浮点数大小类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;

    };

    3Rect[F](矩形)

    GDI+中,也有两种类型的矩形:整数矩形(对应于Rect类)和浮点数矩形(对应于RectF类)。下面分别加以介绍:

    l     整数矩形类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; // 不是lefttop

        INT Y;

        INT Width; // 更不是rightbottom

        INT Height;

    };

    注意,这里的矩形与GDI的区别:

    RECT{left; top; right; bottom;}; // 不是宽和高

    虽然Rect中的(X, Y)等价于RECT( left, top),但是Rect中的(Width, Height)却不同于RECT( right, bottom)

     

    l     浮点数矩形类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;

    };

     

    GDIMFC封装中,也有点、大小和矩形的

    n         结构:(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;

     

    n         类:(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的兼容。

    比较可知,GDIGDI+都有对应的类,不过GDI+没有对应的结构(但有浮点数版类),而GDI则没有对应的浮点数版类(但却有结构)。

    width="728" scrolling="no" height="90" frameborder="0" align="middle" marginwidth="0" marginheight="0" src="http://download1.csdn.net/down3/20070601/01184120111.htm">

    最新回复(0)