1896


MFCタグが作れなかったのでC++タグで失礼いたします。(2014/12/17 16時27分提案→MFCタグ追加済)

今MFCを学んでおります。

現在MFCのSDIで図形作成プログラムを作っていて、Viewにすべてのデータを持たせてDocに保存していましたが、データが増えてきたので別クラスにてデータを管理しようとしています。

保存するデータとして  
・図形が何個あるのか  
・図形の座標  
を考えており、数を制限したくないので可変にするためにCArrayで管理しようとしています。  
CArrayを独自クラスで利用する際の書き方がよくわかりませんので下記コードだとどうなるか具体的に教えていただければ幸いです。

CPaintData.h

[code]

    class CPaintData : public CObject
    {
    public:
        CPaintData();
        virtual ~CPaintData();
    
    private:
        int m_nFigureNumber;        // 図形の数
        double m_dCoodinateX;       // 各種X座標
        double m_dCoodinateY;       // 各種Y座標
    
    public:
        void setFigureNumber(int Number);       //現在の図形の数
        double getFigureNumber(void);
        void setCoodinateX(CPoint point);       //現在のX座標の取得
        double getCoodinateX(void);
        void setCoodinateY(CPoint point);       //現在のY座標の取得
        double getCoodinateY(void);
    };
    
[/code]

CPaintData.cpp

[code]

    CPaintData::CPaintData()
    : m_dCoodinateX(0)
    {
    }
    
    CPaintData::~CPaintData()
    {
    }
    
    void CPaintData::setCoodinateX(CPoint point)        // 現在のX座標の取得
    {
        m_dCoodinateX = point.x;
    }
    
    double CPaintData::getCoodinateX(void)
    {
        return m_dCoodinateX;
    }
    
[/code]

(↑同じような形なので図形の数とY座標は省略)

CPaintView.h

[code]

    #include "atltypes.h"
    #include "PaintData.h"
    
    enum{   
            DRAW_LINE = 1,
            DRAW_TRIANGLE,
            DRAW_SQUARE,
            DRAW_CIRCLE_CONTINUE,
            DRAW_POLYLINE_CONTINUE
    };
    
    class CScrollViewPaintView : public CView
    {
    public:
        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
        CArray<CPaintData, CPaintData&> m_arDataArray;
    
    };
    
[/code]

(↑必要そうなところだけ抜粋)

CPaintView.cpp

[code]

    #include "stdafx.h"
    #include "Paint.h"
    
    #include "PaintDoc.h"
    #include "PaintView.h"
    
    (省略)
    
    void CScrollViewPaintView::OnLButtonDown(UINT nFlags, CPoint point) //左クリック時の処理
    {
        if(m_nType == DRAW_CIRCLE){     //メニューで円を選んだとき
            CPaintDoc* pDoc = GetDocument();    //Docを使うために必要
            ASSERT_VALID(pDoc);
    
            CPaintData PaintData;           //このあたりからよくわからない
    
            PaintData.setCoodinateX(point.x);   //setできてる模様？
            PaintData.setCoodinateY(point.y);   //setできてる模様？
            PaintData.getCoodinateX();      //getできるけどVSで見るとm_arDataArrayに入っていない模様でどこからとってるのか謎
            PaintData.getCoodinateY();      //getできてない？
    
            //ここでクリックが2回目なら、1回目を中心、2回目を外周のどこかとする円を書く処理にとばす
    
            //図形の個数をプラス1する
    
            pDoc->SetModifiedFlag();        //Docに保存
        }
    
    }
    
[/code]

CPaintDoc(今回は関係ないはずなので省略)

開発環境はwin7 64bit VS2010です。  
よろしくおねがいいたします。


CC BY-SA 3.0
2014-12-17T06:46:33.940
1881
2015-01-17T16:53:39.080
2014-12-17T07:34:11.227
4525
4525
question
c++ mfc
MFCのCArrayで独自クラスを利用する際の書き方


期待される解答とはちょっと違うかもしれませんが、現状であれば、MFC独自の CArray を使うよりは、標準ライブラリの std::vector
を使うことを強くお薦めします。 その方が、情報も多いですし、普遍性が高いです。

