绘图视图对话框中具有什么功能,根据视图创建视图的语句

  绘图视图对话框中具有什么功能,根据视图创建视图的语句

  作者:朱

  资料来源:http://blog..net/clever101

  本文来自《在对话框上创建视图的方法总结》。有网友朋友发邮件反映在对话框上可以成功创建视图,但是用鼠标点击视图时会出现Assert错误,说ViewCore.cpp 252行有错误。具体是在CView类的onmouseActive函数中断言(pparentframe==pdesktownd pdesktownd-is child(pparentframe)),错误!

  当我下班回家后,我决定亲自尝试一下。我在我的对话框程序中添加了各种鼠标消息,包括WM_LBUTTONDOWN、WM_MOUSEMOVE和WM_LBUTTONUP,但是都没有出错。我一时蒙了,只好在论坛上发帖求助,但是有一段时间,没有多少人响应。我只好直接在谷歌上搜索assert(pparentframe==pdesktownd pdesktownd-is child(pparentframe))。终于找到一篇相关文章《如何在没有文档的情况下使用CView及其派生类》。看完之后,我就明白为什么会出问题了。首先我们明确断言错误发生在CView:OnMouseActivate函数上,那么我们来看看MSDN对OnMouseActivate函数的解释:

  当光标在非活动窗口中并且用户按下鼠标按钮时,框架调用这个成员函数。

  当光标在非活动窗口中并且用户按下鼠标时,框架将调用此消息。然后我们来看CView:OnMouseActivate函数的源代码:

  让我们集中分析代码:

  在对话框程序上,pdesktownd是对话框指针,view类的父窗口也是对话框指针,所以语句assert(pparentframe==pdesktownd pdesktownd-is child(pparentframe))不会出错。因为CView:GetParentFrame()回到它的祖先窗口,直到找到FrameWnd类型的窗口,并返回这个窗口对象的指针(如果没有,则返回NULL),这个指针要么是NULL,要么是对话框程序中的对话框指针;但是如果是单文档程序,情况就不一样了。CView:GetParentFrame()必须是返回单文档程序的框架指针,而PDESTOWND指针是对话框指针。它们不相等,所以我们看看PDESTOWND-ISCHILD (pparentFrame)是否为真。显然,框架窗口不可能是对话框窗口的父窗口。

  那么如何解决这个问题呢?在线实现的一种方法是在对话框的视图类中嵌入一个框架窗口,这样断言PDESKTOWND-is child(PPARENTFRAME)为真。具体来说,是这样做的:

  在对话框类上定义一个框架类指针:

  然后在dialog类的构造函数上将帧指针初始化为NULL:

  这样你点视图就不会出错了。也许你会怀疑m_pFrame=new CFrameWnd()并且没有对应的delete语句。这样会导致内存泄露吗?但是,经过我的测试,没有出现内存泄漏。找不到具体原因。可能DestroyWindow函数删除了自己的内存,MFC的内部机制有时候真的很诡异。

  说实话,我觉得这种做法有点繁琐。其实我们可以换个思路。既然是在CView:OnMouseActivate函数的断言上出错,那就不能重写WM_MOUSEACTIVE消息的响应函数吗?让我们试一试。

  我仍然使用我之前的两种创建视图的方法,没有任何框架类。然后在你的自定义视图类上重写WM_MOUSEACTIVATE的响应函数。具体代码如下:

  因此,这个方法是完全可行的。

  后来我检讨自己的思维,我发现我最初的思维是完全错误的。我觉得既然assert(pparentframe==pdesktownd pdesktownd-is child(pparentframe))错了,我就应该先分析一下为什么这个断言是错的,而不是忙着搜索资料。这个道理有点像前天在CCTV 6上看到的《危机时刻》电视剧的情节:一车雷管翻车,排爆大队副大队长忙着怎么封锁铁路,疏散村民,而更高级的大队长先分析出翻车的雷管是火雷管,然后对症下药让消防车把雷管弄湿,一举消除了危机。

  参考资料:

  如何在没有文档的情况下使用CView及其派生类

绘图视图对话框中具有什么功能,根据视图创建视图的语句