欢迎光临散文网 会员登陆 & 注册

【滴水基础】5.MFC(3)

2023-06-04 20:54 作者:沙漠里的鲸  | 我要投稿

第十:GDI基础概念和MFC的CDC类

#GDI图形设备(Graphics Device InterFace)

---和Win32Api类似,为应用程序提供了可调用的多种服务,这些服务构成了强大、通用的图形编程语言

#DC图形描述表(同时表示设备上下文)

---Windows程序在屏幕、打印机、其它输出设备上画图时,并不是将像素直接输出到设备上

---而是将图先绘制到设备描述表(内存设备dc)表示的逻辑意义上的显示平面上去

---它是Windows中的一种数据结构,包含了GDI需要的所有有关于显示平面情况的描述

---早期的图形开发,是针对具体的设备开发(如:根据打印机厂家提供的不同接口开发不同的代码),需要适配不同的显卡,造成开发者困难

---Windows通过驱动管理,将设备接口细节隐藏在OS内部,我们只需要针对一个:公有的虚拟设备DC

#MFC不同场景下的DC类

---MFC的CDC类,将DCHDC(句柄:可以操作所有DC有关的GDI函数)的GDI函数封装到了一起,派生了四个不同场景的DC类,以下是常用的3个

---注意:OnPaintON_WM_PAINT消息的响应函数,当窗口进行某些特定操作引起窗口重绘时,会发送WM_PAINT消息

---系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时等等

---大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和InvalidateRgn函数来完成的。

---ON_WM_PAINT可以捕获此消息,并自己调用OnPaint()函数来实现对某些要素图形的重新绘制

---当然,视频里面省略了一个

#在消息响应函数的基础上,区分Win32Api和MFC

---如果是传统的Win32Api的调用,分为设备对象(窗口),设备上下文(内存),图形对象

---通过设备对象获取窗口的设备上下文,然后自定义图形对象

---最后,将图形对象和设备上下文关联,调用WinApi进行绘图

---绘制图形如下(这个只能显示一次,而窗口是不停的绘制、渲染)
---这也是为什么上面MFC要利用dc对象来进行画图

#MFC的窗口句柄

---哪如何获得窗口类的自己的句柄呢?有如下方法:
---1、this->m_hWnd;             //成员变量
---2、GetSafeHwnd();             //成员方法
---3、AfxGetMainWnd()->m_hWnd;

#在MFC里面模拟Win32Api的调用

---Hello.h

---hello.cpp:为什么OnPaint()里面调用:BeginPaint(m_hWnd,&ps)和EndPaint(m_hWnd,&ps)?

---BeginPaint函数的作用是告诉Windows系统,要开始向显示卡输出内容了,把这次显示的操作请求放到系统显示队列里。

---由于系统上的显示卡往往只有一个,那么这种资源是独占的,所以操作系统会让显示操作线性化,保证每个窗口的显示是独立进行的,而不是A窗口显示一部份,或者B窗口显示一部份,而是A窗口显示完成后再让B窗口显示

---因此,BeginPaint函数就是跟操作系统说,我需要显示了,你安排好吧。当BeginPaint返回时,就获取到系统的显示资源句柄,这样就可以调GDI一大堆函数来操作了

---显示完成后,一定要记得调用函数EndPaint,因为使用BeginPaint函数请求了独占的显示资源后,如果不释放回去,就会让其它程序永远获取不到显示资源了,这样系统就死锁了

---应用程序除了响应WM_PAINT消息外,不应该调用BeginPaint

---效果如下

---点击鼠标左键

---上面是Win32Api进行的操作,如果替换为MFC封装的DC类

---效果如下

#设备描述表的属性(重要)

---例如,修改字体的颜色

---效果如下

#鼠标左键点击,画一个黄色的矩形

---pen(1,2,3)相当于CreatePen(1,2,3)

---代码如下

---效果如下

---总结

第十一:WindowsGDI

#GDI的映射模式

