View和Control的区别(如何在对话框上使用CView类)[1]

[入库:2006年2月23日] [更新:2007年3月24日]

本文简介:

View和Control的区别(如何在对话框上使用CView类)

  CView继承类,和其他窗口类的区别,很重要的就是对CDocument类和CFrameWnd类的操作,而其中,涉及CDocument类的操作,都进行了有效性判断(m_pDocument != NULL),CView类初始化的时候,m_pDocument = NULL,因此并不影响CView类作为控件的使用。涉及CFrame类的操作,有这么几个地方:
  第一个地方:CView::OnDestroy()。
void CView::OnDestroy()
{
 CFrameWnd* pFrame = GetParentFrame();
 if (pFrame != NULL && pFrame->GetActiveView() == this)
  pFrame->SetActiveView(NULL);    // deactivate during death
 CWnd::OnDestroy();
}
  第二个地方:CView::OnActivateFrame()。
void CView::OnActivateFrame(UINT /*nState*/, CFrameWnd* /*pFrameWnd*/)
{
}
  这里,其实是空的,在CView继承类中,只有CFormView类继承了这个虚函数
void CFormView::OnActivateFrame(UINT nState, CFrameWnd* /*pFrameWnd*/)
{
 if (nState == WA_INACTIVE)
  SaveFocusControl();     // save focus when frame loses activation
}
  实际上都不需要真的CFrame指针,对CView类作为控件使用没有障碍。
  第三个地方:CView::OnMouseActivate()。
int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
 int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
 if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
  return nResult;   // frame does not want to activate
 CFrameWnd* pParentFrame = GetParentFrame();
 if (pParentFrame != NULL)
 {
  // eat it if this will cause activation
  ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame));
  // either re-activate the current view, or set this view to be active
  CView* pView = pParentFrame->GetActiveView();
  HWND hWndFocus = ::GetFocus();
  if (pView == this &&
   m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus))
  {
   // re-activate this view
   OnActivateView(TRUE, this, this);
  }
  else
  {
   // activate this view
   pParentFrame->SetActiveView(this);
  }
 }
 return nResult;
}
  另外,在CView::PostNcDestroy(),实现了CView类的自我销毁,这是因为CView类是可以动态生成的(DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)。
// self destruction
void CView::PostNcDestroy()
{
 // default for views is to allocate them on the heap
 //  the default post-cleanup is to 'delete this'.
 //  never explicitly call 'delete' on a view
 delete this;
 
  基本上,修改了CView继承类的这几个地方,直接返回不要调用基类相应的成员函数,就可以在对话框上使用。
  下面举例,用向导生成对话框应用程序,对话框类为CMyDigalog。
  从CHTMLView类继承一个CHTMLCtrl类,建立相应的消息处理函数并修改以下几个地方:
// CHTMLCtrl 消息处理程序
int CHTMLCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
 //return CHtmlView::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
void CHTMLCtrl::OnDestroy()
{
 //CHtmlView::OnDestroy();
 // TODO: 在此处添加消息处理程序代码
 CWnd::OnDestroy();
}
void CHTMLCtrl::PostNcDestroy()
{
 // TODO: 在此添加专用代码和/或调用基类
 //CHtmlView::PostNcDestroy();
}
void CHTMLCtrl::OnActivateFrame(UINT nState, CFrameWnd* pDeactivateFrame)
{
 // TODO: 在此添加专用代码和/或调用基类
 //CHtmlView::OnActivateFrame(nState, pDeactivateFrame);
}
  增加一个成员函数CreateFromCtrl:
public:
 BOOL CreateFromCtrl(UINT nID, CWnd* pParent);
  这个函数通过对话框上的控件创建一个CHTMLCtrl控件,目的是在对话框设计的时候便于布局:

BOOL CHTMLCtrl::CreateFromCtrl(UINT nID, CWnd* pParent)
{
 if (!pParent || !pParent->GetSafeHwnd())
  return FALSE;
 CWnd *pCtrl = pParent->GetDlgItem(nID);
 if (!pCtrl)
  return FALSE;
 CRect rcCtrl;
 pCtrl->GetWindowRect(rcCtrl);
 pParent->ScreenToClient(rcCtrl);
 UINT style = ::GetWindowLong(pCtrl->GetSafeHwnd(), GWL_STYLE);
 pCtrl->DestroyWindow();

 return Create(NULL, NULL, style | WS_CHILD | WS_VISIBLE, rcCtrl, pParent, nID, NULL);

}

  还应注意,默认的从CView继承的类,其构造函数和析构函数是protected的,需要修改成public。

本文关键:View和Control的区别(如何在对话框上使用CView类)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top