
MFC指的是Microsoft Foundation Classes ,是一种ApplicationFramework,随微软Visual C++开发工具发布。MFC以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。该类库提供一组通用的可重用的类库供开发人员使用。大部分类均从CObject 直接或间接派生,只有少部分类例外。 其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
MFC实际上是微软提供的,用于在C++环境下编写应用程序的一个框架和引擎。VC++是Windows下开发人员使用的专业C++ SDK(SDK,Standard SoftWare Develop Kit,专业软件开发平台),MFC就是挂在它之上的一个辅助软件开发包。
MFC是WinAPI与C++的结合。API,即微软提供的Windows下应用程序的编程语言接口,是一种软件编程的规范,但不是一种程序开发语言本身,可以允许用户使用各种各样的第三方的编程语言来进行对Windows下应用程序的开发,使这些被开发出来的应用程序能在Windows下运行
MFC不只是一个功能单纯的界面开发系统,它提供的类绝大部分用来进行界面开发,关联一个窗口的动作,但它提供的类中有好多类不与一个窗口关联,即类的作用不是一个界面类,不实现对一个窗口对象的控制(如创建、销毁),而是一些在Windows(用MFC编写的程序绝大部分都在Windows中运行)中实现内部处理的类,如数据库的管理类等
MFC:微软基础类(Microsoft Foundation Classes),同VCL类似,是一种应用程序框架,随微软Visual C++ 开发工具发布。目前最新版本为100(截止2011年3月),并且发布了中文版。该类库提供一组通用的可重用的类库供开发人员使用,大部分类均从CObject 直接或间接派生,只有少部分类例外。
由于它的易用性,初学者常误认为VC++开发必须使用MFC,这种想法是错误的。作为Application Framework,MFC的使用只能提高某些情况下的开发效率,只起到辅助作用,而不能替代整个Win32 程序设计。
具体内容,请参考>
一模态对话框和非模态对话框
Windows对话框分为两类:模态对话框和非模态对话框。
模态对话框是这样的对话框,当它d出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应 *** 作退出后,其他窗口才能继续与用户交互。
非模态对话框则是,它d出后,本程序其他窗口仍能响应用户输入。非模态对话框一般用来显示提示信息等。
大家对Windows系统很了解,相信这两种对话框应该都遇到过。之前的加法计算器对话框其实就是模态对话框。
二模态对话框是怎样d出的
毕竟加法计算器程序大部分都是MFC自动生成的,对话框怎么d出来的大家可能还不是很清楚。鸡啄米下面简单说说它是在哪里d出来的,再重新建一个新的对话框并d出它,这样大家实践以后就能更灵活的使用模态对话框了。
大家打开Additioncpp文件,可以看到CAdditionApp类有个InitInstance()函数,在MFC应用程序框架分析中提到过此函数,不过那是单文档应用程序App类中的,函数体不太相同,但都是进行App类实例的初始化工作。
InitInstance()函数的后半部分有一段代码就是定义对话框对象并d出对话框的,鸡啄米下面给出这段代码并加以注释:
C++代码
CAdditionDlg dlg; // 定义对话框类CAdditionDlg的对象dlg
m_pMainWnd = &dlg; // 将dlg设为主窗口
INT_PTR nResponse = dlgDoModal(); // d出对话框dlg,并将DoModal函数的返回值(退出时点击按钮的ID)赋值给nResponse
if (nResponse == IDOK) // 判断返回值是否为OK按钮(其ID为IDOK,鸡啄米已经将它删除)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL) // 判断返回值是否为Cancel按钮(其ID为IDCANCEL,鸡啄米将它的Caption改为了逗退出地)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
d出对话框比较关键的一个函数,就是对话框类的DoModal()函数。CDialog::DoModal()函数的原型为:
virtual INT_PTR DoModal();
返回值:整数值,指定了传递给CDialog::EndDialog(该函数用于关闭对话框)的nResult参数值。如果函数不能创建对话框,则返回-1;如果出现其它错误,则返回IDABORT。
调用了它对话框就会d出,返回值是退出对话框时所点的按钮的ID,比如,我们点了逗退出地按钮,那么DoModal返回值为IDCANCEL。
三添加一个新对话框并d出它
鸡啄米再为加法计算器程序添加一个对话框,以在计算之前询问用户是否确定要进行计算。大家可以完整的看下对话框的添加和d出过程。
1根据逗创建对话框模板和修改对话框属性地中所讲的方法,在Resource View中的逗Dialog地上点右键选择逗Insert Dialog地,创建一个新的对话框模板,修改其ID为IDD_TIP_DIALOG,Caption改为逗提示地,然后参考逗为对话框添加控件地中所讲,在对话框模板上添加一个静态文本框(static text),Caption改为逗您确定要进行加法计算吗看地,接下来修改OK按钮的Caption为逗确定地,Cancel按钮的Caption为逗取消地,最后调整各个控件的位置和对话框的大小。最终的对话框模板如下图:
2根据逗创建对话框类和添加控件变量地中创建对话框类的方法,在对话框模板上点右键选择逗Add Class地,d出添加类的对话框,设置逗Class name地为CTipDlg,点逗OK地。在Solution Explorer中可以看到生成了CTipDlg类的头文件TipDlgh和源文件TipDlgcpp。
3我们要在点逗计算地按钮之后d出此提示对话框,那么就要在逗计算地按钮的消息处理函数OnBnClickedAddButton()中访问提示对话框类,所以为了访问CTipDlg类,在AdditionDlgcpp中包含CTipDlg的头文件:#include "TipDlgh"。
4修改OnBnClickedAddButton()的函数体,在所有代码前,构造CTipDlg类的对象tipDlg,并通过语句tipDlgDoModal();d出对话框,最后判断DoModal()函数的返回值是IDOK还是IDCANCEL来确定是否继续进行计算。OnBnClickedAddButton()函数修改后如下:
C++代码
void CAdditionDlg::OnBnClickedAddButton()
{
// TODO: Add your control notification handler code here
INT_PTR nRes; // 用于保存DoModal函数的返回值
CTipDlg tipDlg; // 构造对话框类CTipDlg的实例
nRes = tipDlgDoModal(); // d出对话框
if (IDCANCEL == nRes) // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行
return;
// 将各控件中的数据保存到相应的变量
UpdateData(TRUE);
// 将被加数和加数的加和赋值给m_editSum
m_editSum = m_editSummand + m_editAddend;
// 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值
UpdateData(FALSE);
}
5测试。编译运行程序后,在对话框上输入被加数和加数,点逗计算地,d出提示对话框询问是否进行计算,如果选择逗确定地,则提示对话框退出,并在主对话框上显示被加数和加数的和,而如果选择逗取消地,则提示对话框也会退出,但主对话框显示的和不变,即没有进行加法计算。
WIN32 程序和MFC 程序生成的都是Windows应用程序。不同的是,Win32程序使用Windows SDK框架生成应用程序框架,默认该框架程序不使用MFC(微软基础类),生成的都是面向过程的程序框架,程序的入口时WinMain,使用这个框架需要对Windows SDK程序比较熟悉;MFC程序,可以选择单文档、多文档和对话框的应用程序框架,该框架支持MFC,生成的程序框架,都是C++面向对象的应用程序,程序的入口是CXXXApp。
MFC(Microsoft Foundation class)微软基本类(库),它是一个面向对象的应用程序架构。程序员利用它可以很方便搭建应用程序框架。
MFC结合了面向对象的编程技术和WINDOWS消息驱动的编程技术,并封装了WIN32API,其设计好处是:消除了WIN32API的复杂性,封装了WIN32API,统一了程序的概念,而且可扩展。
MFC实际上是微软提供的,用于在C++环境下编写应用程序的一个框架和引擎。VC++是Windows下开发人员使用的专业C++ SDK,MFC就是挂在它之上的一个辅助软件开发包。
扩展资料
MFC编程优势
面对底层程序,它能很轻松的与Windows API或驱动程序结合,就是在自己的代码中直接使用API函数,而API和驱动程序的资料都是以C语言为基础的,这使得VC程序员能够更轻松的使用Windows API。
这样造成了一个很有意思的现象,即入门时VC程序员要付出更多的努力来学习,但是一旦掌握后,开发其他领域的程序或使用第三方软件时,如工业控制类的程序,由于底层的程序都是用C语言编写,反倒是VC程序员能够更快的掌握该领域的编程技术。而很多其他的编程语言甚至找不到相关的资料。
这就说明VC(MFC)实际上是一种入门困难,但是扩展学习却很轻松的语言框架。
CChildFrame做为子窗口包含于MDIClient中(可以包含多个),CChildFrame里面则是真实的文档表示窗口CMDITestView了。 我们从这里开始:// CMDITestApp 初始化BOOL CMDITestApp::InitInstance() 做为CWinApp的派生类,通常需要重载InitInstance(), ExitInstance()两个函数,以完成应用的初始化和退出。我们现在关心InitInstance中关于文档模板、窗口处理的部分,而忽略掉一些CommonControl, OLE初始化部分。 整个InitInstance代码如下:BOOL CMDITestApp::InitInstance(){ InitCommonControls(); // 这里删减了大量注释和错误处理 CWinApp::InitInstance(); AfxOleInit(); AfxEnableControlContainer(); SetRegistryKey(_T(“应用程序向导生成的本地应用程序“)); LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) TRACE(“Before CMultiDocTemplate\n“); // 注册应用程序的文档模板。文档模板 // 将用作文档、框架窗口和视图之间的连接 CMultiDocTemplate pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView)); if (!pDocTemplate) return FALSE; TRACE(“Before AddDocTemplate\n“); AddDocTemplate(pDocTemplate); // 创建主 MDI 框架窗口 TRACE(“Before new CMainFrame\n“); CMainFrame pMainFrame = new CMainFrame; TRACE(“Before pMainFrame->LoadFrame\n“); if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; TRACE(“Before ParseCommandLine\n“); CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 调度在命令行中指定的命令。如果 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 TRACE(“Before ProcessShellCommand\n“); if (!ProcessShellCommand(cmdInfo)) return FALSE; TRACE(“Before pMainFrame->ShowWindow\n“); // 主窗口已初始化,因此显示它并对其进行更新 pMainFrame->ShowWindow(m_nCmdShow); TRACE(“Before pMainFrame->UpdateWindow\n“); pMainFrame->UpdateWindow(); return TRUE;} 为了研究整个创建过程,我在其中添加了一些TRACE来跟踪创建顺序。 忽略掉开始的乱七八糟的初始化,从CMultiDocTemplate开始: CMultiDocTemplate pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView)); AddDocTemplate(pDocTemplate);(作了一点点简化)这里首先创建了一个CMultiDocTemplate ——文档模板,文档模板包括的三个运行时刻类信息:Document – CMDITestDoc, FrameWnd – CChildFrame, View – CMDITestView。然后通AddDocTemplate函数将新创建的文档模板添加到模板管理器之中(我们以后再研究模板管理器)。 然后创建主框架窗口CMainFrame: CMainFrame pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; 其中,需要研究的是LoadFrame的实现,以及里面都做了些什么。我们稍后研究。 处理命令行,在这里第一个空文档被建立出来: CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 调度在命令行中指定的命令。如果用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 if (!ProcessShellCommand(cmdInfo)) // �0�8 这里创建出初始空文档 return FALSE; 我们一会会重点研究ProcessShellCommand。 最后,显示主窗口: pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); 至此,WinApp::InitInstance()完成了自己的工作。 上面遗留了三个待研究的分支,让我们现在去研究它们:1、 CDocTemplate2、 CFrameWnd::LoadFrame3、 CWnd::ProcessShellCommand 研究CDocTemplate 我们的例子中是构造了一个CMultiDocTemplate,它是从CDocTemplate派生而来,所以我们主要研究CDocTemplate。CDocTemplate的几个关键属性列表如下: CRuntimeClass m_pDocClass; // class for creating new documents CRuntimeClass m_pFrameClass; // class for creating new frames CRuntimeClass m_pViewClass; // class for creating new views 其中:m_pDocClass表示文档类类型,在此例子中就是CMDITestDocm_pFrameClass表示容纳View窗口的框架窗口类类型,此例中为CChildFramem_pViewClass表示显示文档的View视类类型,此例中为CMDITestView 我们可以这样认为,CDocTemplate用于描述Frame-View-Doc的关系。当然它还有一大堆别的属性,我们暂时先忽略。 一会还会看到CDocTemplate的创建文档、框架、视的过程,<在ProcessShellCommand中研究。 研究LoadFrame 让我们继续研究CFrameWnd::LoadFrame是怎么运作的。使用的方法是跟踪进入。。。BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd pParentWnd, CCreateContext pContext){ // 调用基类 CFrameWnd 的 LoadFrame, pContext 在创建主窗口时 = NULL // pParentWnd = NULL if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext)) return FALSE; // save menu to use when no active MDI child window is present ASSERT(m_hWnd != NULL); // 主窗口带有菜单,所以。。。 m_hMenuDefault = ::GetMenu(m_hWnd); if (m_hMenuDefault == NULL) TRACE(traceAppMsg, 0, “Warning: CMDIFrameWnd without a default menu\n“); return TRUE;}注意,我们的MDITest Application的主窗口CMainFrame是从CMDIFrameWnd派生的,所以进入到这里,参考代码中红色的注释部分。继续跟踪进入CFrameWnd::LoadFrame。 BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd pParentWnd, CCreateContext pContext){ // only do this once ASSERT_VALID_IDR(nIDResource); // nIDResource = 128, IDR_MAINFRAME ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource); m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE) CString strFullString; if (strFullStringLoadString(nIDResource)) // = “MDITest” AfxExtractSubString(m_strTitle, strFullString, 0); // 取得第一个子串 VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); // attempt to create the window // GetIconWndClass 会调用 virtual PreCreateWindow 函数,别处也会调用,从而 // 使得子类的PreCreateWindow 将被调用多次 LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource); CString strTitle = m_strTitle; // 调用 CFrameWnd::Create() 实际创建出窗口。 // 注意:在这里将给 CMainFrame 发送 WM_CREATE 等多个消息。触发 CMainFrame 的 // OnCreate 处理等。 if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext)) { return FALSE; // will self destruct on failure normally } // save the default menu handle, 好像CMDIFrameWnd 也保存了一次? ASSERT(m_hWnd != NULL); m_hMenuDefault = ::GetMenu(m_hWnd); // load accelerator resource LoadAccelTable(MAKEINTRESOURCE(nIDResource)); // WM_INITIALUPDATE 是 MFC 发明的消息,参见后面的说明。 if (pContext == NULL) // send initial update SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); return TRUE;} 以下是从TN024: MFC-Defined Messages And Resources中抽取的部分说明:WM_INITIALUPDATEThis message is sent by the document template to all descendants of a frame window when it is safe for them to do their initial update It maps to a call to CView::OnInitialUpdate but can be used in other CWnd-derived classes for other one-shot updatingwParamNot used (0)lParamNot used (0)returnsNot used (0) 归纳一下,LoadFrame中进行了如下事情:1、 注册窗口类(AfxDeferRegisterClass)2、 实际创建窗口(Create)3、 处理菜单、快捷键,发送WM_INITIALUPDATE消息给所有子窗口。实际将在CView中处理此消息。(例如:在ToolBar上面放一个FormView,可能就能收到这个消息并处利?) 至此,CMainFrame已经成功创建,菜单已经装载,工具条、状态行等已经在CMainFrame::OnCreate中创建。让我们接着研究第一个子窗口是怎么被创建出来的,该过程和CMainFrame::LoadFrame比起来就不那么直接了。 研究CWnd::ProcessShellCommand 第一个MDI子窗口是从这里面建立出来的,这实在是缺乏直观性。不过MFC就是这样,没办法。BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo){ BOOL bResult = TRUE; switch (rCmdInfom_nShellCommand) { case CCommandLineInfo::FileNew: if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) // 关键是这里 OnFileNew(); if (m_pMainWnd == NULL) bResult = FALSE; break; case CCommandLineInfo::FileOpen: // 忽略 case CCommandLineInfo::FilePrintTo: // 忽略 case CCommandLineInfo::FilePrint: case CCommandLineInfo::FileDDE: case CCommandLineInfo::AppRegister: case CCommandLineInfo::AppUnregister: } return bResult;}进入到ProcessShellCommand,要处理很多种不同命令,我们忽略其它命令,单独看FileNew部分。注意:实际进入到了AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)之中。 AfxGetApp()实际返回了CMDITestApp的唯一实例,它从CWinApp – CWinThread – CCmdTarget – CObject 派生而来。我们没有重载OnCmdMsg,所以进入到CCmdTarget的OnCmdMsg处理中。为了研究,我们删减了一些代码。BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void pExtra, AFX_CMDHANDLERINFO pHandlerInfo){ // 这里删减了一些代码 // determine the message number and code (packed into nCode) const AFX_MSGMAP pMessageMap; const AFX_MSGMAP_ENTRY lpEntry; UINT nMsg = 0; // 这里删减了一些代码,处理后 nMsg = WM_COMMAND // 为了简化,删减了一些断言等。以下循环用于查找处理此消息的入口。
以上就是关于C++语言中说的“MFC”一般是指什么啊全部的内容,包括:C++语言中说的“MFC”一般是指什么啊、新手问MFC应用程序是什么、MFC对话框编程问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)