深入浅出MFC文档/视图架构之框架(转)
来源:互联网 发布:知乎如何幼儿园合作 编辑:程序博客网 时间:2024/06/06 01:34
从前文可知,在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函数第一个参数为窗口注册类名,第二个参数为窗口标题,其余几个参数指定了窗口的风格、大小、父窗口、菜单名等,其源代码如下:
{
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使用该参数从资源中获取主边框窗口的标题、图标、菜单、加速键等,其源代码为:
*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, 0, 0, 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;
}
2006-03-21 08:37作者:宋宝华出处:天极开发责任编辑:方舟
http://dev.yesky.com/301/2340801.shtml
- 深入浅出MFC文档/视图架构之框架(转)
- 深入浅出MFC文档/视图架构之框架
- 深入浅出MFC文档/视图架构之框架
- 深入浅出MFC文档/视图架构之视图(转)
- 深入浅出MFC文档/视图架构之文档(转)
- 深入浅出MFC文档/视图架构之基本概念收藏(转)
- 深入浅出MFC文档/视图架构之框架(1)
- 深入浅出MFC文档/视图架构之框架(2)
- 深入浅出MFC文档/视图架构之视图
- 深入浅出MFC文档/视图架构之视图
- 深入浅出MFC文档/视图架构之视图
- 深入浅出MFC文档/视图架构之文档
- 深入浅出MFC文档/视图架构之文档
- 深入浅出MFC文档/视图架构之基本概念
- 深入浅出MFC文档/视图架构之相互关系
- 深入浅出MFC文档/视图架构之基本概念
- 深入浅出MFC文档/视图架构之相互关系
- 深入浅出MFC文档/视图架构之相互关系
- debian 源 apt-spy (转)
- google知道百度知道知道,而百度不知道百度知道知道
- 我对开源社区的体会
- 兼职做网站
- iphone设置非阻塞模式socket两种方法
- 深入浅出MFC文档/视图架构之框架(转)
- tomcat6.0中配置JNDI的DBCP连接及JNDI在程序中调用
- 怎么成为一个优秀的程序员?
- 网页设计中的页面尺寸标准
- 变量命名中的[匈牙利命名法][骆驼命名法][帕斯卡(pascal)命名法]
- OWASP-CM-002
- 详解如何注册PayPal
- [转]java 安装配置
- 华亚HTV903升级程序使用说明