mfc基础入门教程

嵌入式操作系统

55人已加入

描述

  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));//设置焦点在第一个编辑框

  }

  最后编写完成,运行一下,弹出一个界面如下:

  mfc

  验证一下程序,以加法为例,m_edit1输入18,m_edit2输入36,得出结果如下所示。

  mfc

  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的基类可以覆盖该函数,例如边框窗口类等覆盖了该函数以实现边框窗口的创建,视类则使用它来创建视窗口。

  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。

  mfc

  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 toolbar\n”);

  return -1; // fail to create

  }

  if (!m_wndStatusBar.Create(this) ||

  !m_wndStatusBar.SetIndicators(indicators,

  sizeof(indicators)/sizeof(UINT)))

  {

  TRACE0(“Failed to create status bar\n”);

  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开发文档。

  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派生的窗口

  程序员可以在派生类中实现上述两种机制之一,然后,在相应的规范下使用。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分