有没有办法在不使用(MFC)动态对象创建的情况下在 CSplitterWnd 中创建视图?
Posted
技术标签:
【中文标题】有没有办法在不使用(MFC)动态对象创建的情况下在 CSplitterWnd 中创建视图?【英文标题】:Is there a way to create a view in a CSplitterWnd without using (MFC) dynamic object creation? 【发布时间】:2009-09-30 19:36:59 【问题描述】:我以前在 MFC 应用程序中使用 CSplitterWnd
,使用它的 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的回答之后添加更多细节:
您认为初始化方法会起作用,但这迫使我记住调用该初始化方法,但就像您指出的那样,我可能不会多次创建这些视图,所以应该没问题。我可能想要的另一件事是自己管理视图的生命周期,所以再次使用 CreateView 是不可能的。
谢谢
【问题讨论】:
【参考方案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);
这对我来说似乎并没有那么糟糕。也许您正试图避免某种特定情况?
【讨论】:
添加了更多信息,但您的观点很好,我认为我不会多次创建这些视图。谢谢。 投票支持你,虽然它并没有完全解决我的需求,但在其他情况下它可能是最好的答案。只创建一次视图的好处。我没想到。【参考方案2】:在检查了 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 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 指针保留在别处,只要我在文档退出之前删除它。
感谢你们的帮助。
【讨论】:
【参考方案3】:我认为没有任何方法可以将视图指针传递给拆分器窗口。相反,您需要从CWplitterWnd
派生一个类并覆盖CreateView
虚拟方法。
默认方法类似于pClass->CreateObject()
,但您的版本可以根据需要创建对象。但是,您需要注意该方法处理的任何其他细节,因为您将无法调用默认实现。
【讨论】:
【参考方案4】:我自己没有尝试过,但我认为这样的方法应该可行:
CMyView *pView = new CMyView( PARAM );
splitter.CreateView( 0,
0,
pView->GetRuntimeClass(),
size,
0);
显然,您仍然需要在视图 (CMyView) 中使用 DECLARE_DYNCREATE,并且您需要提供默认构造函数,但您将能够使用参数化构造函数。
【讨论】:
我还没有尝试过,但我认为它不会起作用。 CreateView 函数调用 pClass->CreateObject(),它将从 RuntimeClass 结构调用 m_pfnCreateObject,创建一个新对象。虽然我可能会创建一个新函数来返回新创建的 CMyView* 而不是创建一个新函数并覆盖运行时类 m_pfnCreateObject 参数。我认为这应该有效。如果可行,我会尝试并发布答案。谢谢。 投票支持你,虽然你的答案不正确,但你让我走上了解决问题的正确道路,谢谢。 这将创建两个CMyView
对象;我以前尝试过这样的事情。以上是关于有没有办法在不使用(MFC)动态对象创建的情况下在 CSplitterWnd 中创建视图?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在不使用 ImageMagick 或其他第三方软件的情况下在 R 中制作 GIF?
有没有办法在不刷新页面的情况下在电子商务网站中创建“添加到购物车”?
有没有办法在不使用画布的情况下在 JavaScript 中合并图像?
有没有办法在不使用 AVFoundation 框架的情况下在 iOS 中录制音频?