發新話題

[教學]MFCmodel 對話盒的使用

[教學]MFCmodel 對話盒的使用

複製內容到剪貼板
代碼:
#include <afxwin.h>
#include "resource.h"
#include <afxtempl.h>
#include <afxext.h>
#include <math.h>        //增加math標頭檔

class GraphicObject : public CObject
{        //儲存形狀物件的類別,衍生自CObject類別以便具備儲存(Serialize)功能
public:
        int shapenum;        //形狀代號
        BOOL fill;        //是否填滿
        COLORREF FillColor, LineColor;        //填滿顏色與外框顏色
        int width;        //外框寬度
        CPoint StartPnt, EndPnt;        //形狀的起點與終點

        GraphicObject(){}        //預設建構子
        //一般建構子
        GraphicObject(int shapenum, BOOL fill, COLORREF FillColor,
                COLORREF LineColor,int width, CPoint StartPnt, CPoint EndPnt)
                : shapenum(shapenum), fill(fill), FillColor(FillColor)
                , LineColor(LineColor),width(width), StartPnt(StartPnt),
                EndPnt(EndPnt) {}
        GraphicObject(GraphicObject & g)        //複製建構子
                : shapenum(g.shapenum), fill(g.fill), FillColor(g.FillColor),
                LineColor(g.LineColor),        width(g.width), StartPnt(g.StartPnt),
                EndPnt(g.EndPnt) {}
        //過載=運算子
        GraphicObject & operator= (GraphicObject & g){
                shapenum = g.shapenum;
                fill = g.fill;
                FillColor = g.FillColor;
                LineColor = g.LineColor;
                width = g.width;
                StartPnt = g.StartPnt;
                EndPnt = g.EndPnt;
                return *this;
        }
        //GraphicObejct::Serialize
        void Serialize(CArchive & ar)
        {
                CObject::Serialize(ar);
                if(ar.IsStoring())        //判斷是否為存檔
                {        //輸出至檔案
                        ar << shapenum << fill << FillColor << LineColor
                                << width << StartPnt << EndPnt;        
                }
                else
                {        //從檔案輸入
                        ar >> shapenum >> fill >> FillColor >> LineColor
                                >> width >> StartPnt >> EndPnt;
                }
        }

        DECLARE_SERIAL(GraphicObject)        //宣告為可Serialize的類別
};
//宣告GraphicObject為可Serialize的類別
IMPLEMENT_SERIAL(GraphicObject, CObject, 1)

class Shape        //形狀類別的基礎類別
{
protected:
        CPoint StartPnt, EndPnt;        //定義形狀的終點與起點
        int shapenum;        //形狀代號
        friend class MyView;        //將MyView設為friend類別,方便資料存取
public:
        //建構子
        Shape(CPoint StartPnt, CPoint EndPnt, int shapenum)
                : StartPnt(StartPnt), EndPnt(EndPnt), shapenum(shapenum) {}
        //複製建構子
        Shape(Shape & s)
                : StartPnt(s.StartPnt), EndPnt(s.EndPnt), shapenum(s.shapenum) {}
        Shape () {}
        //過載=運算子
        Shape & operator= (Shape & s)
        {
                StartPnt = s.StartPnt;        //設定起點
                EndPnt = s.EndPnt;        //設定終點
                return *this;
        }
        //Shape::draw
        virtual void draw(CDC & aDC, COLORREF color, COLORREF fcolor,
                        int width,BOOL Filled = false) = 0;
        //Shape::GetShapeNum
        int GetShapeNum()        //取得形狀代號
        { return shapenum; }
        //Shape::SetPoint
        void SetPoint(CPoint SPnt, CPoint EPnt)        //設定形狀的起點、終點
        {
                StartPnt = SPnt;
                EndPnt = EPnt;
        }
};

class Line : public Shape        //直線類別
{
public:
        friend class MyView;
        //預設建構子
        Line () { shapenum = 0;}
        //建構子
        Line(CPoint StartPnt, CPoint EndPnt) : Shape(StartPnt, EndPnt,0){}
        //複製建構子
        Line (Line & l) : Shape(l.StartPnt, l.EndPnt, 0){}
        //過載=運算子
        Line & operator= (Line & l)
        {
                StartPnt = l.StartPnt;
                EndPnt = l.EndPnt;
                return *this;               
        }

