c++面试题(WIN32与MFC篇)

●MFC主要要用到哪几个类?及其各个类的作用。

(1) CCmdTarget类是MFC的消息映射基础类,所有需要消息响应功能的MFC类都要继承这个基类。

(2)CWinThread类是MFC中用于封装线程的类。

(3)CWinApp代表应用程序自己,它封装了应用程序的初始化、消息循环。

(4)CWnd类是所有MFC 窗口的基类,它封装了窗口的基本操作,以及窗口对大部分消息的默认响应。

(5)CDocument类是文档对象的基类。

(6)CFrameWnd类往往用于创建应用程序的主窗口。

(7)CObject类是大部分类的基类,它封装了运行时类信息,动态创建和串行化机制。

●MFC六大核心机制

(1)MFC程序的初始化。

MFC程序会首先建立应用程序对象,也就是我们所说的theApp对象,因为全局对象会比main函数先运行,在执行完WinApp的构造函数(构造过程:将自己的this指针分别保存到一个线程指针和一个winapp指针中)后由连接器向程序内自动链接的AfxWinMain函数就将被调用.

以下是MFC库简单的实现:

class CFrameWnd

{

       int Create()

       {

              //注册窗口类 RegisterClass(WNDCLASS)

              //创建窗口 CreateWindow()

       }

       LRESULT WindowProc();//窗口处理函数

}

class CWinApp

{

       BOOL InitInstance()

       {

              CFrameWnd * pWnd = new();

              pWnd->Create();

              pWnd->ShowWindow();

       }

       BOOL Run()//消息循环

}

AfxWinMain()

{

       pApp->InitApplication();//初始MFC内部数据

       pApp->InitInstance();//窗口创建,显示主窗口

       pApp->Run()//消息循环

}
(2)运行时类型识别(RTTI)。

就是程序执行过程中知道某个对象是属于某个类的。

每一个从CObject类派生出的类都维护了一个CRuntimeClass类型变量,然后所有类的CRuntimeClass类型变量构建了一个链表。每一个支持运行时类型识别的类都要定义一个CRuntimeClass静态成员。因为静态成员为所有类对象共享,所以它可以作为类的类型识别依据。同时CRuntimeClass还记录了基类的类型,它的成员函数有类名,对象大小,还有指向基类的CRuntimeClass结构指针,因此还可以用于判断某个子类是否是某个基类。IsKindOf 实现宏:DECLARE_DYNAMIC  IMPLEMENT_DYNAMIC
(3)动态创建。

就是在程序运行时创建指定类的对象

具体实现(原理):先定义默认不带参数的构造函数,因为我们是用CreateObject()动态创建,然后在类的头文件和cpp中加入声明宏和实现宏,这个宏会完成构造出CRuntimeClass对象加入到动态创建类的链表当中,使用时通过RUNTIME_CLASS就可以得到类的运行时类信息,然后再调用CreateObject完成创建。
(4)永久保存(串行化)。
(5)消息映射。

消息处理函数WindowProc收到消息后, 调用OnWndMsg进行消息路由, 它会到相应的子类头文件中查找消息声明宏DECLARE_MESSAGE_MAP()下是否有相应的消息响应函数原型声明;再到子类的cpp中查看是否有相应的消息映射宏.如果有就找到了消息响应函数,完成了消息映射。
(6)消息传递。

●OnDraw和OnPaint

OnPaint()是CWnd的类成员,负责响应WM_PAINT消息,一般用于维护窗口的客户区(例如我们的窗口客户区加一个背景图片),OnDraw()是CVIEW的成员函数,它一般用来维护视图的客户区(例如我们通过鼠标在视图中画图)。OnPaint最后也要调用OnDraw函数,因此我们一般会在OnDraw函数中进行绘制.  

●win32程序的消息响应机制是如何实现的

在Win32程序中,当有消息产生时,操作系统会把这条消息放到应用程序的消息队列中,应用程序通过GetMessage函数从这个队列中取出消息,并通过DispatchMessage 函数把消息交给操作系统,然后调用应用程序的窗口过程函数WndProc进行处理

●MFC中的消息响应机制是如何实现的

