2009-09-30 37 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

相关问题