        //Line::draw 繪出直線
        void draw(CDC &dc, COLORREF color, COLORREF fcolor,
                 int width, BOOL Filled = false)
        {
                CPen pen(PS_SOLID, width, color);        //建立畫筆物件
                CPen *oldPen = dc.SelectObject(&pen);        //設定DC物件使用pen物件

                dc.MoveTo(StartPnt);        //移至直線起點
                dc.LineTo(EndPnt);        //移至直線終點

                dc.SelectObject(oldPen);        //還原選取的畫筆物件
        }
};

class ellipse : public Shape        //橢圓形類別
{
public:
        //預設建構子
        ellipse () { shapenum = 1; }
        //建構子
        ellipse(CPoint StartPnt, CPoint EndPnt) : Shape(StartPnt, EndPnt, 1) {}
        //複製建構子
        ellipse (ellipse & e) : Shape(e.StartPnt, e.EndPnt, 1){}
        //過載=運算子
        ellipse & operator= (ellipse & e)
        {
                StartPnt = e.StartPnt;
                EndPnt = e.EndPnt;
                return *this;               
        }
        //ellipse::draw   繪出橢圓
        void draw(CDC & dc, COLORREF color, COLORREF fcolor,
                 int width,BOOL Filled = false)
        {
                CRect rect(StartPnt, EndPnt);        //建立CRect物件
        
                CPen pen(PS_SOLID, width, color);        //建立畫筆物件
                CPen *oldPen = dc.SelectObject(&pen);        //設定DC物件使用pen物件

                dc.SelectStockObject(NULL_BRUSH);        //設定DC物件不使用畫筆
                dc.Ellipse(rect);        //繪出橢圓形

                dc.SelectObject(oldPen);        //還原畫筆物件
        }
};

class rectangle : public Shape        //矩形類別
{
public:
        rectangle () {shapenum = 2;}//預設建構子
        rectangle(CPoint StartPnt, CPoint EndPnt)        //建構子
                : Shape(StartPnt, EndPnt, 2) {}
        rectangle (rectangle & r)        //複製建構子
                : Shape(r.StartPnt, r.EndPnt, 2){}
        //過載=運算子
        rectangle & operator= (rectangle & r)        //過載=運算子
        {
                StartPnt = r.StartPnt;
                EndPnt = r.EndPnt;
                return *this;               
        }
        //rectangle        ::draw                繪出矩形
        void draw(CDC & dc, COLORREF color, COLORREF fcolor,
                 int width, BOOL Filled = false)
        {
                CRect rect(StartPnt, EndPnt);        //建立CRect物件

                CPen pen(PS_SOLID, width , color);        //建立畫筆物件
                CPen *oldPen = dc.SelectObject(&pen);        //設定DC物件使用pen物件
               
                dc.SelectStockObject(NULL_BRUSH);        //設定DC物件不使用無畫刷
                dc.Rectangle(rect);        //繪出矩形

                dc.SelectObject(oldPen);        //還原畫筆物件
        }
};

class MyDocument : public CDocument
{
private:
        CArray<GraphicObject , GraphicObject> gArray;
                //儲存GraphicObject物件的CArray容器物件
public:
        MyDocument() {}
        //MyDocument::AddObject
        void AddObject(GraphicObject & g)        //增加GraphicObject物件
        {
                SetModifiedFlag(true);        //設定檔案已被修改
                gArray.Add(g);
        }
        //MyDocument::GetObject 取得容器中第i個GraphicObject物件
        GraphicObject & GetObject(int i){ return gArray[i]; }
        //MyDocument::GetSize
        int GetSize()        //取得CArray容器目前儲存的元素數目
        { return gArray.GetSize(); }
        //MyDoucment::Serialize
        void Serialize(CArchive & ar)
        {
                CObject::Serialize(ar);        //呼叫CObject::Serialize
                gArray.Serialize(ar);        //呼叫CArray::Serialize儲存容器中的元素
        }
        //MyDocument::DeleteContents
        void DeleteContents()
        {
                gArray.RemoveAll();        //刪除容器中所有元素
                CDocument::DeleteContents();        //呼叫CDocument::DeleteContents
        }

