昨天写了个简单的自绘按钮,使用的几个模式如下:
Factory Method , Abstract Factory , Strategy , Decorator部分代码如下:
//DataInterface.h#ifndef _DATAINTERFACE_H_
#define _DATAINTERFACE_H_/*------------------------------- 说明 ------------------------------
 * 功能:简单演示几个模式的使用。该文件中使用的模式有:Strategy Pattern
         Factory Method Pattern, Abstract Factory, Decorator Pattern
 * 作者:吴龙为,吉首大学,2002-6-18
 * 版本:2.0 
 * 版权所有(c), 可以随便修改和使用,但请将修改后的文件发一份到邮箱:
                    [email protected] * 修改:该版是2.0版,修改了其中的一个模式.1.0版在实现CSharp类是使用
         的是Strategy Pattern,为了支持平面按钮和支持更透明的操作,2.0
         版改用了Decorator Pattern,另外还增加了Abstract Factory Pattern * 注意:因为目的只是演示和学习,所以实现都比较简单,也没有很详细的优
         化,而且模式的选择可能也不是最好。大家如果有兴趣可以尝试改动
         和增加更多的模式,当然,写好后,请别忘了也给我一份学习学习
 *------------------------------------------------------------------*/
namespace face
{
    /*---------------------该类是一个数据基类---------------------------*/
    class CDataBase
    {
    public:
        CDataBase();
        virtual ~CDataBase();
    public:
        virtual    void DrawMouseIn(CDC *pDC);
        virtual void DrawMouseOut(CDC *pDC);
        virtual void DrawNormal(CDC *pDC) = 0;
        virtual void DrawFocus(CDC *pDC) = 0;
        virtual void DrawDown(CDC *pDC) = 0;
        virtual void DrawUp(CDC *pDC) = 0;
    public:
        void SetBkColor(COLORREF, COLORREF clrBkF = -1, COLORREF clrBkS = -1);
        void SetRect(const CRect &rc);
        const CRect & GetRect() const;
    public:                        
        //CSharp 类要取用该类成员
        COLORREF    m_clrBkN, m_clrBkF, m_clrBkS;
        CRect        m_rcBk;
    };
    //文本数据类
    class CTextData: public CDataBase
    {
    public:
        CTextData();
        virtual ~CTextData();
    public:
        virtual void DrawNormal(CDC *pDC);
        virtual void DrawFocus(CDC *pDC);
        virtual void DrawDown(CDC *pDC);
        virtual void DrawUp(CDC *pDC);
    public:
        void SetTextColor(COLORREF, COLORREF clrTextF = -1, COLORREF clrTextS = -1);
        void SetText(CString &szText);
    protected:
        void InternalDrawText(CDC *pDC, CRect &rc, COLORREF clrText);
    protected:
        COLORREF m_clrTextN, m_clrTextF,m_clrTextS;
        CString     m_szText;
    };

解决方案 »

  1.   

    ----------------------------------------------------------------*/
        /*----------------图象的生成类,这是一个Factory Method ---------*/
        class CImageMgr;
        class CImageMaker
        {
        public:
            //Make Bitmap
            CImageMgr *MakeBitmapImage(UINT idBitmap,COLORREF clrTransparent = -1, bool bStretch = false);
            CImageMgr *MakeBitmapImage(LPCTSTR szBitmap,COLORREF clrTransparent = -1, bool bStretch = false);        //Make Icon
            CImageMgr *MakeIconImage(UINT idIcon);
            CImageMgr *MakeIconImage(LPCTSTR szIcon);
        };
        //--------------------------------------------------------------    class CImageData: public CTextData
        {
        public:
            CImageData();
            virtual ~CImageData();
        public:
            //设置图象和文本位置的函数
            void  SetImageLeft();
            void  SetImageRight();
            void  SetImageDown();
            void  SetImageOnly();
            //设置图片
            void  SetImage(CImageMgr *pImageNormal, CImageMgr *pImageFocus = NULL, CImageMgr *pImageSelected =NULL);
        public:
            virtual void DrawNormal(CDC *pDC);
            virtual void DrawFocus(CDC *pDC);
            virtual void DrawDown(CDC *pDC);
            virtual void DrawUp(CDC *pDC);
        private:
            //内部绘制函数
            void InternalDrawImage(CDC *pDC,COLORREF &clrText, CImageMgr *pImage);
            //文本和图象绘制区域的初始化函数
            void InternalInitRect();
        private:
            CImageMgr    *m_pImageMgrN;        //Strategy(策略) pattern
            CImageMgr    *m_pImageMgrF;        
            CImageMgr    *m_pImageMgrS;
        private:
            CRect        m_rcImage;            //图象绘制的矩形区域
            CRect        m_rcText;            //文本绘制的矩形区域
        private:
            bool        m_bInitRect;        //是否已经初始化了绘制区域
            enum    enumImageSize { IMAGE_LEFT, IMAGE_RIGHT, 
                IMAGE_DOWN, IMAGE_ONLY };
            enumImageSize    m_eImageSize;    //图象的绘制范围变量
        };
        