---映射模式是设备描述表的属性,用于确定逻辑坐标值(内存)到设备坐标值(显示屏)的转换(设备坐标值:窗口中相对应的像素位置

---传递给CDC(CDC封装了HDC和DC有关的函数)输出函数的逻辑坐标值,然后被转换为设备坐标值

---通过CDC::SetMapMode来进行设置逻辑设备到设备坐标的映射方式

#映射模式的nMapMode取值与含义

符号常量                 数字常量             x方向           y方向         逻辑单位的大小
MM_TEXT                     1             向右(默认)向下(默认)             像素
MM_LOMETRIC            2                    向右           向上                     0.1 mm
MM_HIMETRIC             3                    向右           向上                     0.01 mm
MM_LOENGLISH          4                    向右           向上                     0.01 in
MM_HIENGLISH           5                    向右           向上                     0.001 in
MM_TWIPS                   6                     向右             向上                 1/1440 in  
MM_ISOTROPIC           7                     自定义       自定义                     自定义
MM_ANISOTROPIC      8                     自定义         自定义                   自定义

#设备空间下的坐标

---1.客户区坐标 2.屏幕坐标 3.全窗口坐

#GDI坐标空间

---Windows程序利用坐标空间转换来对图形输出进行缩放、旋转、平移、斜切、反射等

---坐标空间是一个平面的空间,通过互相垂直的XY轴来定位二维对象

#Win32Api使用4种坐标空间

---在窗口的ON_WM_PAINT()消息的响应函数OnPaint()中

---绘制圆形

---这里的映射模式是默认的以像素为映射:MM_TEXT

---如果将映射模式设置为:MM_LOMETRIC(修改的是逻辑坐标的单位)

---一个逻辑单位:0.1毫米,x和y轴方向:x+y-

---效果如下

---映射模式的修改优点:与物理设备无关如显示器,不同的屏幕具有不同的分辨率

---获取客户区的逻辑坐标,使得圆形铺满整个窗口

---圆形可以铺满整个窗口,但是一旦放大窗口,就会变成椭圆

---可以通过修改映射模式进行自适应,发现放大了之后,圆也不会变成椭圆

---将映射模式改为:MM_ANISOTROPIC,发现逻辑单位还是1个像素点,但是放大之后,就会变成椭圆

---通常情况下SetWindowExt()函数和SetViewportExt()函数成对调用(我这里在网上找了一个例子)

---在X轴方向,每个逻辑单位有 1024 / 10240 个像素,

---而在Y轴方向,每个逻辑单位有 768 / 7680 个像素

#总结

#对应鼠标左键点击消息ON_WM_LBUTTONDOWN()对应的响应函数:OnLButtonDown(UINT nFlags,CPoint point)

---这里就是在以鼠标点击的点为源点(设备坐标),然后画矩形

---效果如下

---我们设置映射模式,将原本的默认的映射,改为:MM_LOMETRIC

---:一个逻辑单位=0.1毫米,x轴y轴方向:X+Y-

---效果如下:

#先设置CMianWindow主窗口的范围(0,0,515,540)

---发现画一个(0,0,500,500)的圆形正好在中间

---现在更改窗口的原点,改为逻辑坐标的(100,100)

#窗口和视口的绘图

---窗口中的坐标都是逻辑坐标,视口中的坐标都是设备坐标。我们的绘图语句(dc的成员函数)中用的坐标都是逻辑坐标

---这里窗口的原点,变成了逻辑坐标的(100,100),截取了一个小正方形,并且会补充一部分的空白

--而窗口到视口的映射方式没有变化,所以显示是部分的圆

---如果改为

---效果如下圆形直接显示完全

---背后的原理如下:先创建窗口,然后在窗口中绘制(100,100,500,500)的圆形

---在逻辑坐标画好之后,截取(100,100)为原点的部分

---更改视口

---效果如下:

---原理分析:将窗口的映射到视口上,由于在逻辑坐标上,窗口是完整的,所以圆形不会缺失(大小:500,500)

---但是视口上,只有(400,400)来接受映射会舍弃一部分,所以视口原点在原来的视口基础上,变成了原来视口的坐标位置的(100,100)开始

---总结:

---要更改 窗口/视口 原点,就在原来 窗口/视口 坐标系的基础上,进行 窗口/视口原点定位

---然后进行投影,没有投影到的部分,就是空白区域

#页面控件到设备空间的转换

---根据映射方式来确定绘图操作单位大小的一种度量转换

第十二:GDI绘图

#常用的绘图函数

---:MoveTo:在画线前设定当前的位置(指定起始)

---:LineTo:从当前位置画1条线到指定位置(指定指定终止)

---:Polyline:将一系列的点用线段连接起来(无需指定起始位置)

---:PolylineTo:从当前位置开始,将一系列点用线段连接起来(需要指定起始位置)

---:Elipse:画圆或者画椭圆

---:Rectangle:画一个带直角的矩形

---:FillRect:用指定画刷填充矩形

---:Draw3dRect:实现3D立体感

---效果如下

---也可以通过Polyline将一系列的点进行连接

---当然也可以PolylineTo函数,需要设定起始位置,但是和Polyline没有本质的区别

---效果如下

---系统中的画刷、画笔、字体等,可以自己创建并设计,也可以使用系统内置的

---CreateStockObject表示使用系统内置,LTGRAY_BRUSH是一个内置宏

---Windows的系统预定义的画刷如下

---CreateStockObject的优点:无需用dc.SelectObject()去更换画刷对象

---效果如下:

#如果鼠标点击在矩形内,就修改窗口名称

---效果如下,点击矩形内,窗口名改为:yes,点击其它区域,窗口名:no

---如果想改变矩形边框的颜色,风格,可以使用pen

---对于画笔、画刷等图形对象,在MFC中GDI的函数中可以使用:SelectObject()函数加载,并且返回了原来的图形对象,可以在后面加载原来的图形对象

---为什么要保存原来的图形对象:因为GDI没有异常机制,载入自定义的pen之后,在退出的时候,先调用的默认pen的析构函数,再调用dc的析构函数

---但是dc里面存在的是自定义的pen,而默认的pen已经优先释放了,所以会产生异常

---设置字体的大小,风格

---效果如下

---更大范围的更改字体:通过LOGFONT结构体来进行更大范围的字体的传参

---效果如下:

---带阴影的字体:

---效果如下

#作业

---用GDI绘制一个excel: Draw3dRect; FillRect; 填充之后画像

---注意我的主窗口大小

---思路:先两点连线,画出表格

---然后自定义画笔,画刷,填充横轴、纵轴的区域

---效果如下:

第十三:鼠标消息

#Windows鼠标消息

---Windows有20多种不同的消息,用来报告与鼠标有关的输入事件

---这些消息分为:客户消息非客户消息,我们只需要关注客户消息(知识点:理解客户消息和非客户消息)

#客户区域的鼠标消息

#按下鼠标左键输出鼠标点击的坐标(注意:point是物理的设备坐标

---效果如下:

#鼠标移动并且按下鼠标左键才能显示坐标

---定义的鼠标消息

---定义消息映射

---定义移动鼠标的消息响应函数

---效果如下:需要同时按3个键盘

#窗口的非客户区消息

---定义非客户区域的消息映射

---重写映射函数

---效果如下:只有在非客户区域才能接受消息

---自定义部分非客户区的消息处理

---只有点击系统菜单,才改变窗口的名字

#窗口在接收到客户、非客户区消息之前,先接受到:光标的屏幕坐标(很重要)

---通过 ON_WM_NCHITTEST() 确定光标在客户区 or 不在客户区

---在BEGIN_MESSAGE_MAP中添加ON_WM_HITTEST()

---然后添加头文件,重写相应的响应函数

---发现可以像非客户区域一样,拖动客户区区域

#鼠标位置画直线(注意不能和上面的将客户区改为非客户区的一起,不然只能拖到窗口)

---注意,在两个消息处理函数之间,需要通过全局的CPoint来传递鼠标的位置

---然后通过OnLButtonDown来进行初始坐标的传输

---通过SetCapture/GetCapture来确保鼠标的位置被当前窗口捕获(即使在窗口之外)

---利用OnLButtonUp来进行绘图操作

---效果如下

---作业1:鼠标画一条红色的直线(思路:自定义画笔)

---效果如下

---作业2:Ctrl+鼠标左键画一个矩形

---效果如下:特点是鼠标在窗口外面,任然可以画

---作业3:鼠标右键画一条黄色的线条(非直线)

---思路:捕获鼠标光标滑动的地址,然后将这些点通过直线连接起来,从宏观上来看就是曲线

---思路是这样,但是好像原点都是按下的初始点

---但是我记得LineTo之后,原点是会改变的,不知道为啥不行

第十四:键盘消息

---通过给拥有输入焦点的窗口发送:WM_KEYDOWNWM_KEYUP 消息

---来报告按钮是按下还是松开的事件,这些被称为按击键消息

---除了 ALT F10 以外的所有按键都产生按下/抬起的消息

---而 Alt F10系统键,对 Window 具有特殊的意义

#键盘消息

---在BEGIN_MESSAGE_MAP中,添加: ON_WM_KEYDOWN()

---部分的虚拟键代码(VK_CANCEL代码是一个虚拟键码,它包括同时按下两个键(Ctrl-Break))

---Backspace、Tab、Enter、Esc和空格——通常用于Windows程序。不过,Windows一般用字元讯息(而不是键盘讯息)来处理这些键

---Windows程序通常不需要监视Shift、Ctrl或Alt键的状态

---重写消息响应函数

---通过调试模式运行,发现Ctrl对应的十进制代码,以及之前的状态都是抬起

---但是一直按却没有1的出现

---在DeBugView中一直按下Ctrl也没有出现1,奇怪

#获取区分大小写的键盘消息,在消息映射中添加:ON_WM_CHAR()

---重写映射函数

---效果如下:

# ON_WM_CHARON_WM_KEYDOWN 的区别

---ON_WM_CHAR是通过TranslateMessage翻译之后,转换为ASCII码

---不经过翻译是无法识别按键的大小写

---当然,也可以判断Shift键的状态来判断大小写

---视频里面'VK_A'不加''的话编译不通过,但是加了''在调试的时候看不到输出。不知道问题出在哪里?

#设置键盘消息的钩子函数:SetWindowsHookEx

#钩子函数的定义

---钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的

---当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

----钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息

---这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递

#钩子函数的原理

---每一个Hook都有一个关联的指针列表,称之为钩子链表

---这个列表的指针指向钩子的各个处理子程序

----当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程

---最近安装的钩子放在链的开始,而最早安装的钩子放在最后,后加入的先获得控制权

---SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子

----线程钩子用于监视指定线程的事件消息,一般在当前线程或者当前线程派生线程内---

---系统钩子监视系统中的所有线程的事件消息。因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL)