        DECLARE_DYNCREATE(MyDocument)
        DECLARE_MESSAGE_MAP()
};

IMPLEMENT_DYNCREATE(MyDocument, CDocument)

BEGIN_MESSAGE_MAP(MyDocument, CDocument)

END_MESSAGE_MAP()

class MyFrame : public CFrameWnd        //視窗框架類別
{
protected:
        CMenu * menu;
public:
        CToolBar toolbar;        //視窗框架中的工具列物件
        CStatusBar statusbar;        //視窗框架中的狀態列物件
        //建構子與解構子
        MyFrame(){}
        ~MyFrame(){}
        //MyFrame::OnCreate,回應OnCreate的函數
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)
        {
                if(CFrameWnd::OnCreate(lpCreateStruct))
                        return 1;

                toolbar.Create(this);        //建立工具列物件
                toolbar.LoadToolBar(IDR_MyFrame);        //載入工具列資源
                toolbar.EnableDocking(CBRS_ALIGN_ANY);
                                //設定工具列在視窗中可停靠的位置
                toolbar.SetBarStyle( toolbar.GetBarStyle() | CBRS_TOOLTIPS |
                        CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
                                //設定工具列的形式
                EnableDocking(CBRS_ALIGN_ANY);        //設定視窗可讓工具列停靠的位置
                DockControlBar(&toolbar);        //將工具列加入視窗框架

                //建立與狀態列對應之字串資源代號
                static UINT indicators[] =
                {
                        ID_SEPARATOR,        
                        IDS_Color,
                        IDS_Shape,
                        IDS_Width        //顯示筆寬
                };

                statusbar.Create(this);        //在目前的視窗框架裡,建立一個狀態列
                statusbar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT));
                                //連結狀態列欄位與字串資源代號
                return 0;
        }

        DECLARE_DYNCREATE(MyFrame)        //宣告為Run-Time類別
        DECLARE_MESSAGE_MAP()
};

IMPLEMENT_DYNCREATE(MyFrame, CFrameWnd)
                //宣告MyFrame為Run-Time類別
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)
        ON_WM_CREATE()        //回應建立視窗的訊息
END_MESSAGE_MAP()

