有没有办法在不使用(MFC)动态对象创建的情况下在CSplitterWnd中创建视图?

时间:2009-09-30 19:37:00

标签: c++ mfc csplitterwnd

我以前在MFC应用程序中使用CSplitterWnd,使用它的CreateView函数。一切都工作正常,但现在我想将一个参数传递给我的视图的构造函数,所以我不能使用MFC动态对象创建(DECLARE_DYNCREATEIMPLEMENT_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回答后添加更多详细信息:

你的权利,初始化方法可以工作,但这迫使我记得调用初始化方法,但就像你指出我可能不会多次创建这些视图,所以应该没问题。我可能想要的另一件事是自己管理视图的生命周期,所以再次使用CreateView是不可能的。

由于

4 个答案:

答案 0 :(得分: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);

这对我来说似乎并不那么糟糕。也许您正试图避免某种特定情况?

答案 1 :(得分:0)

我认为没有办法将视图指针交给拆分器窗口。相反,您需要从CWplitterWnd派生一个类并覆盖CreateView虚拟方法。

默认方法与pClass->CreateObject()类似,但您的版本可以根据需要创建对象。但是,您将需要处理该方法处理的任何其他详细信息,因为您将无法调用默认实现。

答案 2 :(得分:0)

我没有尝试过,但我认为这样的事情应该有效:

CMyView *pView = new CMyView( PARAM );

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

显然你仍然需要在你的视图中使用DECLARE_DYNCREATE(CMyView),你需要提供一个默认的构造函数,但是你可以使用参数化的构造函数。

答案 3 :(得分:0)

在检查了Javier De Pedro的答案之后我虽然可以覆盖创建功能所以我做了(半伪代码):

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这个:

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指针保留在其他地方,只要我在文档退出之前删除它。

感谢您的帮助。