深入浅出MFC文档视图架构之框架(1)

深入浅出MFC文档视图架构之框架(1),第1张

概述  从前文可知,在MFC中,文档是真正的数据载体,视图是文档的显示界面,对应同一个文档,可能存在多个视图界面,我们需要另外一种东东来将这些界面管理起来,这个东东就是框架。MFC创造框架类的初衷在于:把界面管理工作独立出来!框架窗口为应用程序的用户界面提供结构框架,它是应用程序的主窗口,负责管理其包容的窗口。一个应用程序启动时会创建一个最顶层的框架窗口  
从前文可知,在MFC中,文档是真正的数据载体,视图是文档的显示界面,对应同一个文档,可能存在多个视图界面,我们需要另外一种东东来将这些界面管理起来,这个东东就是框架。

  MFC创造框架类的初衷在于:把界面管理工作独立出来!框架窗口为应用程序的用户界面提供结构框架,它是应用程序的主窗口,负责管理其包容的窗口。一个应用程序启动时会创建一个最顶层的框架窗口。

  MFC提供二种类型的框架窗口:单文档窗口SDI和多文档窗口MDI(你可以认为对话框是另一种框架窗口)。单文档窗口一次只能打开一个文档框架窗口,而多文档窗口应用程序中可以打开多个文档框架窗口,即子窗口(Child Window)。这些子窗口中的文档可以为同种类型,也可以为不同类型。

  在Visual C++ AppWizard的第一个对话框中,会让用户选择应用程序是基于单文档、多文档还是基于对话框的,如图5.1。


图5.1 在AppWizard中选择框架窗口

  MFC提供了三个类CFrameWnd、CMDiframeWnd、CMDIChilDWnd用于支持单文档窗口和多文档窗口,这些类的层次结构如图5.2。


图5.2 CFrameWnd、CMDiframeWnd、CMDIChilDWnd类的层次

  (1)CFrameWnd类用于SDI应用程序的框架窗口,SDI框架窗口既是应用程序的主框架窗口,也是当前文档对应的视图的边框;CFrameWnd类也作为CMDiframeWnd和CMDIChilDWnd类的父类,而在基于SDI的应用程序中,AppWizard会自动为我们添加一个继承自CFrameWnd类的CMainFrame类。

  CFrameWnd类中重要的函数有Create(用于创建窗口)、LoadFrame(用于从资源文件中创建窗口)、PreCreateWindow(用于注册窗口类)等。Create函数第一个参数为窗口注册类名,第二个参数为窗口标题,其余几个参数指定了窗口的风格、大小、父窗口、菜单名等,其源代码如下:

BOol CFrameWnd::Create(LPCTSTR lpszClassname,LPCTSTR lpszWindowname,DWORD DWStyle,const RECT &rect,CWnd *pParentWnd,LPCTSTR lpszMenuname,DWORD DWExStyle,CCreateContext *pContext)
{
 HMENU hMenu = NulL;
 if (lpszMenuname != NulL)
 {
  // load in a menu that will get destroyed when window gets destroyed
  HINSTANCE hInst = AfxFindResourceHandle(lpszMenuname,RT_MENU);
  if ((hMenu = ::LoadMenu(hInst,lpszMenuname)) == NulL)
  {
   TRACE0("Warning: Failed to load menu for CFrameWnd./n");
   PostNcDestroy(); // perhaps delete the C++ object
   return FALSE;
  }
 }
 m_strTitle = lpszWindowname; // save Title for later

 if (!CreateEx(DWExStyle,lpszClassname,lpszWindowname,DWStyle,rect.left,
rect.top,rect.right - rect.left,rect.bottom - rect.top,pParentWnd
->GetSafeHwnd(),hMenu,(LPVOID)pContext))
 {
  TRACE0("Warning: Failed to create CFrameWnd./n");
  if (hMenu != NulL)
   DestroyMenu(hMenu);
  return FALSE;
 }
 return TRUE;
}

  LoadFrame函数用于从资源文件中创建窗口,我们通常只需要给其指定一个参数,LoadFrame使用该参数从资源中获取主边框窗口的标题、图标、菜单、加速键等,其源代码为:

BOol CFrameWnd::LoadFrame(UINT nIDResource,DWORD DWDefaultStyle,CWnd
*pParentWnd,CCreateContext *pContext)
{
 // only do this once
 ASSERT_VALID_IDR(nIDResource);
 ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

 m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)

 CString strFullString;
 if (strFullString.LoadString(nIDResource))
  AfxExtractSubString(m_strTitle,strFullString,0);
  // first sub-string

 VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

 // attempt to create the window
 LPCTSTR lpszClass = GetIconWndClass(DWDefaultStyle,nIDResource);
 LPCTSTR lpszTitle = m_strTitle;
 if (!Create(lpszClass,lpszTitle,DWDefaultStyle,rectDefault,pParentWnd,
MAKEINTRESOURCE(nIDResource),0L,pContext))
 {
  return FALSE; // will self destruct on failure normally
 }

 // save the default menu handle
 ASSERT(m_hWnd != NulL);
 m_hMenuDefault = ::GetMenu(m_hWnd);

 // load accelerator resource
 LoadAcceltable(MAKEINTRESOURCE(nIDResource));

 if (pContext == NulL)
  // send initial update
  SendMessagetoDescendants(WM_INITIALUPDATE,TRUE,TRUE);

 return TRUE;
}

  在SDI程序中,如果需要修改窗口的默认风格,程序员需要修改CMainFrame类的PreCreateWindow函数,因为AppWizard给我们生成的CMainFrame::PreCreateWindow仅对其基类的PreCreateWindow函数进行调用,CFrameWnd::PreCreateWindow的源代码如下:

BOol CFrameWnd::PreCreateWindow(CREATESTRUCT &cs)
{
 if (cs.lpszClass == NulL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  cs.lpszClass = _afxWndFrameOrVIEw; // color_WINDOW background
 }

 if ((cs.style &FWS_ADDTOTitle) && afxData.bWin4)cs.style |= FWS_PREFIXTitle;

 if (afxData.bWin4)
  cs.DWExStyle |= WS_EX_CLIENTEDGE;
 return TRUE;
}
总结

以上是内存溢出为你收集整理的深入浅出MFC文档/视图架构之框架(1)全部内容,希望文章能够帮你解决深入浅出MFC文档/视图架构之框架(1)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1156367.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存