2009-09-30 39 views
2

我之前在MFC應用程序中使用CSplitterWnd,使用它的CreateView函數。一切工作正常,但現在我想傳遞一個參數給我的視圖的構造函數,所以我不能使用MFC動態對象創建(DECLARE_DYNCREATEIMPLEMENT_DYNCREATE),因爲它們需要一個空的構造函數。有沒有辦法在不使用(MFC)動態對象創建的情況下在CSplitterWnd中創建視圖?

在互聯網上搜索了一點後,我發現,看起來像這樣的爲例:

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的回答後,添加更多的細節:

你的初始化方法的工作,但這種力量我記得調用初始化方法,但像你指出我可能不會創建這些意見很多權次,所以應該沒問題。另一件我可能會喜歡的事情是自己管理視圖的生命週期,所以再次使用CreateView是不可能的。

感謝

回答

0

檢查哈維爾·德佩德羅的回答後,我雖然我可以覆蓋創建功能,所以我做(半僞代碼):

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); 
} 

現在這個工作,但有是,它會破壞我的類問題關閉和我說我可能要跟蹤存儲自己的時候,所以我重載PostNcDestroy中去做在CMyView做的,而不是調用刪除這個沒什麼:

CMyView::PostNcDestroy(){} 

現在應該防止屏幕刪除,但現在它退出,所以當崩潰我重寫了CMyFrame :: OnClos è這樣的:

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(); 
} 

現在theorically我應該能夠保持MyView的指針其他地方,只要我在文稿出口之前將其刪除。

感謝您的幫助球員。

0

我不認爲有什麼辦法剛剛到手的視圖指針拆分窗口。相反,您需要從CWplitterWnd中派生出一個類並覆蓋CreateView虛擬方法。

默認的方法有類似pClass->CreateObject()的操作,但是您的版本可以根據需要創建對象。但是,您需要注意由該方法處理的任何其他細節,因爲您將無法調用默認實現。

1

當你說這會很醜並且容易出錯時,你的意思是說你的視圖的創建在很多地方會發生多次?如果是這樣,那麼我會部分同意你的看法。

但是,如果你只是有兩個的情況,其中您應用程序啓動時創建視圖,那麼「醜」和「容易出錯」歸結爲兩個額外的線路:

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); 

似乎並沒有那麼糟糕對我來說。也許你正在試圖避免的具體情況?

+0

增加了一些信息,但你有一個好點我不認爲我會創造這些意見很多時間。謝謝。 – n1ckp 2009-09-30 20:56:50

+0

因爲投票給你,雖然它不能完全解決我的需求,但在其他情況下,這可能是最好的答案。創建視圖的好處只有一次。我沒有經過這件事。 – n1ckp 2009-10-04 18:20:38

+0

很高興爲您提供幫助,感謝您的支持。 – el2iot2 2009-10-05 14:26:58

0

我還沒有嘗試過自己,但我覺得這樣的事情應該工作:

CMyView *pView = new CMyView(PARAM); 

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

很明顯,你還需要在您的視圖(CMyView)使用DECLARE_DYNCREATE,你需要提供一個默認的構造函數,但你將能夠使用參數化的構造函數。

+0

我還沒試過,但我不認爲它會起作用。 CreateView函數調用pClass-> CreateObject(),它將從RuntimeClass結構中調用m_pfnCreateObject,從而創建一個新對象。雖然我可能會創建一個新的函數來返回新創建的CMyView *,而不是創建一個新的函數並覆蓋運行時類m_pfnCreateObject參數。我認爲這應該工作。我會嘗試它,併發布答案,如果它的工作。謝謝。 – n1ckp 2009-09-30 21:26:26

+0

因爲投票你,雖然你的答案是不正確的,你讓我在正確的道路上解決我的問題,謝謝。 – n1ckp 2009-10-04 18:14:08

+0

這將創建兩個'CMyView'對象;我之前嘗試過這樣的事情。 – sergiol 2017-11-29 16:35:17

相關問題