        //--------------------------------------------------------------------
            
        /*---------------图象的管理类,这是一个Strategy(策略)模式-----------*/
        class CImageMgr
        {
        public:
            virtual ~CImageMgr();
        public:
            virtual    void DrawImage(CDC *pDC, const CRect &rc) = 0;
            virtual const CSize & GetImageSize() const;
        protected:
            CSize    m_imageSize;
        };
        
        class CImageBitmap : public CImageMgr
        {
        public:
            CImageBitmap(UINT idBitmap,COLORREF clrTransparent = -1, bool bStretch=false);
            CImageBitmap(LPCTSTR szBitmap, COLORREF clrTransparent = -1, bool bStretch=false);
            virtual ~CImageBitmap();
        public:
            virtual void DrawImage(CDC *pDC, const CRect &rc);
            void  SetStretch(bool bStretch);
            void  SetTransparentColor(const COLORREF clrTransparent);
        private:
            CBitmap        m_imageBitmap;
            COLORREF    m_clrTransparent;
            bool        m_bStretch;
        };
        
        class CImageIcon : public CImageMgr
        {
        public:
            CImageIcon(UINT idIcon);
            CImageIcon(LPCTSTR szIcon);
            virtual ~CImageIcon();
        public:
            virtual void DrawImage(CDC *pDC, const CRect &rc);
        private:
            HICON    m_hIcon;
        };
        //-------------------------------------------------------------------
        
        /*----------------CSharp类,管理形状,是一个Decorator模式--------*/
        class CSharp : public CDataBase
        {
        public:
            CSharp(CDataBase *pDataBase , int nBorderWidth = 2);
            virtual ~CSharp();
        public:
            //CDataBase functions
            virtual    void DrawMouseIn(CDC *pDC);
            virtual void DrawMouseOut(CDC *pDC);
            virtual void DrawNormal(CDC *pDC);
            virtual void DrawFocus(CDC *pDC);
            virtual void DrawDown(CDC *pDC);
            virtual void DrawUp(CDC *pDC);
        public:
            void    SetBorderWidth(int nBorderWidth);
            void    SetFlat(bool bFlat);
        private:
            virtual void FillSharp(CDC *pDC,COLORREF clrFill) = 0;
            virtual void DrawBorder(CDC *pDC, bool bDown) = 0;
            virtual    void DrawFlat(CDC *pDC,COLORREF &clrPen) = 0;
        protected:
            CDataBase    *m_pDataBase;        //Decorator Pattern
            int            m_nBorderWidth;
            bool        m_bFlat;            //if the sharp 3D or Flat
        };
        
        class CRectangle : public CSharp
        {
        public:
            CRectangle(CDataBase *pDataBase, int nBorderWidth = 2);
            virtual ~CRectangle();
        private:
            virtual void FillSharp(CDC *pDC,COLORREF clrFill);
            virtual void DrawBorder(CDC *pDC, bool bDown);
            virtual void DrawFlat(CDC *pDC, COLORREF &clrPen);
        };
        