---系统自动将包含“钩子回调函数”的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程

---几点说明:

(1)如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。

(2)对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数

(3)钩子特别是系统钩子会消耗消息处理时间,只有在必要的时候才安装钩子,在使用完毕后要及时卸载

#挂一个全局的键盘钩子(系统钩子

---选择静态链接库(VC6的版本太老了,只能选择静态链接库)

---生产的静态链接库的HOOK函数如下

#思路:1.做一个导出函数StartHook(),由HelloMFC调用2.安装一个鼠标Hook,将鼠标消息再传输给主程序

---在HelloMFC的hello.cpp的OnKeyDown消息响应函数中,调用SetWindowsHookEx()函数,截获发送给键盘消息响应函数的键盘按下消息

---在HOOKDLL.cpp中设置具体的钩子的子程序

---设置钩子的类型为低水平的键盘钩子:WH_KEYBOAD_LL,可以看到右边是对应的钩子的处理函数地址LowLevelKeyboardProc

---WH_KEYBOAD_LL的处理函数如下:

---如果 nCode 小于零,则挂钩过程必须返回 CallNextHookEx 返回的值
---如果 nCode 大于或等于零,建议调用 CallNextHookEx 并返回返回的值

---在CallNextHookEx的功能:可以将钩子信息传递到当前钩子链中的下一个子程,一个钩子程序可以调用这个函数之前或之后处理钩子信息。

