`
逆风的香1314
  • 浏览: 1416954 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

《深入浅出MFC》学习笔记之二

阅读更多

      MFC程序也是Windows程序,所以它也有一个WinMain,但是我们在程序中看不到它的踪影。实际上,在程序进入点之前,有一个(而且只有一个)全局对象(在Hello程序中名为theApp),这是所谓的application object,当操作系统<o:p>将程序加载并激活时,这个全局对象获得配置,其构造函数会先执行,比WinMain更早。<o:p> </o:p></o:p>

书中所举Hello程序,是一个简单的MFC程序,其主体在于WinMain和WndProc,而这两个部分其实都有相当程度的不变性MFC就是把有着相当固定行为的WinMain内部操作封装在CWinApp中;把有着相当固定行为的WndProc内部操作封装在CFrameWnd中。也就是说,CWinApp代表程序本体,CFrameWnd代表一个主框窗口<o:p> </o:p>

虽然WinMain和WndProc内部操作有相当程度的不变性,但面对不同应用程序也需有变化,所以必须以这两个类为基础,派生自己的类,并改写其中一部分成员函数。<o:p> </o:p>

 <o:p> </o:p>

CWinApp----取代WinMain的地位<o:p> </o:p>

传统上SDK程序的WinMain所完成的工作现由CWinApp的三个函数完成:
virtual BOOL InitApplication( );

virtual BOOL InitInstance( );

virtual BOOL Run( );

CFrameWnd-----取代WndProc的地位<o:p> </o:p>

CFrameWnd主要用来掌握一个窗口

引爆器------Application object<o:p> </o:p>

当执行Hello程序时,这个全局对象产生,于是构造函数(见APPCORE.CPP)执行起来,CWinApp之中的成员变量将因为这个全局对象的诞生而获得配置与初值,配置完成后,WinMainMFC早已准备好,并由链接器直接加到应用程序中去的)登场。<o:p> </o:p>

AfxWinInit:是继CWinApp构造函数之后的第一个操作;<o:p> </o:p>

此后的操作是pApp->InitApplication(其中的pApp指向CMyWinApp对象,即本例中的theApp),因为CMyWinApp继承自CWinApp,而InitApplication又是CWinApp的一个虚拟函数,我们没有改写它(大部分情况下也不需要改它),所以上述操作相当于调用CWinApp::InitApplication。此程序的代码出现在APPCORE.CPP中;<o:p> </o:p>

InitApplication之后,AfxWinMain调用pApp->InitInstanceInitInstanceCWinApp的一个虚拟函数(应用程序一定要改写这个函数,因为它在CWinApp中是个空函数,没有任何默任操作),我们改写了它,所以上述操作就是调有我们自己的这个InitInstance函数,我们将在该处展开我们的主窗口生命。<o:p> </o:p>

CMyWinApp::InitInstance一开始new了一个CMyFrameWnd对象,new会引发构造函数CmyFrameWnd::CMyFrameWnd,其中调用了CFrameWnd的成员函数Create,它将产生一个窗口。<o:p> </o:p>

   Create函数共八个参数,第一个,指定WNDCLASS窗口类,如果放置NULL,表示要以MFC内建的窗口类产生一个标准的外框窗口(Create函数在产生窗口之前会引发窗口类的注册操作,下一段讲述这一内容);第二个,指定窗口标题;第三个,指定窗口风格,默认是WS-OVERLAPPEDWINDOW,如果你不想要窗口右上角的极大极小钮,可以改成WS-OVERLAPPED|WS-CAPTION|WS-SYSMENU|WS-THICKFRAME|WS-MINIMIZEBOX|WS-MAXIMIZEBOX,如果希望有垂直滚动条,再加上WS-VSCROLL;第四个参数,指定窗口的位置与大小,默认值rectDefault ;第五个,指定父窗口,第六个指定菜单;第七个,为扩充风格,唯有以:CreateWindowEx(而非:CreateWindow)函数才能完成,事实上,CFrameWndCreate最终调用的正是:CreateWindowEx;第八个,是一个指向CCreateContext结构的指针,framework利用它,在具备Document/View结构的程序中初始化外框窗口,默认值NULL<o:p> </o:p>

CFrameWndCreate在函数中调用CreateExCWnd有这个成员函数,但其派生类CFrameWnd并没有,所以这里调用的实际上是CWndCreateEx);后者又调用PreCreateWindow虚拟函数(它在CWnd及其派生类CFrameWnd都有定义,所以实际上调用的是CFrameWnd::PreCreateWindow),这个函数调用了AfxDeferRegisterClass宏,它表示如果变量afxRegisteredClass的值显示系统已经注册了fClass 这种窗口类,MFC啥也不做,否则就调用AfxEndDeferRegisterClass(fClass){它调用两个函数完成实际的窗口类注册操作,一个是RegisterWithIcon,一个是AfxRegisterClass},准备注册之。<o:p> </o:p>

窗口显示与更新
CMyFrameWnd
::CMyFrameWnd结束后,窗口已经诞生出来;程序又回到CMyWinApp::InitInstance,于是调用ShowWindow函数令窗口显示出来,并调用UpdateWindow函数令Hello程序送出WM-PAINT<o:p> </o:p>

CWinApp::Run----程序生命的活水源头<o:p> </o:p>

Run又是CWinApp的一个虚拟函数,我们没有改写它(大部分情况下也不需要改它),所以上述操作相当于调用CWinApp::Run<o:p> </o:p>

WinMain已由MFC提供,窗口类已由MFC注册完成,连窗口函数也都由MFC提供<o:p> </o:p>

把消息与处理函数连接在一起:Message Map机制<o:p> </o:p>

MFC提供给应用程序使用的“很方便的接口”是两组宏,以Hello为例,第一个操作是在Hello.hCMyFrameWnd加上DECLARE-MESSAGE-MAP;第二个操作是在Hello.cpp的任何位置(当然不能在函数内)使用宏<o:p> </o:p>

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)<o:p> </o:p>

   ON_COMMAND(IDM_ABOUT, OnAbout)<o:p> </o:p>

   ON_WM_PAINT()<o:p> </o:p>

END_MESSAGE_MAP()<o:p> </o:p>

 <o:p> </o:p>

来龙去脉总整理<o:p> </o:p>

程序的诞生<o:p> </o:p>

Application object 产生, 内存于是获得配置,初值亦设立了。<o:p> </o:p>

  AfxWinMain执行AfxWinInit,后者又调有AfxInitThread,把消息队列尽量加<o:p> </o:p>

大到96<o:p> </o:p>

  AfxWinMain执行InitApplication。这是CWinApp的虚拟函数,我们通常不改写它<o:p> </o:p>

  AfxWinMain执行InitInstance。这是CWinApp的虚拟函数,我们必须改写它<o:p> </o:p>

  CMyWinApp::InitInstance new”了一个CMyFrameWnd对象<o:p> </o:p>

  CmyFrameWnd构造函数调用Create,产生主窗口。我们在Create参数中指定的窗口类是NULL,于是MFC根据窗口种类,自行为我们注册一个名为“AfxFrameOrView42d”的窗口类。<o:p> </o:p>

  回到InitInstance中继续执行ShowWindow,显示窗口<o:p> </o:p>

执行UpdateWindow,于是发出WM-PAINT<o:p> </o:p>

回到AfxWinMain,执行Run,进入消息循环。<o:p> </o:p>

 <o:p> </o:p>

程序开始运行:<o:p> </o:p>

  程序获得WM-PAINT消息(由CWinApp::Run中的::GetMessage循环)<o:p> </o:p>

  WM-PAINT经由::DispatchMessage送到窗口函数CWnd::DefWindowProc中。<o:p> </o:p>

  CWnd::DefWindowProc将消息传递到消息映射表格<o:p> </o:p>

  传递过程中发现有相符项目,于是调用项目中对应的函数。此函数是利用BEGIN_MESSAGE_MAPEND_MESSAGE_MAP之间的宏设立起来的。<o:p> </o:p>

  标准消息的处理程序亦有标准命名,例如WM-PAINT必由OnPaint处理<o:p> </o:p>

 <o:p> </o:p>

程序的死亡:<o:p> </o:p>

    使用者单击File/Close,于是发出WM-CLOSE<o:p> </o:p>

    CMyFrameWnd并没有设置WM-CLOSE处理程序,于是交给默认的处理程序<o:p> </o:p>

    默认函数对于WM-CLOSE的处理方式是调用::DestroyWindow,并因而发出WM-DESTROY<o:p> </o:p>

    默认的WM-DESTROY处理方式是调用::PostQuitMessage,因此发出WM-QUIT<o:p> </o:p>

    CWinApp::Run收到WM-QUIT后会结束内部之消息循环,然后调用ExitInstance,这是CWinApp的一个虚拟函数;如果CMyWinApp改写了ExitInstance,那么CWinApp::Run所调用的就是CMyWinApp::ExitInstance,否则就是CWinApp::ExitInstance<o:p> </o:p>

    最后回到AfxWinMain,执行AfxWinTerm,结束程序<o:p> </o:p>

 <o:p> </o:p>

Hello程序部分代码:<o:p> </o:p>

Hello.cpp<o:p> </o:p>

 <o:p> </o:p>

#include "Stdafx.h"<o:p> </o:p>

#include "Hello.h"<o:p> </o:p>

#include "Resource.h"<o:p> </o:p>

 <o:p> </o:p>

CMyWinApp theApp;   // application object<o:p> </o:p>

 <o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

// CMyWinApp's member<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

BOOL CMyWinApp::InitInstance()<o:p> </o:p>

{<o:p> </o:p>

   m_pMainWnd = new CMyFrameWnd();<o:p> </o:p>

   m_pMainWnd->ShowWindow(m_nCmdShow);<o:p> </o:p>

   m_pMainWnd->UpdateWindow();<o:p> </o:p>

   return TRUE;<o:p> </o:p>

}<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

// CMyWinApp's member<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

BOOL CMyWinApp::OnIdle(LONG lCount)<o:p> </o:p>

{<o:p> </o:p>

   CMyFrameWnd* pWnd = (CMyFrameWnd*)m_pMainWnd;<o:p> </o:p>

   pWnd->IdleTimeHandler(lCount);<o:p> </o:p>

 <o:p> </o:p>

   return TRUE;<o:p> </o:p>

}<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

// CMyFrameWnd's member<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

CMyFrameWnd::CMyFrameWnd()<o:p> </o:p>

{<o:p> </o:p>

   Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault,<o:p> </o:p>

          NULL, "MainMenu");     }<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)<o:p> </o:p>

   ON_COMMAND(IDM_ABOUT, OnAbout)<o:p> </o:p>

   ON_WM_PAINT()<o:p> </o:p>

END_MESSAGE_MAP()<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

void CMyFrameWnd::OnPaint()<o:p> </o:p>

{<o:p> </o:p>

CPaintDC dc(this);<o:p> </o:p>

CRect rect;<o:p> </o:p>

 <o:p> </o:p>

   GetClientRect(rect);<o:p> </o:p>

 <o:p> </o:p>

   dc.SetTextAlign(TA_BOTTOM | TA_CENTER);<o:p> </o:p>

 <o:p> </o:p>

   ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,<o:p> </o:p>

       (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);<o:p> </o:p>

}<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)<o:p> </o:p>

{<o:p> </o:p>

static char szText[] = "Hello, MFC";<o:p> </o:p>

 <o:p> </o:p>

   ((CDC*)lpdc)->TextOut(x, y, szText, sizeof(szText)-1);<o:p> </o:p>

   for(int i=1; i<50000; i++);  <o:p></o:p>

}<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

void CMyFrameWnd::OnAbout()<o:p> </o:p>

{<o:p> </o:p>

   CDialog about("AboutBox", this);  // "AboutBox" <o:p></o:p>

   about.DoModal();<o:p> </o:p>

}<o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

void CMyFrameWnd::IdleTimeHandler(LONG lCount)<o:p> </o:p>

{<o:p> </o:p>

  CString str;<o:p> </o:p>

  CRect rect(10,10,200,30);<o:p> </o:p>

  CDC* pDC = new CClientDC(this);<o:p> </o:p>

 <o:p> </o:p>

  str.Format("%010d", lCount);<o:p> </o:p>

  pDC->DrawText(str, &rect, DT_LEFT | DT_TOP);<o:p> </o:p>

}<o:p> </o:p>

 <o:p> </o:p>

Hello.h

 <o:p> </o:p>

class CMyWinApp : public CWinApp<o:p> </o:p>

{<o:p> </o:p>

public:<o:p> </o:p>

   virtual BOOL InitInstance();       // <o:p></o:p>

   virtual BOOL OnIdle(LONG lCount);  // OnIdle e<o:p> </o:p>

};<o:p> </o:p>

 <o:p> </o:p>

//--------------------------------------------------------------------<o:p> </o:p>

class CMyFrameWnd : public CFrameWnd<o:p> </o:p>

{<o:p> </o:p>

public:<o:p> </o:p>

   CMyFrameWnd();            // constructor<o:p> </o:p>

   afx_msg void OnPaint();   // for WM_PAINT<o:p> </o:p>

   afx_msg void OnAbout();   // for WM_COMMAND (IDM_ABOUT)<o:p> </o:p>

   void IdleTimeHandler(LONG lCount);  // we want it call by CMyWinApp::OnIdle<o:p> </o:p>

 <o:p> </o:p>

private:<o:p> </o:p>

   DECLARE_MESSAGE_MAP()     // Declare Message Map<o:p> </o:p>

   static VOID CALLBACK LineDDACallback(int,int,LPARAM);<o:p> </o:p>

   //<o:p> </o:p>

};
分享到:
评论

相关推荐

    深入浅出MFC读书笔记2

    深入浅出MFC读书笔记2是对MFC框架的进一步学习和理解,主要涵盖了MFC的基础概念、类库结构以及程序构建的关键要素。MFC(Microsoft Foundation Classes)是微软为Windows平台开发的应用程序提供的一种类库,它基于...

    深入浅出MFC学习笔记

    ### 深入浅出MFC学习笔记:关键知识点解析 #### 一、Windows消息机制与回调函数 在深入探讨MFC之前,我们先来理解Windows操作系统中的消息机制及其核心组成部分——回调函数。 ##### 1.1 Windows消息机制概述 ...

    《深入浅出MFC》读书心得

    "《深入浅出MFC》读书心得" 《深入浅出MFC》读书心得是 Windows...《深入浅出MFC》读书心得涵盖了 Windows 程序设计的方方面面,包括程序结构、头文件、makefile、消息循环等知识点,为开发者提供了系统性的学习指南。

    MFC 深入浅出 + 学习笔记

    总的来说,"深入浅出MFC"的学习资源可以帮助开发者从基础到高级全面了解MFC,通过实例和笔记加深理解,从而更高效地开发Windows应用程序。无论是初学者还是有一定经验的程序员,都能从中受益,提升自己的MFC编程能力...

    《深入浅出MFC》学习笔记

    ### 《深入浅出MFC》学习笔记关键知识点解析 #### 一、Win32基本程序概念 在探讨MFC之前,我们先了解Win32应用程序的基础知识,这对于理解MFC至关重要。 **Windows是一个“以消息为基础的事件驱动系统”** - **...

    深入浅出MFC随书光盘内容

    通过深入学习《深入浅出MFC》及其随书光盘的内容,开发者可以掌握以下关键知识点: 1. **MFC基础**:了解MFC的基本架构,如消息映射、事件处理机制、CWinApp类的应用程序初始化等。 2. **窗口编程**:学习如何创建...

    深入浅出MFC随书完整光盘

    深入浅出MFC随书完整光盘是一份包含丰富的MFC(Microsoft Foundation Classes)学习资源的集合,由著名计算机科学家侯捷所著书籍的配套资料。MFC是微软开发的一个C++类库,用于构建Windows应用程序,它为开发者提供...

    深入浅出MFC笔记 配合原书的好笔记 doc

    MFC(Microsoft ...总的来说,深入浅出MFC笔记是学习和理解MFC框架及其在Windows应用开发中的作用的重要参考资料,它涵盖了从应用创建到对象模型,再到图形对象的使用等多个方面,帮助开发者快速上手MFC编程。

    深入浅出MFC第二版

    台湾的繁体版本,包含学习笔记,pdf格式

    <<MFC深入浅出>>(中文简体)

    "读书拉.htm"可能是书中的一些笔记或阅读指南,"深入浅出 MFC_华中理 工_简体版.pdf"是主要的教材内容,"dushula.txt"可能是读者在阅读过程中的个人感悟或摘录,这些资源结合起来,将构成一个全面的MFC学习资料库。...

    MFC深入浅出 页面经剪裁,大小适中

    《MFC深入浅出》是一本针对Microsoft Foundation Classes (MFC)框架的经典著作,由作者深入剖析MFC的核心概念和技术细节,为读者提供了全面且系统的MFC学习资料。该书不仅适合初学者入门,也是高级开发人员不可或缺...

    MFC学习代码及笔记

    本资源包含深入浅出的MFC源代码和笔记,是学习和理解MFC框架的理想资料。 一、MFC基础 MFC由一系列的类组成,这些类代表了Windows编程中的关键概念,如窗口、对话框、菜单、控件等。其中,CWinApp是应用的核心,...

    MFC相关(三)MFC相关(三)

    《深入浅出MFC》的学习笔记提供了关于MFC框架的宝贵知识,让我们深入了解这个Microsoft的基础组件。MFC,即Microsoft Foundation Classes,是一个C++库,它封装了Windows API,简化了Windows应用程序的开发。 首先...

    『VC++技术内幕』学习笔记.rar_VC 学习_VC技术内幕_Vc_chm_vc++

    总之,《VC++技术内幕》的学习笔记是一部深入浅出的教程,对于任何想要精通VC++开发的程序员来说,都是宝贵的参考资料。通过系统学习和实践,读者将能够熟练掌握Windows环境下C++编程的各项技能。

    VC学习资料

    《深入浅出MFC》的学习笔记中,作者探讨了MFC(Microsoft Foundation Classes)框架的基础概念,特别是关于CWinApp和CFrameWnd类的角色。MFC是微软开发的一个C++库,用于简化Windows应用程序的开发,它将Windows API...

    高质量c++-c编程指南

    《深入浅出MFC》简体版则是对MFC的深入解析,适合有一定C++和Windows编程基础的开发者。它不仅讲解了MFC的基本用法,还可能涉及MFC的高级特性和技术,如ActiveX控件、网络编程、数据库访问等。通过阅读本书,开发者...

    vc sunxin part2

    2. "深入浅出.MFC.pdf":MFC(Microsoft Foundation Classes)是微软提供的一套C++库,用于简化Windows应用程序的开发。这本书可能详细解释了如何使用MFC进行Windows编程,包括窗口管理、用户界面设计、文件操作等。...

    vc笔记,孙新视频作的一些笔记

    孙新的视频教程是许多初学者学习VC++的宝贵资源,他的教学风格深入浅出,适合新手入门。通过观看他的视频并记录笔记,可以系统地了解VC++的基本概念和编程技巧。 1. **IDE介绍** Visual Studio是Microsoft提供的...

Global site tag (gtag.js) - Google Analytics