mfc基础入门教程
扫描二维码
随时随地手机看文章
MFC
微软基础类库(英语:Microsoft FoundaTIon Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
MFC(MicrosoftFoundaTIonClasses)是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数,vc++是微软公司开发的c/c++的集成开发环境,所谓集成开发环境,就是说利用它可以编辑,编译,调试,而不是使用多种工具轮换操作,灵活性较大。vc也指它的内部编译器,集成开发环境必须有一个编译器内核,例如DevC++其中一个编译器内核就是gcc。
MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率。但是MFC的封装很浅,所以效率上损失不大。
MFC初学教程
编写MFC程序,其实跟编写C++程序一样,在VS编译平台上新建项目,然后一直默认下一步就行,不过有其他需求则需要根据实际情况来添加。建好一个项目后,会出现两个界面,一个是显示窗口,一个是编程界面,类似LV中的前面板和程序框图。在界面右边有个工具箱,可以根据需要添加控件。
下面主要编写一个简单的计算器程序,实现对输入数的四则运算,主要步骤如下:
1、在对话框中放置6个按钮控件和3个编辑框控件
具体操作:界面右边点击工具箱,根据具体需要选择具体控件。
2、将3个编辑框控件分别添加float型变量m_edit1、m_edit2、m_edit3
具体操作:选中编辑框点右键添加变量,将右边类别改为value,变量名分别改为m_edit1、m_edit2、m_edit3。
3、将6个个按钮控件重新命名
具体操作:选中按钮点击右键属性,将CapTIon改为所需要+ - * / 清除 关闭,具体可根据需要来命名。
4、选择工具箱中Group Box将四则运算框住,然后通过属性改名字,同时在上方添加静态文本(StaTIc Text)来编辑命名。
界面主要部分完成,接下来就是编写代码,双击各个控件,就可自动跳转到程序编写部分,主要代码如下
[html] view plain copyvoid CMFC入门Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(true);//从控件获得数据赋给变量
m_edit3 = m_edit1 + m_edit2;
UpdateData(false);//输出变量的值到控件
}
void CMFC入门Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(true);
m_edit3 = m_edit1 - m_edit2;
UpdateData(false);
}
void CMFC入门Dlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(true);
m_edit3 = m_edit1*m_edit2;
UpdateData(false);
}
void CMFC入门Dlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(true);
if (m_edit2 == 0)
{
MessageBox(_T(“除数不能为0”));
return;
}
m_edit3 = m_edit1 / m_edit2;
UpdateData(false);
}
void CMFC入门Dlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
m_edit1 = 0;
m_edit2 = 0;
m_edit3 = 0;
UpdateData(false);
GotoDlgCtrl((CEdit*)GetDlgItem(IDC_EDIT1));//设置焦点在第一个编辑框
}
最后编写完成,运行一下,弹出一个界面如下:
验证一下程序,以加法为例,m_edit1输入18,m_edit2输入36,得出结果如下所示。
mfc编程入门教程
1.MFC窗口类CWnd
在Windows系统里,一个窗口的属性分两个地方存放:一部分放在“窗口类”里头,如上所述的在注册窗口时指定;另一部分放在Windows Object本身,如:窗口的尺寸,窗口的位置(X,Y轴),窗口的Z轴顺序,窗口的状态(ACTIVE,MINIMIZED,MAXMIZED,RESTORED…),和其他窗口的关系(父窗口,子窗口…),窗口是否可以接收键盘或鼠标消息,等等。
为了表达所有这些窗口的共性,MFC设计了一个窗口基类CWnd。有一点非常重要,那就是CWnd提供了一个标准而通用的MFC窗口过程,MFC下所有的窗口都使用这个窗口过程。至于通用的窗口过程却能为各个窗口实现不同的操作,那就是MFC消息映射机制的奥秘和作用了。这些,将在后面有关章节详细论述。
CWnd提供了一系列成员函数,或者是对Win32相关函数的封装,或者是CWnd新设计的一些函数。这些函数大致如下。
方法/步骤
(1)窗口创建函数
这里主要讨论函数Create和CreateEx。它们封装了Win32窗口创建函数::CreateWindowEx。Create的原型如下:
BOOL CWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd, UINT nID,
CCreateContext* pContext)
Create是一个虚拟函数,用来创建子窗口(不能创建桌面窗口和POP UP窗口)。CWnd的基类可以覆盖该函数,例如边框窗口类等覆盖了该函数以实现边框窗口的创建,视类则使用它来创建视窗口。[!--empirenews.page--]
Create调用了成员函数CreateEx。CWnd::CreateEx的原型如下:
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
CreateEx有11个参数,它将调用::CreateWindowEx完成窗口的创建,这11个参数对应地传递给::CreateWindowEx。参数指定了窗口扩展风格、“窗口类”、窗口名、窗口大小和位置、父窗口句柄、窗口菜单和窗口创建参数。
CreateEx的处理流程将在后面4.4.1节讨论窗口过程时分析。
窗口创建时发送WM_CREATE消息,消息参数lParam指向一个CreateStruct结构的变量,该结构有11个域,其描述见后面4.4.1节对窗口过程的分析,Windows使用和CreateEx参数一样的内容填充该变量
(2)窗口销毁函数
例如:
DestroyWindow函数 销毁窗口
PostNcDestroy( ),销毁窗口后调用,虚拟函数
3)用于设定、获取、改变窗口属性的函数,例如:
SetWindowText(CString tiltle) 设置窗口标题
GetWindowText() 得到窗口标题
SetIcon(HICON hIcon, BOOL bBigIcon);设置窗口像标
GetIcon( BOOL bBigIcon ) ;得到窗口像标
GetDlgItem( int nID);得到窗口类指定ID的控制子窗口
GetDC(); 得到窗口的设备上下文
SetMenu(CMenu *pMenu); 设置窗口菜单
GetMenu();得到窗口菜单
…
(4)用于完成窗口动作的函数
用于更新窗口,滚动窗口,等等。一部分成员函数设计成或可重载(Overloaded)函数,或虚拟(Overridden)函数,或MFC消息处理函数。这些函数或者实现了一部分功能,或者仅仅是一个空函数。如:
有关消息发送的函数:
SendMessage( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );
给窗口发送发送消息,立即调用方式
PostMessage(( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );
给窗口发送消息,放进消息队列
…
有关改变窗口状态的函数
MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );
移动窗口到指定位置
ShowWindow(BOOL );显示窗口,使之可见或不可见
…
实现MFC消息处理机制的函数:
virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam ); 窗口过程,虚拟函数
virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam );处理命令消息
…
消息处理函数:
OnCreate( LPCREATESTRUCT lpCreateStruct );MFC窗口消息处理函数,窗口创建时由MFC框架调用
OnClose();MFC窗口消息处理函数,窗口创建时由MFC框架调用
…
其他功能的函数
CWnd的导出类是类型更具体、功能更完善的窗口类,它们继承了CWnd的属性和方法,并提供了新的成员函数(消息处理函数、虚拟函数、等等)。
常用的窗口类及其层次关系见图1-1。
2.在MFC下创建一个窗口对象
MFC下创建一个窗口对象分两步,首先创建MFC窗口对象,然后创建对应的Windows窗口。在内存使用上,MFC窗口对象可以在栈或者堆(使用new创建)中创建。具体表述如下:
创建MFC窗口对象。通过定义一个CWnd或其派生类的实例变量或者动态创建一个MFC窗口的实例,前者在栈空间创建一个MFC窗口对象,后者在堆空间创建一个MFC窗口对象。
调用相应的窗口创建函数,创建Windows窗口对象。
例如:在前面提到的AppWizard产生的源码中,有CMainFrame(派生于CMDIFrame(SDI)或者CMDIFrameWnd(MDI))类。它有两个成员变量定义如下:
CToolBar m_wndToolBar;
CStatusBar m_wndStatusBar;
当创建CMainFrame类对象时,上面两个MFC Object也被构造。
CMainFrame还有一个成员函数
OnCreate(LPCREATESTRUCT lpCreateStruct),
它的实现包含如下一段代码,调用CToolBar和CStatusBar的成员函数Create来创建上述两个MFC对象对应的工具栏HWND窗口和状态栏HWND窗口:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
…
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0(“Failed to create toolbarn”);
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0(“Failed to create status barn”);
return -1; // fail to create
}
…
}
关于工具栏、状态栏将在后续有关章节作详细讨论。
在MFC中,还提供了一种动态创建技术。动态创建的过程实际上也如上所述分两步,只不过MFC使用这个技术是由框架自动地完成整个过程的。通常框架窗口、文档框架窗口、视使用了动态创建。介于MFC的结构,CFrameWnd和CView及其派生类的实例即使不使用动态创建,也要用new在堆中分配。理由见窗口的销毁(2.2.5节)。
至于动态创建技术,将在下一章具体讨论。
在Windows窗口的创建过程中,将发送一些消息,如:
在创建了窗口的非客户区(Nonclient area)之后,发送消息WM_NCCREATE;
在创建了窗口的客户区(client area)之后,发送消息WM_CREATE;
窗口的窗口过程在窗口显示之前收到这两个消息。
如果是子窗口,在发送了上述两个消息之后,还给父窗口发送WM_PARENATNOTIFY消息。其他类或风格的窗口可能发送更多的消息,具体参见SDK开发文档。[!--empirenews.page--]
3.MFC窗口的使用
MFC提供了大量的窗口类,其功能和用途各异。程序员应该选择哪些类来使用,以及怎么使用他们呢?
直接使用MFC提供的窗口类或者先从MFC窗口类派生一个新的C++类然后使用它,这些在通常情况下都不需要程序员提供窗口注册的代码。是否需要派生新的C++类,视MFC已有的窗口类是否能满足使用要求而定。派生的C++类继承了基类的特性并改变或扩展了它的功能,例如增加或者改变对消息、事件的特殊处理等。
主要使用或继承以下一些MFC窗口类(其层次关系图见图1-1):
框架类CFrameWnd,CMdiFrameWnd;
文档框架CMdiChildWnd;
视图CView和CView派生的有特殊功能的视图如:列表CListView,编辑CEditView,树形列表CTreeView,支持RTF的CRichEditView,基于对话框的视CFormView等等。
对话框CDialog。
通常,都要从这些类派生应用程序的框架窗口和视窗口或者对话框。
工具条CToolBar
状态条CStatusBar
其他各类控制窗口,如列表框CList,编辑框CEdit,组合框CComboBox,按钮Cbutton等。
通常,直接使用这些类。
4.在MFC下窗口的销毁
窗口对象使用完毕,应该销毁。在MFC下,一个窗口对象的销毁包括HWND窗口对象的销毁和MFC窗口对象的销毁。一般情况下,MFC编程框架自动地处理了这些。
(1)对CFrameWnd和CView的派生类
这些窗口的关闭导致销毁窗口的函数DestroyWindow被调用。销毁Windows窗口时,MFC框架调用的最后一个成员函数是OnNcDestroy函数,该函数负责Windows清理工作,并在最后调用虚拟成员函数PostNcDestroy。CFrameWnd和CView的PostNcDestroy调用delete this删除自身这个MFC窗口对象。
所以,对这些窗口,如前所述,应在堆(Heap)中分配,而且,不要对这些对象使用delete操作。
(2)对Windows Control窗口
在它们的析构函数中,将调用DestroyWidnow来销毁窗口。如果在栈中分配这样的窗口对象,则在超出作用范围的时候,随着析构函数的调用,MFC窗口对象和它的Windows window对象都被销毁。如果在堆(Heap)中分配,则显式调用delete操作符,导致析构函数的调用和窗口的销毁。
所以,这种类型的窗口应尽可能在栈中分配,避免用额外的代码来销毁窗口。如前所述的CMainFrame的成员变量m_wndStatusBar和m_wndToolBar就是这样的例子。
(3)对于程序员直接从CWnd派生的窗口
程序员可以在派生类中实现上述两种机制之一,然后,在相应的规范下使用。