---在HOOKDLL.cpp文件中,设定导出函数StartHook()

---1.先获取窗口句柄 2.创建键盘HOOK,定义HOOK处理函数 3.在HOOK处理函数中,将hook后的信息,传递给钩子链的下一个子钩子

---在HOOKDLL.def将定义的StartHook函数进行导出

---将HOOKDLL.dll拷贝到HelloMFC的根目录(这里是动态链接库)

---在HelloMFC中,对按下F2的键盘消息,设置键盘钩子

---在hello.h中定义函数StartHook()

---自定义Hook函数,本质是调用DLL中的StartHook函数

---传入当前窗口的句柄(MFC封装了,但是源代码封装了m_hWnd

---在键盘按下消息响应函数,按下F2键,就调用HOOK键盘的消息

---HOOK成功就修改窗口名称

---效果如下

----但是我在消息响应函数里面弹窗,发现没有报错,但是F2没有进行弹窗

---而且视频里面也是在HOOKDLL.dll的hook处理函数进行判断的(不知道为什么不能再消息响应函数里面进行MessageBox)

---视频里面是之间在Hook的处理函数里面LowLevelKeyboardProc函数,存在3个参数

---不管HOOK成功与否,都将调用CallNextHookEx将消息传递给钩子链的下一个HOOK

---KBDLLHOOKSTRUCT的内容如下

---修改HOOK处理函数,对拦截的消息进行预先处理

---将更新后的HOOKDLL.dll重新复制到HelloMFC,并且运行

---emmm,我这里还是没有消息弹窗,难受

#通过自定义消息,如果HOOK成功,向主窗口发送自定义消息,然后主窗口处理

---在HelloMFC中使用:ON_MESSAGE自定义消息,传参为自定义的消息类型消息的响应函数

---然后窗口接到了消息,根据第一个wParam参数,判断是否为键盘按下消息,如果是的话就弹窗

---我这里存在弹窗不能出现的问题,猜测是W11是不支持吧,建议开个虚拟机在Xp上运行VC6

---效果如下


第十五:MFC对话框

---MFC的对话框就是一个窗口,不仅可以接受消息,还可以被移动和关闭,还可以在它的客户区域进行绘图

---我们可以把它看成是一个大容器,在上面能够放置各种各样的控件,使得程序的支持用户输入的手段更加的丰富。

---创建一个MFC的exe文件

---选择Dialog框(基本对话框)

---去掉所有的添加,只创建一个基本的Dialog框(基本对话框)

---不生成源文件备注,使用静态的DLL

---默认生成以下文件

---在#include "stdafx.h"之前的默认都不编译,所以111不会报错

---也就是说:#include "stdafx.h"是MFC的编译的第一行

---我们可以看到:theApp就是之前全局变量CMyApp

---InitInstance就是之前的WinMain主函数

---在里面也可以看到消息映射

---点击DialogTest.rc是一个资源脚本

---可以在rc里面添加一些版本信息等

---可以在项目的目录下面查看DiaLogTest.rc的部分具体代码

---可以看到IDD_DIALOGTEST_DIALOG 的风格、标题、字体、消息等等

---有两个按钮,确定、取消“在这里设置对话控制”

---点击IDD_DIALOGTEST_DIALOG右边的窗口图,然后查看属性

---发现对应的DiaLogTest.rc的内容在这里凸显

---向Dialog框,添加一个控件

---发现在DiaLogTest.rc里面也添加了一行按钮的代码

---在DiaLogTestDlg.cpp文件中,存在着DoDataExchange()的函数

---这个是添加相应按钮的响应函数,这个函数是一种动态绑定技术

---什么是动态绑定技术?

---添加一个名为:IDC_EDIT1的编辑框

---添加按钮的消息响应函数,使得按下按钮,改变编辑框里面的值

---代码如下

---发现编辑框的内容发生了改变

---也可以在:类向导 > 成员变量 > IDC_EDIT1 (控件ID) >添加成员变量

---相当于原来是通过GetDlgItem(IDC_EDIT1)来获取IDC_EDIT1的函数地址(指针)

---现在通过给Dialog框的控件创建成员变量,进而更好的调用方法

---通过成员变量,调用方法来改变编辑框的值

---效果如下

---可以看到,这里的动态绑定,添加了控件的绑定:IDC_EDIT1和m_edit1进行绑定

---我们操作m_edit1就会改变IDC_EDIT1的控件

---在类向导里面的成员变量,删除IDC_EDIT1的成员变量

---添加成员变量和m_edit1绑定,添加Value(之前是Control),Value的类似是CString(字符串数组)

---定义m_edit的长度为255

---发现动态绑定的地方发生了改变

---在OnButton1控件的映射函数修改m_edit1的值,赋值为一个字符串

---发现编辑框控件的值同样发生了改变,之前相当于获取了IDC_EDIT1函数地址(指针),然后调用方法修改编辑框的值

---这里是将medit1数组和IDC_EDIT1关联,然后更新编辑框控件的值

---UpdateData(FALSE)和UpdateData(TRUE)的区别

---例如,在初始化的时候将空间的内容传递给edit1

---在显示的时候,不点击Button1,IDC_EDIT1编辑框也会显示test

---在DoModal()里面:就是一个模态对话框

---在DoModal()里面实现了Dialog框的绘制,输出、消息循环

---并且默认了两个按钮:确认取消,分别对应下面的IDOKIDCANCEL

---在int nResponse = dlg.DoModal();处下断点,然后点击确定,发现nResponse的值为1

---同样,点击取消,nResponse的值为2

---可以看到不同的按钮对应不同的值

---为确定按钮添加消息响应函数

---发现确定按钮调用的是CDialog::OnOK();,在这里下断点进去查看

---注意,这里是先进入BOOL CDiaLogTestApp::InitInstance()

---然后在    int nResponse = dlg.DoModal();创建、显示Dialog框,并设置消息循环

---然后再按下确定按钮,根据nResponse的值,来调用CDiaLogTestDlg::OnOK()

---发现CDiaLogTestDlg::OnOK()的本质是调用EndDialog(IDOK);方法

---如果是CDiaLogTestDlg::IDCANCEL()就调用EndDialog(IDCANCEL);

---模态对话框(就是Dialog框)会造成一个结果:对话框卡在屏幕,双击rc

---插入一个新的Dialog框

---新建的Dialog框创建一个名为CDialog1的新类

---然后发现CDialog1类里面存在2各确定和取消的按钮

---而且在FileView路径下

---在DiaLogTest.cpp中,#include "Dialog1.h"

---然后在OnButton1()的响应函数里面

---发现带点击OnButton1,就会弹出第二个Dialg对话框

---而且只能将模态对话框关闭之后,才能进行主窗口的操作(可以当作验证,如果不能通过密码验证,就不能使用主窗口)

---如果是非模态对话框,就不能通过DoModal函数

---但是这样创建的窗口,只会一闪而过(原因是在void CDiaLogTest2Dlg::OnButton1()
函数结束之后,dlg对象就会被释放掉)

---解决方法:采用在堆中创建对象(new一个对象)

---但是存在问题:new了对象,但是没有释放对象

#解决方法1

---在Dialog的取消控件,添加响应函数

---将原来的CDialog::OnCancel();删除,替换为销毁窗口

---为什么要改写呢?是因为:这里原本的方法是对应的DoModal的模态对话框

---这里是非模态对话框,所以需要重写取消的函数,删除对话框

---为Dialog1的PostNCDestroy(在视图窗口关闭时最后调用的成员函数,即删除视图对象)消息添加消息响应函数

---由于DestroyWindow();最后会产生PostNcDestroy()消息

---重写PostNcDestroy()消息,在这里添加销毁堆内存中new的对象

#解决方法2(更简洁):

---在CDiaLogTest2Dlg.h中,首先#include "Dialog1.h",其次CDialog1* dlg;

---OnButton1() 的消息响应函数不需要声明CDialog1的指针

---在CDiaLogTest2Dlg的DestroyWindow消息中,建立消息响应函数

---销毁窗口

---DestroyWindow和PostNcDestroy的区别

---综合以上:先调用DestroyWindow,在此间会有OnDestroy消息,接着窗口被销毁

---于是DestroyWindow返回TRUE

---然后是OnNcDestroy消息,之后再调用PostNcDestroy

#模态对话框:

---产生一个窗口卡在前一个窗口,用dlg.DoModual返回参数

---根据参数的返回值来判断是按下确定还是取消

#非模态对话框

---不能直接调用局部变量调用,需要new一个对象

---然后去创建、显示,以及手动的释放对象


【滴水基础】5.MFC(3)的评论 (共 条)

分享到微博请遵守国家法律