MFC学习(五)常见面试题
1:应用程序类
CTestOneApp::InitInstance
可以看做是MFC程序的入口函数,main函数隐藏在这个函数中。实际开发中一般不需要对这个类进行操作,但如果要在建立主对话框之前处理一些数据或者准备工作,就可以把代码添加到这个函数中,主对话框显示之前。
这里有两个比较典型的应用:
1)启动界面之前弹出个登录界面。
2)启动界面之前,弹出一个项目配置界面。
2:对话框类
// CTestOneDlg 对话框类,继承自CDialogEx类。对话框类负责与用户交互,处理用户消息,接收用户输入。
class CTestOneDlg : public CDialogEx
{
public:
// 标准构造函数
CTestOneDlg(CWnd* pParent = NULL);
// 对话框数据
enum { IDD = IDD_TESTONE_DIALOG };
protected:
// 动态数据交换,负责控件与变量之间的关联
virtual void DoDataExchange(CDataExchange* pDX);
protected:
//应用程序句柄
HICON m_hIcon;
//重载初始化对话框
virtual BOOL OnInitDialog();
//定义消息WM_SYSCOMMAND处理函数
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
//定义消息WM_PAINT处理函数
afx_msg void OnPaint();
//定义消息ON_WM_QUERYDRAGICON处理函数
afx_msg HCURSOR OnQueryDragIcon();
//消息映射
DECLARE_MESSAGE_MAP()
};
这个类看出以下几点:
(1)控件与数据关联,可以简单的交给框架
(2)在MFC框架上开发主要是针对消息处理机制
添加一个button,并且添加一个事件后:会有如下变化
PUSHBUTTON "Button1",IDC_BTN_TEST,151,57,50,14 // RC 文件拿这个ID作为控件的标示
#define IDC_BTN_TEST 1001 /resource.h 定义一个ID号。
afx_msg void OnBnClickedBtnTest(); // 事件响应函数
BEGIN_MESSAGE_MAP(CTestOneDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_TEST, &CTestOneDlg::OnBnClickedBtnTest) // 把事件,响应函数, 行为三者绑定到一起
END_MESSAGE_MAP()
void CTestOneDlg::OnBnClickedBtnTest() //事件响应函数
{
// TODO: 在此添加控件通知处理程序代码
}
3 SendMessage和 postMessage 区别
SendMessage : 同步, 返回值表示处理消息后的返回值。
postMessage: 异步,只是把消息放入队列,返回值仅表示post是否正确。
同一个线程内:PostMessage只把消息放入队列,然后通过消息循环Dispatch到达窗口。SendMessage发送消息时,系统直接调用目标窗口的消息处理程序,并将结果返回。
不同线程:最好用PostThreadMessage代替PostMessage。 SendMessage发送消息到目标窗口所属线程的消息队列,然后发送的线程等待,直 到处理完。
4 onpaint() 和 ondraw()
窗口改变后,产生无效区域,需要重绘,windows会发送WM_PAINT通知客户区变化,客户区的重绘需要自己完成。
CVIew派生自CWnd, 而OnPaint()是CWnd 的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员,没有响应消息功能。
要想在屏幕上绘图,首先要建立设备环境DC,DC是一个数据结构,包含输出设备的绘图属性的描述。MFC提供了CPaintDC 类和CWindowDC 类
实时响应,CPaintDC支持重画。
当视图无效时(大小,移动,被遮盖)Windows将WM_PAINT消息发送给它。 该视图的OnPaint处理函数通过创建CPaintDC类的DC对象来响应
该消息并调用视图的OnDraw成员函数,通常不用重写ONpaint函数。
void CView::OnPaint()
{
CPaintDC dc(this);
OnPreparDC(&dc);
OnDraw(&dc); //调用了OnDraw
}
OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。
void CMyView::OnDraw( CDC* pDC )
{
CMyDoc* pDoc = GetDocument();
CString s = pDoc->GetData(); // Returns a CString
CRect rect;
GetClientRect( &rect );
pDC->SetTextAlign( TA_BASELINE | TA_CENTER );
pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );
}
5 强制重画窗口
InvalidateRect(&Rect) :使得指定的区域无效。
Invalidate():使得整个窗口无效,形成无效矩形。
UpdateWindow(): 立即发送WM_PAINT,不过在它发送前,先调用GetUpdateRect(hWnd,NULL,TRUE)看有无可 绘制区域,如果没有则不发送消息。
RedrawWindow()是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。
6 CView 与 CDcoument关系
CVIew 有一个成员变量CDocument, 指向相关的Document.
CView 与 Document交谈的过程:
A:使用者在View做动作,取得Document指针,更改资料内容。
B: View调用Document的UpdatedAllViews.
C: 其他的view的onUpdate() 被调用, 各种view的画面就更新了。
D:CVIew:Onupdate()被调用,代表通知他:document的内容已经改变了,你更新画面吧。 也可以用一种低效率的方式: invaalidate(TRUE),把窗口
整个设为重绘区,产生WM_paint,再让Cview::OnDraw()。
7 你熟悉预编译指令么?条件编译是用来做什么的?你会写么?
预编译指令: 在编译之前做一些事。
#include : 文件包含
#define: 宏替换
# if, #ifndef, #ifdef, #endif, #undef : 条件编译。
#pragma :布局控制。 主要是设定编译器的状态。 #pragma once #pragma pack(n)
8 C++ 中的string/WString
string就是*char, wstring wchar_t, 用来处理中文,是宽字符。
9 MFC用的是Unicode
10 stdafx.h 头文件预编译
把一个工程中使用的一些MFC标准头文件(windows.h Afxwin.h)预先编译,以
后该工程编译时,不再编译这部分头文件。
11 MFC包含几种类型程序?其中MFC应用程序又包含哪几类
单文档(画图),多文档(vs 2015), 对话框.
12 MFC的消息机制
MFC使用一种消息映射机制来处理消息,一个消息与消息处理函数一一对应的消息映射表,以及消息处理
函数的声明和实现代码。当窗口接收到消息的时候,会到消息映射表中查找消息的处理函数,然后消息处理函数进行
处理
13 消息映射
Windows程序都维护有自己的消息队列,保持队列消息(当然也有非队列消息,他们直接发给窗口),并用消息循环
对消息进行处理。
消息循环首先通过GetMessage取得消息并从队列中移除,对于加速键,会调用TranslateAccelerator函数,对其进行
翻译和处理,如果处理成功就不在调用translateMessge.
否则进行消息的转换和派发。让目的窗口的窗口过程来处理消息。
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现。
14 自定义消息
A、自定义消息号:#define WM_CCTRY_MSG (WM_USER+100)
B、在头文件中添加消息响应函数的声明:afx_msg LRESULT OnCcTryMsg(WPARAM wParam, LPARAM lParam);
C、在CPP文件中添加消息响应函数的实现:
LRESULT CXXXDlg::OnCcTryMsg(WPARAM wParam, LPARAM lParam) {
//相关代码;
}
D、在 BEGIN_MESSAGE_MAP 与 END_MESSAGE_MAP 之间加入消息的映射代码:ON_MESSAGE(WM_CCTRY_MSG, &CDlgTestDlg::OnCcTryMsg)
然后在想触发消息的地方:sendMessage(),就可以。
15. MFC的对话框的种类,各自怎么使用?及相关函数。
模态对话框和非模态对话框。
模态对话框:工作时其父窗口无效。 DoModal();
非模态对话框: dlg.Create(;)
15 进程间通信
管道(匿名): 半双工。只适合父子进程之间通信。传输的是流。所以进程间通信必须约定好数据格式。创建管道时,
分配一个页面作为数据缓冲区,进程对缓冲区进行读写。
有名管道:非父子进程也可以通信,有传输格式。
消息队列:放在内核中的消息链表,
信号量:
共享内存:分配一块能被其他进程访问的内存。共享的内存被映射到两个进程的虚拟空间。但是需要自己提供同步机制。
信号量,互斥锁都可以。
这个效率最高,管道和消息队列需要在内核和用户空间数据拷贝。
16 MFC程序的初始化:http://www.jizhuomi.com/software/267.html
建立MFC窗口很容易,只用两步:
从CWinApp派生一个应用程序,然后创建应用程序对象。initInstance()里面创建窗口就行。
WinMain()函数:
InitInstance 是程序入口点,是虚函数,应用程序初始化(其实也winmain函数调用它的)
注意: 全局变量的的构造函数在main函数之前执行。
基本流程:
注册窗口:注册后才能从系统中找到它,获得句柄,然后向窗口发送消息。
创建窗口:
显示更新窗口:show, update()
消息循环:
回调函数:
17 消息映射机制的原理及实现。
在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,将消息与消息处理函数绑定。当处理消息的时候到这个表中去查就行了。
BEGIN_MESSAGE_MAP() 宏中定义。
18 ASSERT() ,是函数还是宏
预处理宏, assert(expr), 先计算表达式expr, 如果为假,那么它会输出信息并终止程序执行。
如果用if else实现同样功能的话,就会从函数开始括到函数尾。
assert是宏不是函数,定义在cassert头文件中。
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销;
完成调试后,不必从源代码中删除assert()语句,因为宏NDEBUG有定义时,宏assert()的定义为空,
即可以通过在包含#include assert.h>或#include< csaaert >的语句之前插入 #define NDEBUG 来禁用assert调用:
assert只有在Debug版本中才有效,如果编译为Release版本则被忽略(程序一般分为Debug 版本和Release 版本,
Debug 版本用于内部调试,Release 版本发行给用户使用);
assert用法注意:
A:不要一起判断多个条件,否则不知道是哪个有问题。
B:不能改变变量的值、
C: assert语句后面空一行。
19 MFC消息三种类型
在MFC应用程序中传输的消息有三种类型:窗口消息、命令消息和控件通知。
(1)窗口消息:WM_XXX,除WM_COMMAND之外,所有以WM_开头的消息
窗口消息(Window Message)一般与窗口的内部运作有关,如:创建窗口、绘制窗口和销毁窗口等。通常,消息是从系统发送到窗口,或从窗口发送到窗口。
(2)命令消息:WM_COMMAND
命令消息一般与处理用户请求相关,当用户单击一个菜单项或工具栏时,命令消息产生,并被发送到能处理该请求的类对象(如:装载文件、编辑文本和保存选项等)。
(3)控件通知:有多种格式
通常,控件通知在某些重要事件发生时,由控件窗口发送到父窗口,如打开一个组合框。控件通知为父窗口进一步控制子窗口提供了机会。例如,打开一个组合框时,父窗口可以用组合框初建时得不到的消息填充它。
BN_XXXX是CButton产生的消息,EN_XXXX是CEdit产生的消息,等等。
现在就可以知道为什么有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。
ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM.
ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID, 事件种类…(所有的都在MFC内部解决了:),当然方便了。
ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。
20 MFC绘图有哪几类DC?各自的类名,及区别
设备描述表(DC)是Windows中的一种数据结构,它包含GDI需要的所有关于显示界面情况的描述字段,包括相连的物理设备和各种各样的状态信息。从而提供了应用程序设计的平台无关性。
HDC:设备上下文句柄(可以理解为指向DC结构的指针),它指向一块描述设备的相关的内容的内存块。
CDC:是MFC里面的一个类,且这类封装了几乎所有关于HDC的操作,由于类的内部包含一个m_hWnd的句柄,
所以,CDC封装的操作(函数)与SDK平台中与关于HDC的操作都缺少一个指向设备上的句柄(不是没有,而是这个句柄在被封装起来)。
(1)、HDC到CDC的转换:
方法一: 此方法在设备结束时不会销毁原来的资源(即:hDC,hBitmap)
CDC *pDC = CDC::FromHandle(hDC);
方法二:此方法在设备结束时会销毁原来的资源(即:hDC,hBitmap)
CDC dc;
dc.Attach(hDC);
(2)、CDC到HDC的转换:
CDC dc;
HDC hDC;
hDC = dc.GetSafeHdc();
CPaintDC:
CClientDC:
CWindowDC:
21: MFC的线程有哪几类?相互有什么区别?各自的创建方法是什么
两种:界面线程:有消息循环,能响应用户的界面操作,必须继承自CWinThread.
工作线程:
AfxBeginThread(RUNTIME_CLASS(MyThread)); 二者的参数有区别。
22 MFC常用控件?通用对话框?
23 MFC的文件类?文件查找类?
MFC学习(五)常见面试题的更多相关文章
- Selenium学习之==>常见面试题
转自:http://www.imdsx.cn/ 一.selenium中如何判断元素是否存在? expected_conditions模块提供了多种校验方式,我常用的一种是presence_of_ele ...
- java常见面试题及答案 1-10(基础篇)
java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...
- Mybatis常见面试题
Mybatis常见面试题 #{}和${}的区别是什么? #{}和${}的区别是什么? 在Mybatis中,有两种占位符 #{}解析传递进来的参数数据 ${}对传递进来的参数原样拼接在SQL中 #{}是 ...
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- java常见面试题及答案
java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...
- HTTP、TCP、IP协议常见面试题
前言:在看面试题之前,先了解一下基本定义. HTTP.TCP.IP协议基本定义 HTTP: (HyperText Transport Protocol)是超文本传输协议的缩写,它用于传送WWW方式的数 ...
- python爬虫常见面试题(二)
前言 之所以在这里写下python爬虫常见面试题及解答,一是用作笔记,方便日后回忆:二是给自己一个和大家交流的机会,互相学习.进步,希望不正之处大家能给予指正:三是我也是互联网寒潮下岗的那批人之一,为 ...
- python爬虫常见面试题(一)
前言 之所以在这里写下python爬虫常见面试题及解答,一是用作笔记,方便日后回忆:二是给自己一个和大家交流的机会,互相学习.进步,希望不正之处大家能给予指正:三是我也是互联网寒潮下岗的那批人之一,为 ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- 【javascript常见面试题】常见前端面试题及答案
转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...
随机推荐
- ng2 学习笔记(二)表单及表单验证
在上一篇文章中提到了表单,只说了表单的数据绑定,这一篇文章主要讲一下表单验证,为什么把表单单独拿出来学习,主要是因为,表单是商业应用的支柱,我们用它来执行登录.求助.下单.预订机票.安排会议,以及不计 ...
- Vector3函数理解-计算两向量之间的角度
1.已知两个向量dirA,dirB.Vector3 dirA = new Vector3(-1,1,0); Vector3 dirB = new Vector3(-1,1,1);2.使向量处于同一个平 ...
- GAN的原理入门
开发者自述:我是这样学习 GAN 的 from:https://www.leiphone.com/news/201707/1JEkcUZI1leAFq5L.html Generative Adve ...
- mongodb底层存储和索引原理——本质是文档数据库,无表设计,同时wiredTiger存储引擎支持文档级别的锁,MMAPv1引擎基于mmap,二级索引(二级是文档的存储位置信息『文件id + 文件内offset 』)
MongoDB是面向文档的数据库管理系统DBMS(显然mongodb不是oracle那样的RDBMS,而仅仅是DBMS). 想想一下MySQL中没有任何关系型数据库的表,而由JSON类型的对象组成数据 ...
- day5-python中的序列化与反序列化-json&pickle
一.概述 玩过稍微大型一点的游戏的朋友都知道,很多游戏的存档功能使得我们可以方便地迅速进入上一次退出的状态(包括装备.等级.经验值等在内的一切运行时数据),那么在程序开发中也存在这样的需求:比较简单的 ...
- shell编程-数组
#!bin/bash/ A=(a b c hello) echo ${A[*]} echo ${A[@]} ]} ]} ]} ]} ]}echo ${#A[*]} #测数组长度方法1echo ${#A ...
- 【dlbook】机器学习基础
[机器学习基础] 模型的 vc dimension 如何衡量? 如何根据网络结构衡量模型容量?有效容量和模型容量之间的关系? 统计学习理论中边界不用于深度学习之中,原因? 1.边界通常比较松, 2.深 ...
- eclipse 不能启动虚拟机
在eclipse文件下有个eclipse.ini文件打开它.现在如果没有-vm 这个参数那么就在最后新起一行写上 -vm+空格+参数 参数是你安装的jdk目录比如我的 -vm d:/java/jdk1 ...
- C++中关于标准输出流cout中使用递增运算符的问题
今天听同学提起一个问题,在C++中运行下面的语句会得到什么结果: ; cout << a++ << a++ << a++; 起初我个人想当然地认为会输出012,然而 ...
- [置顶]
【机器学习PAI实践五】机器学习眼中的《人民的名义》
一.背景 最近热播的反腐神剧"人民的名义"掀起来一波社会舆论的高潮,这部电视剧之所能得到广泛的关注,除了老戏骨们精湛的演技,整部剧出色的剧本也起到了关键的作用.笔者在平日追剧之余, ...