class MyView : public CView
{
private:
        COLORREF lcolor, fcolor;
        //lcolor為形狀外框的顏色,fcolor為填滿形狀內部的顏色
        Shape* aShape;        //指向欲繪製之形狀類別的物件指標
        Shape* rdShape;        //rdShape為重繪視窗時,從Document中取得形狀物件
        int width; //形狀的外框寬度
public:
        //建構子
        MyView()
        {
                lcolor = RGB(255,0,0);        //設定外框顏色的起始值
                aShape = new Line;        //設定形狀的起始值
                fcolor = RGB(0,0,0); //設定填滿顏色的起始值
                width = 2; //形狀的外框寬度的起始值
        }
        //解構子
        ~MyView() { }
        //MyView::GetWidth
        int GetWidth() { return width;}        //傳出MyView物件設定的筆寬
        //MyView::OnSetWidth
        afx_msg void OnSetWidth();        //定義函數的程式片段在SWidthDlg類別後
        //MyView::OnEllipse
        afx_msg void OnEllipse()
        {
                aShape = new ellipse;        //產生橢圓形物件
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(2,"Ellipse");
                //設定狀態列IDS_Shape欄位的顯示文字
        }
        //MyView::OnRect
        afx_msg void OnRect()        
        {
                aShape = new rectangle;        //產生矩形物件
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(2,"Rectangle");
                //設定狀態列IDS_Shape欄位的顯示文字
        }
        //MyView::OnLine
        afx_msg void OnLine()
        {
                aShape = new Line;        //產生直線物件
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(2,"Line");
                //取得Document物件,並呼叫CStatusBar::SetPaneText設定狀態列
                //IDS_Shape欄位的顯示文字
        }
        //MyView::OnDraw
        afx_msg void OnDraw(CDC * aDC)        //回應重繪視窗訊息的函數
        {        
                MyDocument *doc = (MyDocument *)GetDocument();
                        //取得目前的Document物件
                int num = doc->GetSize();        //取得目前Document物件中儲存的形狀物件個數
                CView::OnDraw(aDC);        //呼叫CView類別的OnDraw成員函數
               
                int i;

                for(i = 0; i < num; ++i)        //取得儲存於Document物件中的形狀物件
                {
                        GraphicObject * object = &(doc->GetObject(i));
                                //建立指向繪圖物件的指標,並指向由Document物件中的形狀物件
                        switch(object->shapenum){        //判別從Document物件取得哪種形狀物件
                        case 0:                //然後,產生建立適當的形狀物件
                                rdShape = new Line;
                                break;
                        case 1:
                                rdShape = new ellipse;
                                break;
                        case 2:
                                rdShape = new  rectangle;
                                break;                        
                        };

                        rdShape->SetPoint(object->StartPnt, object->EndPnt);
                                //建立形狀物件的起點與終點
                        rdShape->draw((*aDC),object->LineColor, object->FillColor,
                                          object->width);        //繪出形狀物件

                        delete rdShape;        //刪除前面產生的形狀物件
                }        
        }
        //MyView::OnLButtonDown
        afx_msg void OnLButtonDown(UINT, CPoint point)
        {
                SetCapture();        //取得滑鼠訊息的接收權
                if (this == GetCapture())        //判斷滑鼠游標是否在正在執行的視窗中
                        (*aShape).StartPnt = (*aShape).EndPnt = point;
                        //設定形狀物件的起點、終點
        }
        //MyView::OnMouseMove
        afx_msg void OnMouseMove(UINT, CPoint point)
        {
                if (this == GetCapture())        //判斷滑鼠游標是否在正在執行的視窗中
                {
                        CClientDC aDC(this);        //建立畫布
                        aDC.SetROP2(R2_NOT);        //設定繪圖模式

                        (*aShape).draw(aDC, lcolor, fcolor, width);        //畫出形狀物件
                        (*aShape).EndPnt = point;        //設定終點
                        (*aShape).draw(aDC, lcolor, fcolor, width);        //再畫出形狀物件
                }
        }
        //MyView::OnLButtonUp
        afx_msg void OnLButtonUp(UINT, CPoint point)
        {
                if (this == GetCapture())        //判斷滑鼠游標是否在正在執行的視窗中
                {
                        CClientDC aDC(this);        //建立畫布

                        (*aShape).EndPnt = point;
                        //設定形狀物件的終點
                        (*aShape).draw(aDC, lcolor, fcolor, width);        //畫出形狀物件
                        
                        GraphicObject object(aShape->GetShapeNum(), true,
                                fcolor, lcolor, width,aShape->StartPnt,aShape->EndPnt);
                //建立GraphicObject物件,以儲存繪於視窗工作區的形狀物件
                        MyDocument *doc = (MyDocument *)GetDocument();
                        //取得目前的Document物件
                        doc->AddObject(object);        //將GraphicObject物件儲存進Document物件
                        
                        ReleaseCapture();        //釋放滑鼠訊息接收權
                }                        
        }
        //MyView::OnRed
        afx_msg void OnRed()
        {
                lcolor = RGB(255, 0, 0);        //設定圖形外框為紅色
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(1,"Red");
                //設定狀態列IDS_Color欄位的顯示文字
        }
        //MyView::OnBlue
        afx_msg void OnBlue()
        {
                lcolor = RGB(0, 0, 255);        //設定圖形外框為藍色
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(1,"Blue");
                //設定狀態列IDS_Color欄位的顯示文字
        }
        //MyView::OnGreen
        afx_msg void OnGreen()
        {
                lcolor = RGB(0, 255, 0);        //設定圖形外框為綠色
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(1,"Green");
                //設定狀態列IDS_Color欄位的顯示文字
        }
        //控制設定形狀物件的UI元件
        //MyView::OnUpdateEllipse
        afx_msg void OnUpdateEllipse(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck((*aShape).shapenum == 1); }
        //MyView::OnUpdateRect
        afx_msg void OnUpdateRect(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck((*aShape).shapenum == 2); }
        //MyView::OnUpdateLine
        afx_msg void OnUpdateLine(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck((*aShape).shapenum == 0); }

