2

私は以前CSplitterWnd、MFC アプリケーションでそのCreateView関数を使用して使用していました。すべてが正常に機能していましたが、ビューのコンストラクターにパラメーターを渡したいので、空のコンストラクターが必要なため、 MFC 動的オブジェクト作成 (DECLARE_DYNCREATEおよび) を使用できません。IMPLEMENT_DYNCREATE

インターネットで少し検索したところ、次のような例が見つかりました。

m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyView), CSize(0,0), pContext);
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyView),  CSize(0,0), pContext);
m_pView0=(CMyView *)m_wndSplitter.GetPane(0,0);
m_pView1=(CMyView *)m_wndSplitter.GetPane(0,1);

これは回避策になる可能性があります (つまり、必要なものを指定できるようにする新しい関数を作成しCMyViewます) が、これは見苦しく、エラーが発生しやすくなります。私がこれを行うことができる別の方法があるかどうか誰でも知っていますか?

編集:eeの回答の後に詳細を追加:

初期化メソッドが機能するというあなたの権利ですが、これにより、その初期化メソッドを呼び出すことを覚えておく必要がありますが、指摘したように、これらのビューを何度も作成することはおそらくないので、問題ありません。私が望むもう1つのことは、ビューの有効期間を自分で管理することです。これも、CreateViewを使用して行うことはできません。

ありがとう

4

4 に答える 4

1

見苦しくてエラーが発生しやすいと言うとき、ビューの作成が多くの場所で何度も行われるということですか? もしそうなら、私はあなたに部分的に同意します。

ただし、アプリの起動時にビューを作成するケースが 2 つだけある場合、「醜い」および「エラーが発生しやすい」は、次の 2 つの追加行に要約されます。

m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyView), CSize(0,0), pContext);
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyView),  CSize(0,0), pContext);
m_pView0=(CMyView *)m_wndSplitter.GetPane(0,0);
m_pView1=(CMyView *)m_wndSplitter.GetPane(0,1);
//additional stuff
m_pView0->Initialize(v1, v2, v3);
m_pView1->Initialize(v4, v5, v6);

それは私にはそれほど悪くはないようです。おそらく、回避しようとしている特定の状況がありますか?

于 2009-09-30T20:14:48.410 に答える
1

ハビエル・デ・ペドロの答えを確認した後、私は作成機能をオーバーライドすることができたので、私はそうしました(半疑似コード):

class ObjGetter
{
    static CObject* obj;
public:
    ObjGetter(CObject* obj_){obj = obj_;}
    static CObject* __stdcall getObj() { return obj; }
};

CObject* ObjGetter::obj = NULL;

BOOL CMyFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
//...
  myView = new CMyView(NULL);
  CRuntimeClass rt(*myView->GetRuntimeClass());
  ObjGetter objGetter(myView);
  rt.m_pfnCreateObject = &ObjGetter::getObj;

  m_wndSplitter.CreateView(0,0, &rt, CSize(0,0), pContext);
}

これで機能しますが、閉じるときにクラスが破棄されるという問題があり、自分でメモリを追跡したいので、CMyView で PostNcDestroy をオーバーロードして、delete this を呼び出す代わりに何もしません。

CMyView::PostNcDestroy(){}

これで削除されないようにする必要がありますが、終了時にクラッシュするようになったため、次のように CMyFrame::OnClose をオーバーライドしました。

void CMyFrame::OnClose()
{
   m_wndSplitter.DeleteView(0, 0);
   delete myView; myView = NULL; //seems to be needed to be deleted before 
                                 //CFrameWnd::OnClose or it crash
   CFrameWnd::OnClose();
}

理論的には、ドキュメントが終了する前に削除する限り、myView ポインターを別の場所に保持できるはずです。

助けてくれてありがとう。

于 2009-09-30T22:43:34.520 に答える
0

ビューポインタを分割ウィンドウに渡す方法はないと思います。代わりに、仮想メソッド からクラスを派生させCWplitterWndてオーバーライドする必要があります。CreateView

デフォルトのメソッドは のようなpClass->CreateObject()ことをしますが、お使いのバージョンでは必要に応じてオブジェクトを作成できます。ただし、デフォルトの実装を呼び出すことができないため、そのメソッドによって処理されるその他の詳細に注意する必要があります。

于 2009-09-30T20:13:36.097 に答える
0

私は自分で試したことはありませんが、次のようなものがうまくいくと思います:

CMyView *pView = new CMyView( PARAM );

splitter.CreateView(    0, 
                0, 
                pView->GetRuntimeClass(),
                size,  
                0);

明らかに、ビュー (CMyView) で DECLARE_DYNCREATE を使用する必要があり、デフォルトのコンストラクターを提供する必要がありますが、パラメーター化されたコンストラクターを使用できます。

于 2009-09-30T21:18:33.787 に答える