MFC框架类

1.Cwnd

Cwnd类是MFC中一个重要的类,它封装了与窗口有关的操作。

2.MFC中的WinMain

MFC中的WinMain函数在APPMODUL.cpp中,在编译的时候才会连接进来。

3.theApp全局对象

在程序入口函数加载前,系统已经为全局变量或全局对象分配了内存空间并为它们赋与了初值。对于全局对象,要先调用构造函数对其进行初始化。调用theApp时会选调用设用其父类CwinApp的构造函数。

4.CWinApp

在文件appcore.cpp中

5.AfxWinMain函数

WinMain函数实际上是调用AfxWinMain函数来实现的。AfxWinMain位于WINMAIN.app中。

  1. 设计和注册窗口

MFC已经为我们预定义了一些默认的标准窗口类,只需要选择所需的窗口类,然后注册就可以了。窗口类的注册是由AfxEndDeferRegisterClass函数完成的。AfxEndDeferRegisterClass函数判断窗口类的类型,然后赋予相应的类名,这些类名都是MFC预定义的。之后计用AfxRegisterClass函数注册窗口类。

AfxRegisterClass函数首先获得窗口柯类信息。如果该窗口类已经注册,则直接返回一个真值;如果尚未注册,就调用RegisterClass函数注册该窗口类。

  1. 创建窗口

在MFC程序中,窗口的创建功能由Cwnd类的CreateEx函数实现,该函数的声明位于AFXWin.h文件中。实现代码位于WINCORE.CPP文件中。如果在子类的PreCreateWindow函数中修改了CREATESTRUCT结构体的值,那么,接下来调用CreateWindowEx函数时,其参数就会发生相应的改变,从而就会创建一个符合我们要求的窗口。

  1. 显示及更新窗口

在Test程序的应用程序类(CTestApp)中有一个名为m_pMainWnd的成员变量。该变量是一个Cwnd类型的指针,它保存了应用程序框架窗口对象的指针。也就是说,是指向CmainFrame对象的指针。

在CtestApp类的InitInstance函数内部有如下代码。

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();

这两行代码的功能是显示应用程序框架窗口和更新这个窗口。

  1. 消息循环

CwinThread类的Run函数就是完成消息循五常这一任务的,该函数是在AfxWinMain函数中调用的。

调用形式如下

pThread->Run();

  1. 窗口过程函数

AfxEndDeferRegisterClass函数有这样一句代码。

wndcls.lpfnWndProc=DefWindowProc;这行代码的作用指定一个默认的窗口过程DefWindowProc。但实际上,MFC程序并不是把所有消息都交给DefiWindowProc这一默认的窗口过程来处理的,而是采用一种称之为消息映射的机制来处理各种消息的。

11.MFC程序运行过程

首先利用全局应用程序对象theApp启动应用程序。正是产生了这个全局对象,基类CWinApp中的this指针才能指向这个对象。如果没有这个全局对象,程序在编译时不会出错,但是在运行时就会出错。

调用全局应用程序对象的构造函数,从而就会先调用其基类CWinApp的构造函数后者完成应用程序的一些初始化工作,并将用应程序对象的指针保存起来。

进入WinMain函数。在AfxWinMain函数中可以获取子类(对Test程序来说,就是CtestApp类)的指针,利用此指针调用虚函数:InitInstance,根据多态性原理,实际上调用的是子类(CTestApp)的InitInstance函数。后者完成应用程序的一些初始化工作,包括窗口类的注册、创建、窗口的显示和更新。期间会多次调用CreateEx函数,因为一个单文档MFC应用程序有多个窗口,包括框架窗口、工具条、状态条等。

进入消息循环。虽然也设置了默认的窗口过程函数,但是,MFC应用程序实际上是采用消息映射机制来处理各种消息的。当收到WM_QUIT消息时,退出消息循环,程序结束。

  1. 文档视类结构

MFC程序除了主框架窗口外,还有一个窗口视类窗口,对应的类是Cview类,Cview类也派生于CWnd类。

CtestDoc类派生于Cdocument类。其基类是CcmdTarget,后者又派生于Cobject类,CtestDoc不是一个窗口类,是一个文档类。

  1. 窗口类、窗口类对象与窗口

C++窗口类对象与窗口并不是一回事,它们之间惟一的关系就是C++窗口类对象内部定义了一个窗口句柄变量,保存了与这个C++窗口类对象相关的那个窗口的句柄。窗口销毁时,与之对应的C++窗口类对象销毁与否,要看其生命周期是否结束,但C++窗口类对象销毁时,与之相关的窗口也将销毁。

const int *p和int *const p的区别

const int *p;
这里的 p 是一个指向 int 类型 const 对象的指针,const 限定了p指针所指向的对象类型,而并非 p 本身。也就是说,p 本身并不是
const。在定义时不需要对它进行初始化,如果需要的话,允许给 p重新赋值,使其指向另一个 const 对象。但不能通过p 修改其所指对象的值.

int *const p

从右向左把上述定义语句读作“p是指向 int 型对象的const 指针”。与其他 const 量一样,const 指针的值不能修改,这就意味着

不能使p 指向其他对象。任何企图给 const 指针赋值的行为(即使给p 赋回同样的值)都会导致编译时的错误.

在C++中class和struct的区别

            以前老以为有很大的不同,其实也就是默认的的初始化访问级别不同而已,C++默认成员是私有的而 C 默认是公有的。

C++ 是一种静态类型语言:变量和函数在使用前必须先声明。变量可以声明
多次但是只能定义一次。定义变量时就进行初始化几乎总是个好主意。

我心中的C++

如果把我们的对编程语言的需求总结为四个:效率,灵活,抽象,生产率。那么,C语言玩的是前两个,而C++玩的是前三个,Java和C#玩的是后两个(抽象和生产率)

为什么要使用注册窗口类?

为什么要使用注册窗口类?

在一个窗口中,可能有不同的按钮,它们的工作原理都是一样的。但是各个按钮可能都有不同的表现形式,比如大小,颜色等。所以在这种情况下,我们需要将创建窗口的共性提取出来,然后再设置每个具体的窗口。这样就更加符合面向对象的原理。

当应用程序取得消息后,DispatchMessage是如何知道要发给谁去处理呢?

这是因为在注册窗口类时,已经指定了。否则windows不可能知道。

OFFSET 和 ADDR 的异同

OFFSET 和 ADDR 的异同:
1、offset 不能获取局部变量的地址;
2、addr 只能用于调用函数(invoke)时, 不能用于赋值操作;
3、addr 面对局部变量时会转换为 lea 等指令, addr 面对全局变量时则直接调用 offset;
4、在 invoke 中应尽量使用 addr, 其他只用 offset.

CPU直接读取数据的地方

CPU可以直接读写3 个地方的数据:

(1)CPU 内部的寄存器;

(2)内存单元;

(3)端口;

对端口的读写不能用mov、push、pop等内存读写指令。

端口的读写指令只有两条:

in和out,

分别用于从端口读取数据和往端口写入数据。