        //控制設定形狀物件的UI元件
        //MyView::OnUpdateRed
        afx_msg void OnUpdateRed(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck(lcolor == RGB(255, 0, 0)); }
        //MyView::OnUpdateGreen
        afx_msg void OnUpdateGreen(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck(lcolor == RGB(0, 255, 0)); }
        //MyView::OnUpdateBlue
        afx_msg void OnUpdateBlue(CCmdUI * aCmdUI)
        { aCmdUI->SetCheck(lcolor == RGB(0, 0, 255)); }

        DECLARE_DYNCREATE(MyView)        //宣告Run-Time物件
        DECLARE_MESSAGE_MAP()
};

IMPLEMENT_DYNCREATE(MyView, CView)
        //宣告MyView為Run-Time物件

BEGIN_MESSAGE_MAP(MyView, CView)
        ON_COMMAND(IDM_Width, OnSetWidth)        //設定筆寬
        //回應滑鼠訊息
        ON_WM_LBUTTONDOWN()
        ON_WM_MOUSEMOVE()
        ON_WM_LBUTTONUP()
        //回應顏色控制命令訊息
        ON_COMMAND(IDM_Red, OnRed)
        ON_COMMAND(IDM_Green, OnGreen)
        ON_COMMAND(IDM_Blue, OnBlue)
        //回應形狀控制命令訊息
        ON_COMMAND(IDM_Line, OnLine)
        ON_COMMAND(IDM_Ellipse, OnEllipse)
        ON_COMMAND(IDM_Rect, OnRect)
        //回應UI元件狀態控制訊息
        ON_UPDATE_COMMAND_UI(IDM_Red, OnUpdateRed)
        ON_UPDATE_COMMAND_UI(IDM_Green, OnUpdateGreen)
        ON_UPDATE_COMMAND_UI(IDM_Blue, OnUpdateBlue)
        ON_UPDATE_COMMAND_UI(IDM_Line, OnUpdateLine)
        ON_UPDATE_COMMAND_UI(IDM_Ellipse, OnUpdateEllipse)
        ON_UPDATE_COMMAND_UI(IDM_Rect, OnUpdateRect)
END_MESSAGE_MAP()

