概述 从前文可知,在MFC中,文档是真正的数据载体,
视图是文档的显示界面,对应同一个文档,可能存在多个视图界面,我们需要另外一种东东来将这些界面管理起来,这个东东就是框架。MFC创造框架类的初衷在于:把界面管理工作独立出来!框架窗口为应用程序的用户界面提供结构框架,它是应用程序的主窗口,负责管理其包容的窗口。一个应用程序启动时会创建一个最顶层的框架窗口
从前文可知,在MFC中,文档是真正的数据载体,视图是文档的显示界面,对应同一个文档,可能存在多个视图界面,我们需要另外一种东东来将这些界面管理起来,这个东东就是框架。
MFC创造框架类的初衷在于:把界面管理工作独立出来!框架窗口为应用程序的用户界面提供结构框架,它是应用程序的主窗口,负责管理其包容的窗口。一个应用程序启动时会创建一个最顶层的框架窗口。
MFC提供二种类型的框架窗口:单文档窗口SDI和多文档窗口MDI(你可以认为对话框是另一种框架窗口)。单文档窗口一次只能打开一个文档框架窗口,而多文档窗口应用程序中可以打开多个文档框架窗口,即子窗口(Child Window)。这些子窗口中的文档可以为同种类型,也可以为不同类型。
在Visual C++ AppWizard的第一个对话框中,会让用户选择应用程序是基于单文档、多文档还是基于对话框的,如图5.1。
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)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)