`
tansitongba
  • 浏览: 504867 次
文章分类
社区版块
存档分类
最新评论

深入浅出MFC学习笔记:(第一章:win32基本概念,第二章:C++的重要性质)

 
阅读更多

深入浅出MFC阅读笔记:

写在开始的话:

刚结束《C++primer》的第二次阅读,决定趁热打铁,学习《深入浅出MFC》。当然,学习框架不是目的,而是通过学习MFC底层框架实现原理,对C++面向对象思想以及各种特性的进一步巩固。编程是一门实践课,需要不断的练习,才能得到提高。而深入学习MFC框架,就是我选择提高C++编程水平的方式之一。按部就班、不浮躁是我对学习本书的要求。废话少说,直入主题!!!

第一章:win32基本程序概念

Windows的运行本质:基于消息,事件驱动。

Windows程序分为:程序代码和UI资源,两大部分。UI资源借助各种工具产生,以二进制形式存储,并以各种扩展名文件存在。使用.rc文件描述它们RC编译器读取rc文件后将所有的UI资源文件制作成.RES文件。链接器将obj目标文件和.DEF.RES链接在一起,形成完整的windows可执行程序。

应用程序调用的windowsAPI是在执行时链接的,但是,在链接期间,需要为调用者提供必要的信息,表示在执行时需要动态调用哪些函数,它们在那个dll中。这些适当的信息放在.lib文件中。

所有的windows程序都学要包含windows.h头文件,但是它只包含三大模块所提供的API函数。如果需要其他模块中的API就需要包含相应的头文件。

Windows程序依靠外部事件驱动,程序不断等待任何可能的输入,一旦捕捉,就将消息放在系统队列或者程序队列中。GetMessage用于从消息队列中取出消息,然后交由程序处理。因此程序就是靠GetMessage函数推动的。

硬件产生的消息放在系统队列中。由windows系统或其他程序产生的消息放在程序队列。

接受并处理消息的主角是窗口,每个窗口都有一个处理消息的函数,被称为消息处理函数。

Win32callback被定义为_stdcall,它声明函数调用习惯:参数进栈顺序,处理堆栈的责任归属。

一般情况下,将注册窗口的代码封装在InitApplication内,将创建窗口的代码封装在InitInstance内。这种方式很普遍。MFC把这两个函数封装成CwinApp的两个虚成员函数。

TranslateMessage用于转换键盘消息。DispatchMessage将消息发送给函数处理。消息中包含所属窗口的句柄,而窗口类又注册了窗口处理函数。窗口处理函数通过switch/case判断消息的种类,然后决定处理方式。

MFC采用消息映射表的形式,来将消息和它所对应的消息处理函数一一对应。消息映射表为一个数组,每一项存储一个结构体类型:

StructMSGMAP_ENTRY

{

UINTnMessage;

LONG(*pfn)(HWND,UINT,WPARAM,LPARAM);

};

nMessage为消息IDpfn是函数指针,表示该消息对应的消息处理函数。

有了这个结构,当需要相应一个新消息时,只需向数组里添加一项就可以了。这正是面向对象观念中,将数据和处理数据的方法封装起来的一种具体实现。

MFC定义了一个宏,用于计算数组的长度:

#definedim(x)(sizeof(x)/sizeof(x[0]);

接下来将会定义两个MSGMAP_ENTRY类型的数组,并向数组添加元素,将消息与消息处理函数关联起来。

第一个数组处理非COMMAND消息。

structMSGMAP_ENTRY_messageEntries[]=

{

WM_CREATE,OnCreate,

WM_COMMAND,OnCommand,//所有command消息都由此函数处理。

…….

};

第二个处理WM_COMMAND消息:

structMSGMAP_ENTRY_commandEntryis=

{

IDM_ABOUT,OnAbout,

IDM_SAVEAS,OnSaveAs

………..

};

定义好之后,窗口函数就可以以一种通用的形式设计,如:

LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)

{

for(inti=0;i<dim(_messageEntries);i++)

{

if(message==_messageEntries[i].nMessage)

{

(_messageEntries[i].pfn)(hwnd,message,wParam,lParam);

}

}

return(DefWindowProc(hwnd,message,wParam,lParam));

}

LRESULTCALLBACKOnCommand(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)

{

for(inti=0;i<dim(_commandEntries);i++)

{

if(message==_commandEntries[i].nMessage)

{

(_commandEntries[i].pfn)(hwnd,message,wParam,lParam);

}

}

return(DefWindowProc(hwnd,message,wParam,lParam));

}

如此一来,wndProcOnCommand可以永远不变,每当有新的要处理的消息,就在_messageEntries_commandEntries两个数组添加新元素,并针对新消息编写消息处理函数即可。

以上就是对MFC消息映射的一个简单模拟,当然MFC做的更好更精致。

常用的对话框分为模态的和非模态的对话框。

为了创建一个对话框,需要两样东西:

1:对话框模板,它是在RC文件中定义的,用以表明对话框的外观。

2:对话框函数。很类似与窗口函数,但是只处理WM_INITDIALOGWM_COMMAND两个消息。对话框中的每个控件都有自己的窗口函数,它们以消息的方式与父窗口沟通。所有的控件传来的消息都是WM_COMMAND消息,有所属控件ID区分。

DialogBoxEndDialog两个函数,用于模态对话框的激活与结束。DialogBox指明该对话框所使用的模板,所属父窗口以及窗口函数名称。对话框内部有一个系统维护的消息循环。对话框处理过消息后,应该返回TRUE,因为对话框函数上层还有一个系统提供的默认对话框函数,如果返回FALSE则默认对话框函数就会接受处理。

Windows程序需要一个模块定义文件,将模块名称、程序段和数据段的内存特性、模块堆大小、堆栈大小、所有的callback函数名称等登记下来。在vc中,不再需要特别准备.DEF文件,因为所有这些都有默认值。但是在写dll库时,好像需要自己提供.def文件。

操作系统和应用程序职责不同,二者是互相合作的关系,各做各的分内事,并互相以消息通知对方。

当没有任何程序使用定时器,使用者也没有触碰键盘和鼠标或任何外围设备,那么系统就进入了空闲时间。空闲时间是指:系统中没有任何消息等待处理。

PeekMessageGetMessage都是从消息队列中获取消息,有消息时将消息分发出去。不同点是:当消息队列中没有消息时,GetMessage会一直等待(挂起),直到出现下一个消息时返回。而PeekMessage会在没有取得消息后,立即返回,这使得程序得以继续执行。因此,传统的SDK程序一般使用PeekMessage代替GetMessage来运行后台工作。

Cruntime函数库,有两个版本,一个为单线程程序使用,另一个视为多线程程序使用。而vc提供了六个版本的Cruntime函数库。可以使用vc编译器提供的选项,确定使用哪个版本的Cruntime函数库。

进程是资源分配和保护的基本单位。而线程是cpu调度的基本单位

内核对象是系统的一种资源。如进程对象、事件对象、线程对象、文件对象、、、。《windows核心编程》第三章对内核对象有个比较详细的介绍,可以参考下。

这些内核对象通过API产生,通过对应类型句柄进行引用。调用CloseHandle进行关闭。

系统通过调用CreateProcess执行进程。本来通过这种方式执行起来的所有windows程序都是shell的子进程。但是,shell在调用时CreateProcess时已经把关系切断了。它们都是独立的个体。调用CreateProcess产生一个进程对象和一个主线程对象,它们存储在传给CreatProcess的一个PROCESS_INFORMATION结构内。可以从此结构中获得句柄,然后在父进程中使用。

觉得《深入浅出MFC》在介绍进程内核对象的计数时有错误。系统调用CreateProcess成功后,进行内核对象的计数应该是2,而不是1。否则在调用成功后,再CloseHandle切断与父进程关系时,进程对象就被释放了。线程也类似。《windows核心编程》进程这一章,也有详细的介绍。看来大师也有犯浑的时候。不知理解是否正确,有明白的请不吝赐教。

为了保证多线程安全,使用Cruntime函数库时,必须为每一个线程做一些登记工作,有了这些记录,Cruntime函数库就可以为每一个线程配置一块内存作为线程的局部空间使用。_beginthreadex就负责这个任务。它和CreateThread参数完全相同,只是类型不同,因为Cruntime函数库不应该依赖于具体的平台。同样Cruntime也提供了替代ExitThread的函数:_endthreadex

优先级是线程调度的主要依据。优先级高的线程,首先获得cpu的调度。操作系统会视情况调整各线程的优先级,以确保优先级高的不会长时间占用cpu,而优先级低的线程却长时间饥饿。

优先级是由两方面决定的:1,优先级等级。2,相对优先级。

所有这些关于windows内核对象、进程、线程以及优先级调度,我会在博文《谈谈windows核心编程系列》有更详细的介绍。

第二章:C++的重要性质

虽然对C++的很多特定都接触过,也刚看完《C++primer》,但我仍觉得学习这一章也很有必要。一是因为侯绍的都是在MFC中需要的一些技术,在介绍C++的同时也穿插着MFC的一些原理。二是为了阅读的连贯性,跟着作者一步一步的走,慢慢的与作者形成默契,后面的东西也更容易接受。开始!!

面向对象的观念是描绘现实用的,可以用生活中的经验去思考程序设计的逻辑。C++仅仅是其中一种面向对象的语言,而各种面向对象的思想是相通的。

高速行驶的汽车刹车时不能踩离合器。这个真不知道。

MFC有两个十分重要的虚函数:与docunment有关的Serilize函数,和与view有关的OnDraw函数。应该在自己的CMyDocCMyView改写这两个函数。

每一个内含虚函数的类,编译器都会为它生成一个虚函数表。表中的每一项都指向一个虚函数的地址。编译器会在类中添加一项成员:虚函数表地址。因此,任何含有虚函数的类,除了其本身数据成员占有的空间外,还要有一个指向虚函数表的指针所占的空间。32位机器为4字节。

C++类的成员函数,在编译时被编译器改过名称,并添加一个参数:this指针,通过传递的对象的地址不同,作用在不同的对象上。在类的对象上的内存区块上,看不到任何与成员函数有关的东西。它们都变成了一般的函数了。

当我们调用每个对象的虚函数时,事实上是通过指向虚函数表指针,找到虚函数表,间接找出虚函数的真正地址。虚函数表中各虚函数的地址是依据虚函数的声明次序填入的。

派生类会继承基类的虚函数表。当我们在派生类中改写虚函数时,虚函数表就受到影响:表中元素所指的地址将不再是基类的虚函数地址,而是在派生类定义的函数地址。

上面介绍的不就是《深入探索C++对象模型》中的内容吗!!既然如此添加一条书上没有的,《深入探索C++对象模型》中说:内存对齐产生的结果,一定是类中数据成员中,占最大字节数的变量的整数倍。

static成员函数,没有this函数.MFC应用程序中,这正是被调用callback函数所需要的。另外:线程函数如果在类中的话,也必须是static类型的。

P75页,介绍RTTI时,举了一个例子:基类有个name成员,但是派生类对此成员的初始化都是在派生类的构造函数进行的。这一点很不好,《C++primer》中说,基类的成员一定要通过基类的构造函数初始化,不要在派生类中直接初始化,如果以后其他人又派生了其他类,有可能就忘记初始化了。

MFC支持两种exception版本:一种是C++提供的,另一种是MFC定义的宏定义。个人倾向于使用C++的东西,一是觉得看着这么多宏头疼,二是为了可移植性的原因。

分享到:
评论

相关推荐

    《深入浅出MFC》高清第二版(书签)_深入浅出MFC_c++mfc_

    在压缩包内,除了主教材《深入浅出MFC》高清第二版(书签).pdf外,还有两个辅助文件:VC驿站-C C++ VC 编程 教程 培训 论坛.lnk可能是一个链接,提供了更多C++和MFC相关的学习资源和讨论平台;VC 驿站.txt可能包含...

    深入浅出MFC读书笔记3

    深入浅出MFC读书笔记3 在MFC中,Document-View架构是一个非常重要的概念。本文将对Document-View架构中的关键组件进行深入探讨,并对其实现思路进行详细的解析。 首先,让我们来看一下Document的概念。在MFC中,...

    深入浅出MFC学习笔记

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

    深入浅出MFC读书笔记2

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

    深入浅出 MFC (第二版) 高清晰

    第一章 Win32 程序基本概念 第二章 C++的重要性质 第三章 MFC六大关键技术之仿真 第二篇 欲善工事先利其器 第四章 Visual C++ 集成开发环境 第三篇 浅出MFC程序设计 第五章 总观Application Framework 第六章 MFC...

    深入浅出MFC 深入浅出MFC 深入浅出MFC

    《深入浅出MFC》是一本专注于Microsoft Foundation Classes (MFC) 的技术书籍,MFC是微软为Windows应用程序开发提供的一套C++类库。它将Windows API进行了封装,使得开发者能够更方便地构建Windows桌面应用程序。MFC...

    深入浅出MFC读书笔记1

    《深入浅出MFC》读书笔记1主要涵盖了MFC(Microsoft Foundation Classes)的基础知识...总的来说,《深入浅出MFC》读书笔记1为读者揭示了Win32程序的基本构造和MFC框架的初步概念,为后续深入学习MFC打下了坚实的基础。

    MFC 深入浅出 + 学习笔记

    文件`深入浅出MFC笔记(配合原书的好笔记).doc`可能是作者阅读侯捷的《深入浅出MFC》后所做的详细笔记,可能包含了对书中关键概念的理解、例子的解析以及个人的实践心得。这种学习方式对于巩固理论知识和提高实际编程...

    MFC入门教程:1天深入浅出MFC

    MFC入门教程:1天深入浅出MFC

    《深入浅出MFC》读书心得

    "《深入浅出MFC》读书心得" 《深入浅出MFC》读书心得是 Windows 程序设计的经典读物,本文将对书中的一些重要知识点进行总结和解释。 首先,Windows 程序可以分为两个部分:程序代码和 UI(User Interface)资源。...

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC 资源内容: visual c++_MFC 达内 C++ C++课件.ppt c++源码 .rar Core C++ Programming_new.ppt Core C++ ...

    深入浅出MFC第一章例子

    《深入浅出MFC》是面向Windows编程领域的一本经典著作,主要讲解了Microsoft Foundation Classes (MFC)库的应用,这个库是微软为简化Windows应用程序开发而提供的C++类库。MFC是基于Windows API的封装,使得开发者...

    C++ 学习资料大全 C++编程思想 WINDOWS 核心编程 WINDOWS程序设计第5版 深入浅出MFC简体中文版 C++ Primer 3rd Edition 中文完美版

    4. **深入浅出MFC简体中文版**:Microsoft Foundation Classes (MFC) 是一个C++库,用于构建Windows应用程序。本书以易于理解的方式介绍了MFC的架构和用法,包括文档/视图架构、对话框、控件、数据库访问等,帮助...

    深入浅出MFC

    ### 深入浅出MFC —— 侯俊杰详解MFC技术 #### MFC简介与重要性 Microsoft Foundation Classes (MFC) 是一套由微软开发的C++类库,用于简化Windows应用程序的开发过程。它基于Windows API,通过面向对象的方法封装...

    深入浅出mfc-笔记

    ### 深入浅出MFC—笔记关键知识点解析 #### 一、Windows消息机制与回调函数 在深入了解MFC之前,我们首先需要理解Windows操作系统的基本工作原理,尤其是消息驱动模型以及回调函数的概念。 **1.1 Windows消息机制...

    深入浅出MFC(C++)

    **深入浅出MFC(C++)** MFC(Microsoft Foundation Classes)是微软提供的一套C++类库,用于简化Windows应用程序开发。它基于面向对象的设计,为开发者提供了丰富的控件、窗口、消息处理机制等,让开发者可以更加...

    《深入浅出MFC (第二版)》(候捷 著)

    第一章 Win32 程序基本概念 第二章 C++的重要性质 第三章 MFC六大关键技术之仿真 第二篇 欲善工事先利其器 第四章 Visual C++ 集成开发环境 第三篇 浅出MFC程序设计 第五章 总观Application Framework 第六章 MFC...

    深入浅出MFC(第二版).rar

    《深入浅出MFC(第二版)》是一本专注于Microsoft Foundation Classes (MFC) 的经典教程,旨在帮助读者深入理解并熟练运用这一强大的C++库来构建Windows应用程序。MFC是微软公司为开发者提供的一种基于Win32 API的C++...

    候俊杰 深入浅出MFC

    《深入浅出MFC》是由侯俊杰撰写的一本关于Microsoft Foundation Classes (MFC)的权威书籍,旨在帮助读者深入理解和应用这一强大的Windows应用程序开发框架。MFC是微软为简化Win32 API编程而设计的一个类库,它将底层...

Global site tag (gtag.js) - Google Analytics