2

我以前CSplitterWnd在 MFC 应用程序中使用 a ,使用它的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

4 回答 4

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

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

于 2009-09-30T20:14:48.410 回答
1

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

谢谢你们的帮助。

于 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 回答