具体的な使い方ですが、複数の座標値を管理したいのであれば、

[code]

    struct Pos {
       double m_x;
       double m_y;
    };
    
[/code]

のような構造体を作り、CPaintData のメンバ変数として、その動的配列を保持すればいいと思います。

[code]

    class CPaintData {
    private:
      std::vector<Pos> m_posList;  //  座標データたち
    };
    
[/code]

std::vector の使い方そのものは、手前味噌ですが [C++ 動的配列クラス std::vector
入門](http://vivi.dyndns.org/tech/cpp/vector.html) 等を参照してください。


CC BY-SA 3.0
2014-12-17T07:42:56.960
1891
2014-12-17T22:27:15.190
2014-12-17T22:27:15.190
3431
3431
1881
answer


もとのソースと関係なく、概念だけ書くと、こんな感じでしょうか。

その方がいろいろと都合が良いので、CArrayは図形のポインタを保持するものとします。

[code]

    // CArrayでクラスのポインタを保持するテンプレート
    
    template< typename T >
    
    class T_PTR_ARY : public CArray< T*>{
    
    public:
    
        T_PTR_ARY(){}
    
        virtual ~T_PTR_ARY(){ Destroy();}
    
        void Destroy(){
    
        ・・・・// 全てのT*をdelete してから
    
            RemoveAll(); // 全て廃棄
    
        }
    
    };
    
    
    class FIG {・・・・};// 図形の基本クラス
    
    typedef T_PTR_ARY< FIG>  FIG_ARY;// 図形のポインタの配列クラス
    
    class FIG_RECT:public FIG{}; // 図形の派生クラス　矩形
    
    // 実際に使うときは
    
    FIG_ARY fig_ary;
    
    fig_ary.Add( new FIG_RECT); // 矩形を追加
    
[/code]


CC BY-SA 3.0
2014-12-17T07:45:12.717
1892
2014-12-17T16:21:54.947
2014-12-17T16:21:54.947
33
3793
1881
answer


こんな感じですかね？

[code]

    Carray <CPaintData , CPaintData &> arPaintData;
    CPaintData PaintData;
    Cpoint cpWk;
    cpWk.x = 123;
    cpWk.y = 456;
    PaintData.setCoodinateX(cpWk);
    PaintData.setCoodinateY(cpWk);
    arPaintData.Add(PaintData);
    
[/code]


CC BY-SA 3.0
2014-12-17T08:27:49.583
1895
2014-12-17T08:40:53.520
2014-12-17T08:40:53.520
4578
4578
1881
answer


Documentのメンバーに以下を登録。

[code]

    　CArray <CPaintData *, CPaintData *> m_aryPaint;
    
[/code]

追加時のコードは以下。

[code]

      CPaintData *pPaint = new CPaintData();
      pPaint->データ設定
    　GetDocument()->m_aryPaint.Add(pPaint);
    
[/code]

読み出しと描画は以下。

[code]

      for (int i = 0; i < GetDocument()->m_aryPaint.GetCount(); i++)
      {
         CPaintData *pPaint = GetDocument()->m_aryPaint.GetAt(i);
         描画処理
      }
    
[/code]

こんな感じでしょうか。  
削除は以下。

[code]

      for (int i = 0; i < GetDocument()->m_aryPaint.GetCount(); i++)
      {
         delete GetDocument()->m_aryPaint.GetAt(i);
      }
    　 GetDocument()->m_aryPaint.RemoveAll();
    
[/code]


CC BY-SA 3.0
2014-12-17T08:28:37.070
1896
2014-12-17T15:59:13.203
2014-12-17T15:59:13.203
33
4580
1881
answer


CObjectから派生させてる事から察しますが…  
MFCのシリアライズ機能を使う予定であればCArrayを使う方が良い(必須ではない)ですよ。


CC BY-SA 3.0
2015-01-17T16:53:39.080
4759
2015-01-17T16:53:39.080
7504
1881
answer