实现消息响应在程序中有三处相关信息,函数原型,函数实现和消息映射宏。首先在每个能处理消息的类中定义一个消息映射表.在这个表中,消息与对应的处理函数指针是成对出现的.当有消息传送过来时,先找到这个消息的窗口类,然后调用窗口函数WindowProc里的OnWndMsg进行消息路由,也就是上面所说的消息映射表,程序会搜索这个消息映射表中是否有这个消息,如果有的话就调用对应的消息处理函数,没找到的话就交给基类进行处理。

●WM_COMMAND命令消息处理顺序

它的处理优先级依次是CView大于CDocument,大于CFrameWnd,最后是由  CWinApp处理。

 执行过程

      1 WM_COMMAND发送到程序的顶层

        窗口FrameWnd

      2 FrameWnd获取当前活动视图,

        将命令派发给View

      3 在View中进行消息处理,处理后返回,若没有处理然后

        派发给CDocument.

      4 CDocument进行消息处理, 处理后返回,若没有处理返回

        到FrameWnd, FrameWnd自己进行

        消息处理,处理后返回,若没有处理

      5 派发给CWinApp进行消息处理

●MFC序列化的概念

序列化就是将数据以二进制流的方式写入到文件或者从文件中读取数据的过程。

序列化对象 - 将对象的类信息和成员变量写入到文件的过程。

反序列化对象 - 从文件中读取类的信息创建对象,然后读取成员变量的值赋给对象。

作用:

为了让数据的保存与显示分开,如果直接用普通文件操作也可以,但这样不能照顾到整个MFC,因为文件的话只有字节流,没有数据结构,而序列化的思想是把一个运行期的对象保存到永久性设备中,以便任何时候都可以恢复这个对象的状态,它的实现运用到了MFC的动态创建和运行时类信息的机制。

●PeekMessage和GetMessage的主要区别:

两个函数都是从消息队列中拿消息, GetMessage相当于一个线程同步行为的函数,如果消息队列中没有消息的话,函数会一直等待,然后取出消息后,消息就从消息队列中删除了,而PeekMessage是不管消息队列中是否有消息,函数都会立即返回,它要根据它设置的一个参数决定消息是否从消息队列中取出。一个是取消息一个是查消息。

●WIN32创建窗口程序基本函数

(1)注册窗口类RegistClass(2)创建窗口CreateWindow(3)显示和更新窗口ShowWindow和UpdateWindow(4)创建消息循环GetMessage TranslateMessage把虚拟键消息转化为字符消息 DispatchMessage(5)定义窗口过程函数,里面一般有消息处理switch case

●Windows中的系统消息循环占用CPU的疑问

其实while循环是占用cpu的,只是getmessage它是一个阻塞型函数,当消息队列中没有消息时,它会使线程外于阻塞状态,不被激发,所以它是不占用CPU资源的。

●队列消息与非队列消息

队列消息:如鼠标、键盘消息,它会先保存在消息队列中,通过消息循环派发到各窗口函数去处理。

非队列消息:如WM_CREATE消息,它是直接发给窗口函数处理。

●GDI对象绘图步骤

(1)创建绘图对象CreatePen,CreateSolidBrush或调用GetStockObject获取

(2)调用SelectObject将绘图对象应用到当前设备环境DC中,注意保存当前绘图对象(3)绘图

(4)绘图结束再次调用SelectObject放入旧绘图对象

(5)调用DeleteObject删除刚刚创建绘图对象

●设备上下文DC

DC是一个windows数据结构,它包含了一些设备的绘制属性,DC对象封装了用于画线文本等的windows api,所以我们在绘制时都是要借助于设备DC,把创建好的绘图工具应用到设备环境DC中。

●GDI位图绘制步骤

加载位图LoadBitmap->创建与当前DC匹配的DC,CreateCompatibleDC->将位图放到匹配的DC中,SelectObject-->绘制位图BitBlt和StretchBlt

●当模态对话框点开后,主窗口还能响应处理消息吗?

模态对话框是有自己的消息循环的,它屏蔽的是原始的消息循环,它的本质就是调用窗口过程,进一步调用你的各种消息响应函数,所以无论有多少个消息循环存在,只要有一个消息循环有效,所有的消息响应函数都能被调用,这也是为什么主窗口还能响应消息的缘故。

●MFC的消息分类

(1)窗口消息:如WM_CREATE、WM_PAINT通过直接调用窗口处理函数

(2)WM_COMMAND命令消息:先发送到主窗口,再逐层向子窗口派发

(3)通知消息 (4)自注册消息

猜你喜欢

转载自blog.csdn.net/zhouchunyue/article/details/79271937