        class CEllipse : public CSharp
        {
        public:
            CEllipse(CDataBase *pDataBase, int nBorderWidth = 2);
            virtual ~CEllipse();
        private:
            virtual void FillSharp(CDC *pDC,COLORREF clrFill);
            virtual void DrawBorder(CDC *pDC,bool bDown);
            virtual void DrawFlat(CDC *pDC, COLORREF &clrPen);
        };    /*------------------Abstract Factory Pattern -------------------
         * 优点:使得产品组合透明和一致
         * 缺点:带来许多小的类
         *-------------------------------------------------------------*/
        class CButtonFactory
        {
        public:
            //Make Sharp
            virtual CSharp * MakeSharp(CDataBase *pDataBase, int nBorderWidth = 2) = 0;
        public:
            //Make data
            virtual CDataBase * MakeData() = 0;
        };
        class CRectangleTextFactory : public CButtonFactory
        {
        public:
            virtual CSharp * MakeSharp(CDataBase *pDataBase, int nBorderWidth = 2);
            virtual CDataBase *MakeData();
        };
        class CRectangleImageFactory : public CButtonFactory
        {
        public:
            virtual CSharp * MakeSharp(CDataBase *pDataBase, int nBorderWidth = 2);
            virtual CDataBase *MakeData();
        };
        class CEllipseImageFactory : public CButtonFactory
        {
        public:
            virtual CSharp *MakeSharp (CDataBase *pDataBase , int nBorderWidth = 2);
            virtual CDataBase *MakeData ();
        };
        class CEllipseTextFactory : public CButtonFactory
        {
        public:
            virtual CSharp *MakeSharp (CDataBase *pDataBase, int nBorderWidth =2);
            virtual CDataBase *MakeData();
        };
    }#endif//_DATAINTERFACE_H_
      

  2.   

    //DataInterface.cpp #include "DataInterface.h" #pragma comment(lib,"msimg32")        //for TransparentBlt function namespace face 

       //----------------------CDataBase class --------------------------- 
       CDataBase::CDataBase() 
       { 
           m_clrBkN = m_clrBkF = m_clrBkS = ::GetSysColor(COLOR_BTNFACE); 
           m_rcBk.SetRectEmpty(); 
       } 
       CDataBase::~CDataBase () 
       {}    void CDataBase:<img src="images/smilies/biggrin.gif" border="0" alt="">rawMouseIn (CDC *pDC) 
       { 
           DrawFocus(pDC); 
       } 
       void CDataBase:<img src="images/smilies/biggrin.gif" border="0" alt="">rawMouseOut (CDC *pDC) 
       { 
           DrawNormal(pDC); 
       }    void CDataBase::SetBkColor (COLORREF clrBkN, COLORREF clrBkF, COLORREF clrBkS) 
       { 
           m_clrBkN = clrBkN;        if(m_clrBkF != -1) 
               m_clrBkF = clrBkF; 
           else 
               m_clrBkF = m_clrBkN; 
           if(m_clrBkS != -1) 
               m_clrBkS = clrBkS; 
           else 
               m_clrBkS = m_clrBkN; 
       } 
       void CDataBase::SetRect (const CRect &rc) 
       { 
           m_rcBk.CopyRect (&rc); 
       } 
       const CRect & CDataBase::GetRect() const 
       { 
           return m_rcBk; 
       }    //---------------------CTextData class -------------------------- 
       CTextData::CTextData() 
       { 
           m_clrTextN = m_clrTextF = m_clrTextS = ::GetSysColor(COLOR_BTNTEXT); 
           m_szText = _T(""); 
       } 
       CTextData::~CTextData() 
       {}    void CTextData::SetText (CString &szText) 
       { 
           m_szText = szText; 
       } 
       void CTextData::SetTextColor (COLORREF clrTextN, COLORREF clrTextF, COLORREF clrTextS) 
       { 
           m_clrTextN = clrTextN; 
           if(clrTextF != -1) 
               m_clrTextF = clrTextF; 
           else 
               m_clrTextF = m_clrTextN; 
           if(clrTextS != -1) 
               m_clrTextS = clrTextS; 
           else 
               m_clrTextS = m_clrTextN; 
       }    inline void CTextData::InternalDrawText (CDC *pDC , CRect &rc, COLORREF clrText) 
       { 
           pDC->SetTextColor (clrText); 
           pDC->SetBkMode (TRANSPARENT); 
           pDC->DrawText (m_szText, rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); 
       }    inline void CTextData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawNormal (CDC *pDC) 
       { 
           InternalDrawText(pDC, m_rcBk, m_clrTextN); 
       } 
       inline void CTextData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawFocus (CDC *pDC) 
       { 
           InternalDrawText(pDC, m_rcBk, m_clrTextF);        //draw the test, if has 
       } 
       inline void CTextData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawDown (CDC *pDC) 
       { 
           InternalDrawText(pDC, m_rcBk, m_clrTextS); 
       } 
       inline void CTextData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawUp (CDC *pDC) 
       { 
           InternalDrawText(pDC, m_rcBk, m_clrTextF); 
       } 
      

  3.   

    //--------------------CImageData class -------------------------- 
       CImageData::CImageData() 
           :m_bInitRect(false),m_eImageSize(IMAGE_LEFT) 
       { 
           m_pImageMgrN = m_pImageMgrF = m_pImageMgrS = NULL; 
       }    CImageData::~CImageData () 
       { 
           if(m_pImageMgrN) 
               delete m_pImageMgrN; 
           if(m_pImageMgrF) 
               delete m_pImageMgrF; 
           if(m_pImageMgrS) 
               delete m_pImageMgrS; 
       }    void CImageData::SetImageLeft () 
       { 
           m_eImageSize = IMAGE_LEFT; 
       } 
       void CImageData::SetImageRight () 
       { 
           m_eImageSize = IMAGE_RIGHT; 
       } 
       void CImageData::SetImageDown () 
       { 
           m_eImageSize = IMAGE_DOWN; 
       } 
       void CImageData::SetImageOnly () 
       { 
           m_eImageSize = IMAGE_ONLY; 
       }    //设置图象和文本的绘制区域 
       void CImageData::InternalInitRect() 
       { 
           m_bInitRect = true;        //置区域初始化标志位为真 
            
           switch(m_eImageSize) 
           { 
           case IMAGE_LEFT: 
               { 
                   //set the image and text rectangle 
                   m_rcImage.SetRect (m_rcBk.left , m_rcBk.top , m_rcBk.left + m_rcBk.Width ()/2, 
                       m_rcBk.bottom ); 
                   const CSize    &size = m_pImageMgrN->GetImageSize (); 
                   //center the image 
                   m_rcImage.DeflateRect ( (m_rcImage.Width () - size.cx ) /2, 
                       (m_rcImage.Height () - size.cy )/2 ); 
                   m_rcText.SetRect (m_rcImage.right, m_rcBk.top , m_rcBk.right , 
                       m_rcBk.bottom ); 
               } 
               break; 
           case IMAGE_RIGHT: 
               { 
                   m_rcImage.SetRect (m_rcBk.left + m_rcBk.Width ()/2, m_rcBk.top , m_rcBk.right , 
                       m_rcBk.bottom ); 
                   const CSize    &size = m_pImageMgrN->GetImageSize (); 
                   m_rcImage.DeflateRect ( (m_rcImage.Width () - size.cx ) /2, 
                       (m_rcImage.Height () - size.cy )/2 ); 
                   m_rcText.SetRect (m_rcBk.left , m_rcBk.top , m_rcImage.left , 
                       m_rcBk.bottom ); 
               } 
               break; 
           case IMAGE_DOWN: 
               { 
                   m_rcImage.CopyRect (&m_rcBk); 
                   const CSize    &size = m_pImageMgrN->GetImageSize (); 
                   m_rcImage.DeflateRect ( (m_rcImage.Width () - size.cx ) /2, 
                       (m_rcImage.Height () - size.cy )/2 ); 
                   m_rcText.CopyRect (&m_rcBk); 
               } 
               break; 
           case IMAGE_ONLY: 
               { 
                   m_rcImage.CopyRect (&m_rcBk); 
                   const CSize    &size = m_pImageMgrN->GetImageSize (); 
                   m_rcImage.DeflateRect ( (m_rcImage.Width () - size.cx ) /2, 
                       (m_rcImage.Height () - size.cy )/2 ); 
                   m_rcText.SetRectEmpty (); 
               } 
               break; 
           default: 
               break; 
           } 
       } 
        
       inline void CImageData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawNormal (CDC *pDC) 
       { 
           InternalDrawImage(pDC,m_clrTextN, m_pImageMgrN); 
       } 
       inline void CImageData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawFocus (CDC *pDC) 
       { 
           InternalDrawImage(pDC, m_clrTextF, m_pImageMgrF); 
       } 
       inline void CImageData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawDown (CDC *pDC) 
       { 
           InternalDrawImage(pDC, m_clrTextS, m_pImageMgrS); 
       } 
       inline void CImageData:<img src="images/smilies/biggrin.gif" border="0" alt="">rawUp (CDC *pDC) 
       { 
           InternalDrawImage(pDC,m_clrTextF, m_pImageMgrF); 
       }    void CImageData::InternalDrawImage(CDC *pDC, COLORREF &clrText, CImageMgr *pImage) 
       { 
           if(!m_bInitRect) 
               InternalInitRect();        if(pImage) 
               pImage->DrawImage (pDC, m_rcImage);                //draw image 
           else 
               m_pImageMgrN->DrawImage (pDC, m_rcImage);        if( !m_rcText.IsRectEmpty ()) 
               InternalDrawText(pDC, m_rcText, clrText);        //draw text 
       }    void CImageData::SetImage (CImageMgr *pImageNormal, CImageMgr *pImageFocus, CImageMgr *pImageSelected) 
       { 
           m_pImageMgrN = pImageNormal; 
           m_pImageMgrF = pImageFocus; 
           m_pImageMgrS = pImageSelected; 
       }