class SWidthDlg : public CDialog        //與IDD_SWidthDlg對話盒對應之類別
{
private:
        int width;        //筆寬
        CEdit * wEdit;        //編輯控制項物件
public:
        //建構子
        SWidthDlg(CWnd *parent) : CDialog(IDD_SWidthDlg, parent)
                        //將IDD_SWidthDlg對話盒與SWidthDlg類別連結
        { width = 2; }
        //SWidthDlg::Getwidth 傳出使用者設定之欄寬
        int GetWidth() { return width;}
        //SWidthDlg::OnInitDialog IDD_SWidthDlg對話盒起始設定
        BOOL OnInitDialog()
        {
                char strWidth[5];
        
                CDialog::OnInitDialog();        //呼叫CDialog::OnInitDialog

                wEdit = (CEdit *)GetDlgItem(IDC_Width);
                        //將IDD_SWidthDlg對話盒的IDC_Width編輯控制項與wEdit物件連結

                MyView *view = (MyView *)m_pParentWnd;
                //取得目前的View物件

                wsprintf(strWidth, "%d", view->GetWidth());
                        //將目前View物件設定的筆寬輸出strWidth字串中

                wEdit->ReplaceSel(strWidth);
                //將View物件目前設定的筆寬顯示在IDC_Width編輯控制項中
        
                return TRUE;
        }
        //SWidthDlg::OnOK
        void OnOK()
        {
                CString strWidth;
                wEdit->GetWindowText(strWidth);        //取得使用者設定的筆寬

                try{
                        width = StrToInt(strWidth);        //將目前的筆寬由文字轉換為數字

                        if (width > 20)        //如果筆寬大於20則都出例外
                                throw ("Width is greater than 20.");        
                        
                        CDialog::OnOK();        //呼叫CDialog::OnOK
                }
                catch(const char * str)        //如果產生字串例外,則蹦現顯示錯誤訊息的訊息方塊
                { MessageBox(str,"Input Error", MB_OK);        }                                
        }
        //SWidthDlg::StrToInt
        int StrToInt(CString & str)
        {
                int len = str.GetLength();        //先取得字串長度,做為數字位數
                int res = 0;        //轉換結果

                for (int i = 0; i < len; ++i)
                {
                        switch(str[i])        //將字串的每個文字至換成數字
                        {
                        case '0':
                                break;
                        case '1':        
                                res += (int) pow(10, (len-i-1)) * 1;
                                                //將取得的數字,乘以其位數
                                break;
                        case '2':
                                res += (int) pow(10, (len-i-1)) * 2;
                                break;
                        case '3':
                                res += (int) pow(10, (len-i-1)) * 3;
                                break;
                        case '4':
                                res += (int) pow(10, (len-i-1)) * 4;
                                break;
                        case '5':
                                res += (int) pow(10, (len-i-1)) * 5;
                                break;        
                        case '6':
                                res += (int) pow(10, (len-i-1)) * 6;
                                break;
                        case '7':
                                res += (int) pow(10, (len-i-1)) * 7;
                                break;
                        case '8':
                                res += (int) pow(10, (len-i-1)) * 8;
                                break;
                        case '9':
                                res += (int) pow(10, (len-i-1)) * 9;
                                break;
                        case'-':        //如果讀取到負號,則丟例外
                                throw ("Don't input a nagtive number.");
                                break;
                        }
                }
                return res;        //傳回轉換結果
        }
};
//MyView::OnSetWidth
afx_msg void MyView::OnSetWidth()
{
        SWidthDlg dlg(this);
                //建立設定筆寬的對話盒物件,並傳入父視窗物件
        char str[10];
        
        if (dlg.DoModal() == IDOK)        //使用者若按下確定按鈕則傳出IDOK
        {
                width = dlg.GetWidth();        //取得使用者設定的筆寬
                wsprintf(str, "Width : %d ", width);        //將筆寬輸出到str字串
                ((MyFrame *)GetParentFrame())->statusbar.SetPaneText(3,str);
                        //設定狀態列的IDS_Width欄位
        }
}

class MyApp : public CWinApp        //應用程式物件
{
public:
        BOOL InitInstance()
        {
                CDocument *aDOC;
                CSingleDocTemplate *aDocTemplate;
                aDocTemplate = new CSingleDocTemplate(        //建立單一文件框架
                                IDR_MyFrame,
                                RUNTIME_CLASS(MyDocument),
                                RUNTIME_CLASS(MyFrame),
                                RUNTIME_CLASS(MyView));
                AddDocTemplate(aDocTemplate);
                                //將單一文件框架加入應用程式物件
                aDOC = aDocTemplate->CreateNewDocument();
                                //建立Document物件
                CFrameWnd *Frame = aDocTemplate->CreateNewFrame(aDOC, NULL);
                                //建立視窗框架物件
                m_pMainWnd = Frame;        //建立應用程式物件使用之視窗框架                                
                aDocTemplate->InitialUpdateFrame(Frame, aDOC);
                                //起始化View物件
                Frame->ShowWindow(SW_SHOW);
                                //顯示視窗框架
                return true;
        }

        DECLARE_MESSAGE_MAP()
} a_app;        //應用程式物件

BEGIN_MESSAGE_MAP(MyApp, CWinApp)
        ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)        //開啟新檔
        ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)        //開啟舊檔
END_MESSAGE_MAP()
[ 本帖最後由 philxyz0316 於 2006-8-27 13:04 編輯 ]

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。