125
1 Visual C++ MFC 编编编编 .

Visual C++ MFC 编程基础

Embed Size (px)

DESCRIPTION

Visual C++ MFC 编程基础. 一 . 引言. 为什么学习 Windows 程序设计 微机 OS 霸主 Windows 3.X(16 位 ) Windows 95/NT(32 位 ) 程序设计的特殊性 Windows 工作原理 开发工具的多样性. 主要学习内容. Windows 系统引擎 消息驱动体系 三种编程方法 基于 C 语言与 SDK 工具 基于 C++ 语言和 MFC 类库 基于 Visual C++ 环境. 1.1 Windows 系统的特征. 用户观点 统一的图形用户界面 (GUI) - PowerPoint PPT Presentation

Citation preview

Page 1: Visual  C++  MFC  编程基础

1

Visual C++ MFC 编程基础 .

Page 2: Visual  C++  MFC  编程基础

2

一 . 引言 为什么学习 Windows 程序设计微机 OS 霸主

– Windows 3.X(16 位 )– Windows 95/NT(32 位 )

程序设计的特殊性Windows 工作原理开发工具的多样性

Page 3: Visual  C++  MFC  编程基础

3

主要学习内容Windows 系统引擎

消息驱动体系 三种编程方法

基于 C 语言与 SDK 工具基于 C++ 语言和 MFC 类库基于 Visual C++ 环境

Page 4: Visual  C++  MFC  编程基础

4

1.1 Windows 系统的特征用户观点 统一的图形用户界面 (GUI) 多任务多线程机制 设备无关的图形界面 即插即用性 (Plug-and-Play)

Page 5: Visual  C++  MFC  编程基础

5

用户友好性•对相同的对象采用相同的表现方法•对相同的操作采用相同的命令方式

Windows 系统 对象的图形表示 多种输入方式 统一的窗口格式 统一的操作方法

DOS 系统 对象的文字表示 基于文字的输入 命令行交互方式 自定义的用户界面

Page 6: Visual  C++  MFC  编程基础

6

人机对话的交互方式同步交互 用户和 DOS 系统

– ( 例外:中断 ) 用户和一个线程

– (Windows 95/NT)

异步交互 用户和 Windows 系统 用户和多个进程

– ( 多个程序实例 ) 用户和多个窗口

Page 7: Visual  C++  MFC  编程基础

7

1.2 Windows 的控制机制与资源管理 Windows 系统和应用程序的交互方式

– 系统与一线程同步交互– 系统与多线程异步交互

事件驱动体系(异步交互的实现方法)– 事件:鼠标键盘输入、各种状态改变– 事件发生时,用系统消息通知系统– 系统接收消息,提交给各个应用程序

Page 8: Visual  C++  MFC  编程基础

8

资源与内存管理 数据资源 (Resource)

– 文字信息、位图、图标、光标等等– 多个程序共享

动态连接库 (DLL)– 执行中的连接– 多个程序共享

虚存空间– Win 95/NT : 4G

Page 9: Visual  C++  MFC  编程基础

9

1.3 Windows 程序设计的特征 消息驱动体系

– Windows 系统运行中发生的各种事件,以消息的形式通知系统– 各应用程序提供消息循环,接收消息,提交给程序中的各个窗口

窗口处理– 每个窗口配备一个窗口函数,负责处理收到的消息 ( 程序设计的主要任务 )

Page 10: Visual  C++  MFC  编程基础

10

交互控制手段 Windows 系统消息

– 系统控制应用程序的主要手段– 数百条消息表示各种事件的发生

API 函数– 上千个系统函数与专用数据结构– 提供各种功能服务

Page 11: Visual  C++  MFC  编程基础

11

Windows API 函数 窗口管理 图形设备接口 (GDI) 系统服务 数据库: ODBC 网络与通信: RPC/WinSock OLE 支持

Page 12: Visual  C++  MFC  编程基础

12

1.4 软件开发策略 开发需求

– 满足用户需求(功能和友好性)– 保证软件可维护性– 鼓励开发可重用构件– 减少低级工具的使用

目的:提高工作效率,降低开发投入 手段:提供支持程序生成、支持程序综合的各种综合开发工具,

Page 13: Visual  C++  MFC  编程基础

13

两级组织和开发工具 系统开发人员

– 系统设计与集成– 界面设计与实现

系统开发工具– Visual Basic– PowerBuilder– Visual FoxPro– Excel / Access

构件开发人员– 可重用构件的设计与实现

构件开发工具– Visual C/C++– MASM– SDK– Fortran– Java

Page 14: Visual  C++  MFC  编程基础

14

1.5 为什么选用 C++ 语言 学习需求:

– Windows 软件结构– Windows 的消息驱动体系– 学编程技术,不是使用方法– 学基础知识,不是技术手册

矛盾与学习曲线– 众多的程序生成工具,方便简单应用系统的开发,隐蔽了技术细节和工作原理。

Page 15: Visual  C++  MFC  编程基础

15

三种编程方法1. 基于 C 语言和 SDK 开发工具

– 易于理解 Windows 工作原理– 庞大的应用程序接口 (API 、消息 )

2. 基于 C++ 语言和 MFC 基本类库– 消息驱动体系符合面向对象思想– 以 MFC 作为应用程序接口

3. 基于 AppWizard 、 ClassWizard 和 MFC – 自动生成应用程序框架– 提供程序综合支持

Page 16: Visual  C++  MFC  编程基础

16

二、 Windows 程序设计概论 2.1 消息驱动体系 2.2 应用程序框架 2.3 应用程序简例 2.4 可执行程序的产生 2.5 几种常见的系统消息

Page 17: Visual  C++  MFC  编程基础

17

2.1 消息驱动体系键盘输入 鼠标输入 状态改变

系统消息队列应用程序队列 应用程序队列 应用程序队列

窗口窗口窗口 窗口窗口窗口 窗口窗口窗口

消息循环 消息循环消息循环

Windows

应用程序 应用程序

Page 18: Visual  C++  MFC  编程基础

18

控制关系 Windows 系统是主控方

– 通过消息控制 应用程序的各个窗口 各种输入由 Windows 系统接受

– 不受应用程序的控制 应用程序有多个程序入口

– 多个窗口函数 Windows 系统本身的工作

– 也依靠消息驱动体系

Page 19: Visual  C++  MFC  编程基础

19

2.2 应用程序框架程序开发过程

源程序*.C/*.CPP

目标程序*.OBJ

可执行文件*.EXE

可执行程序*.EXE

资源描述*.RC

库函数*.LIB

模块定义*.DEF

资源文件*.RES

编译器

连接器 资源连接

开发工具

资源编译

Page 20: Visual  C++  MFC  编程基础

20

程序员编制的文件 源程序文件( *.C/*.CPP)

– 提供程序入口、消息循环– 提供窗口创建、窗口函数

资源描述文件( *.RC )– 描述常数字符串、位图、图标、光标– 由 SDK 工具、 App Wizard 工具生成

模块定义文件( *.DEF )– 描述内存分配、属性– 库函数的引入、引出

Page 21: Visual  C++  MFC  编程基础

21

源程序结构

Ï ûÏ ¢ Ñ » ·

C AS E Ï û Ï ¢ 1

C AS E Ï û Ï ¢ 2

C AS E Ï û Ï ¢ n

´ ° ¿ Úº ¯ Êý 1 S W IT C H (Ï û Ï ¢ )

C AS E Ï û Ï ¢ 1

C AS E Ï û Ï ¢ 2

C AS E Ï û Ï ¢ n

´ ° ¿Úº ¯ Êý 2 S W IT C H (Ï û Ï ¢ )

C AS E Ï û Ï ¢ 1

C AS E Ï û Ï ¢ 2

C AS E Ï û Ï ¢ n

´ ° ¿ Úº ¯ Êý N S W IT C H (Ï û Ï ¢ )

W in d o w s Ó¦ Óó Ì Ðò ×é ³ É½á ¹ ¹

Page 22: Visual  C++  MFC  编程基础

22

窗口的程序结构 (1/3)登记窗口类

WNDCLASS ws;ws.lpszClassName = 窗口类名;ws.lpfnWndProc = 窗口函数名;……RegisterClass( &ws );/* 给定的窗口函数负责该类窗口的消息响应 */

Page 23: Visual  C++  MFC  编程基础

23

窗口的程序结构 (2/3)

创建窗口、显示窗口窗口句柄 = CreateWindow( 窗口类名,

标题, … );

ShowWindow( 窗口句柄,显示状态 );

/* 窗口句柄是窗口的唯一标识 */

Page 24: Visual  C++  MFC  编程基础

24

窗口的程序结构 (3/3) 定义窗口函数

LRESULT CALLBACK 窗口函数 ( 窗口句柄,消息标识,字参数,长参数 )

{switch( iMsg ) {case WM_PAINT: ...... case ...... }

}// 识别收到的各种消息,完成消息响应

Page 25: Visual  C++  MFC  编程基础

25

WinMain 的程序结构 应用程序入口

WinMain( 程序实例句柄,上一程序实例句柄,命令行参数,显示状态 )

{if( 是首次实例 )

登记主窗口所属的窗口类;创建主窗口;显示主窗口;消息循环;

}

Page 26: Visual  C++  MFC  编程基础

26

消息循环MSG msg; /* 消息结构 */while( GetMessage(&msg,0,0,0) ){ /* 从消息队列取消息 */

TranslateMessage( &msg );/* 翻译消息 */DispatchMessage( &msg );/* 发送消息 */

}/* 收到消息 WM_QUIT 时退出循环

Page 27: Visual  C++  MFC  编程基础

27

2.3 应用程序简例 WinMain 函数

– 设置并登记窗口类“WinAPIDemo” ,指定 WndProc 为窗口函数

– 创建并显示该类的主窗口– 进入消息循环

WndProc 窗口函数– 鼠标消息 WM_LBUTTONDOWN– 鼠标消息 WM_RBUTTONDOWN– 撤消消息 WM_DESTROY– 其余消息交给 DefWindowProc

Page 28: Visual  C++  MFC  编程基础

28

消息的接收与识别 消息接收

窗口函数( HWND hwnd , // 窗口句柄 WORD msg , // 消息标识 WPARAM wParam , // 字参数 LPARAM lParan ) // 长参数

消息识别 msg wParam

Page 29: Visual  C++  MFC  编程基础

29

窗口函数的实现各 case 分支

设计消息响应代码MessageBox 标准信息窗MessageBeep 标准发声函数PostQuitMessage 发送 WM_QUIT 消息DefWindowProc 缺省消息处理函数其他 API GetStockObject 获得系统预定义对象LoadCursor 装入光标LoadIcon 装入图标

Page 30: Visual  C++  MFC  编程基础

30

Windows 窗口的缺省功能缺省功能

– 最大最小化、复原、关闭– 移动、缩放、激活显示、切换– 系统菜单、鼠标选择、按钮选择

实现方法– 依靠 Windows 消息驱动体系– 包括: DefWindowProc

Page 31: Visual  C++  MFC  编程基础

31

根据应用需求的消息响应,设计 case 语句其余消息必须交给 DefWindowProc

– 可能递归调用窗口函数 可以利用缺省的消息响应

– 如:发送 WM_CLOSE 来关闭窗口 需要状态信息时,使用静态变量

窗口函数设计要领

Page 32: Visual  C++  MFC  编程基础

32

模块定义文件( *.DEF ) NAME 程序名称 EXETYPE 目标程序类型 CODE 代码段属性 DATE 数据段属性 HEAPSIZE 局部堆尺寸 STACKSIZE 栈尺寸 EXPORTS 引出函数 IMPORTS 引入函数

Page 33: Visual  C++  MFC  编程基础

33

资源描述文件菜单模板菜单名 MENU 属性BEGIN

MenuItem “菜单项文本”,项标识符POPUP “子菜单项”BEGIN …… END

END菜单的指定

– 指定 ws.lpszMenuName = 菜单名,或在 CreateWindow 调用中指定

– 菜单消息中的 wParam 为项标识符

Page 34: Visual  C++  MFC  编程基础

34

程序的创建 工程文件的使用创建工程文件,加入.CPP 源程序、.C 源程序、.RC 资源描述文件、.DEF 模块定义文件

通过工程文件,完成源程序的编译、目标程序的连接和可执行文件的生成。

Page 35: Visual  C++  MFC  编程基础

35

程序的调试跟踪调试

F10 单步(进入函数)F11 单步(不进入函数)Shift F7 执行到函数出口

程序中断F5 继续执行F9 断点设置与撤消

窗口函数的跟踪在函数入口加断点

Page 36: Visual  C++  MFC  编程基础

36

2.4 几种常见的系统消息 鼠标输入

WM_MOUSEMOVE 鼠标移动WM_LBUTTONDOWN鼠标左键按下WM_LBUTTONUP 鼠标左键释放

键盘输入WM_KEYDOWN 键按下WM_KEYUP 键释放WM_CHAR 字符键入

重画消息WM_PAINT 重画窗口用户区

Page 37: Visual  C++  MFC  编程基础

37

文本输出例HDC hDC; // 输出设备句柄PAINTSTRUCT ps; // 重画信息结构switch( msg ) {……case WM_PAINT: // 重画消息入口

hDC = BeginPaint(hwnd, &ps); // 获得设备TextOut(hDC, 10, 10,“Hello”, 5); // 文本输出EndPaint(hWnd, &ps); // 释放设备break;

} // hDC 代表窗口用户区

Page 38: Visual  C++  MFC  编程基础

38

窗口重画显示原理

– 系统不保存被覆盖的窗口,仅将需要显示的部分设置 为无效区;– 系统自动向有无效区的窗口发 WM_PAINT 消息;– 各种输出函数应在 WM_PAINT 的消息响应中调用

WM_PAINT 消息的程序产生– ShowWindow 、 UpdateWindow 、 Invalid

ateRect 等 API 函数调用时

Page 39: Visual  C++  MFC  编程基础

39

图形输出例int x = LOWORD( lParam ); // 获得鼠标位置int y = HIWORD( lParam );HDC hDC = GetDC( hWnd ); // 获取设备句柄switch( msg ) {……case WM_LBUTTONDOWN: // 鼠标按下

MoveTo(hDC, x, y); break; // 设置当前点case WM_LBUTTONUP: // 鼠标释放

LineTo(hDC, x, y); break; // 画线至指定点}ReleaseDC(hWnd, hDC); // 释放设备句柄

Page 40: Visual  C++  MFC  编程基础

40

补充说明 消息属性的获取

– 参数中可保存多个属性– 常用 LOWORD 和 HIWORD 分解 lParam

输出设备– hDC 标识窗口用户区及其设备描述表

两种获取 hDC 的方法– WM_PAINT 响应 (BeginPaint, EndPaint)– 其他消息响应 (GetDC, ReleaseDC)

Page 41: Visual  C++  MFC  编程基础

41

本章小结 1. 消息驱动体系

– 系统队列、应用队列 2. 程序结构

– 登记窗口类、创建窗口、消息循环 3. 窗口函数与消息响应

– CASE 分支、缺省处理 4. 常用消息和重画机制

– 设备句柄、无效区与 WM_PAINT

Page 42: Visual  C++  MFC  编程基础

42

上机题 1

用 C 语言扩充 65页的程序,实现以下功能:1 . 当鼠标左键按下时,将鼠标当前坐标显示在窗

口中;2 . 随着鼠标移动,持续显示鼠标当前坐标;3 . 鼠标右键按下时,清屏。

Page 43: Visual  C++  MFC  编程基础

43

上机题 2

扩充上机题 1 ,实现以下功能:1 . 当鼠标左键按下时,以鼠标位置为圆心,画出一个直径为 10 的圆。

Ellipse( hDC, left, top, right, bottom )

2 . 要求圆随着鼠标移动,直到鼠标左键抬起3 . 再次按下鼠标时,该圆消失,画出新的圆4 . 要求随着窗口移动、重置大小或被其他窗口覆盖,圆和坐标显示保持原有位置。

Page 44: Visual  C++  MFC  编程基础

44

三、 MFC 程序设计初步基本思想:

以基本类库的形式,支持 Windows 应用程序基本框架和常用模 块,覆盖 API 函数,提供高级编程接口。 3.1 OOP 与 Windows 消息驱动体系 3.2 MFC 基本类库与应用程序框架 3.3 CWnd 类和消息处理机制 3.4 MFC 典型应用例

Page 45: Visual  C++  MFC  编程基础

45

3.1 面向对象程序设计与 Windows 的消息驱动体系

面向对象方法:1. 若干对象组成软件系统2. 对象是封装的数据及其相关操作 ( 方法 )

3. 消息传递提供对象通信手段4. 对象激活方法来响应消息

Page 46: Visual  C++  MFC  编程基础

46

面向对象程序设计1. 确认对象及其相互关系

– 整体部分关系– 一般特殊关系

2. 分析系统的工作– 确认消息传递关系

3. 设计对象类– 用数据结构描述对象的属性与状态– 用成员函数描述外部操作

Page 47: Visual  C++  MFC  编程基础

47

Windows 系统的面向对象分析1. 对象:

– 各种窗口、各种设备和 GDI 对象2. 对象通信:

– Windows 消息、 API 函数调用3. 消息传递:

– 调用窗口函数处理 Windows 消息4. 消息响应:

– 窗口函数 case 语句的各个分支– 设备和 GDI 对象的 API 函数

Page 48: Visual  C++  MFC  编程基础

48

使用 OO 方法的好处:1. 面向对象方法和 Windows 消息驱动体系的完美结合2. 面向对象程序设计语言的支持

– 提供基本类库3. 信息隐蔽

– 以类定义接口代替 API 接口4. 程序结构的模块化

– 分离消息识别和消息响应

Page 49: Visual  C++  MFC  编程基础

49

OOPL 支持 Windows 程序设计提供程序基本框架 各种窗口基本类

– 封装窗口函数、窗口句柄和 API ,提供常用操作和消息响应函数。 各种设备和 GDI 对象类

– 封装句柄、相关数据结构和 API 。 应用程序类和类模板

– 封装 Windows 应用程序的基本结构

Page 50: Visual  C++  MFC  编程基础

50

MFC 的结构

Ó ¦Ó ó ÌÐ ò

¶ Ô» °¿ ò

Ê ÓÍ ¼

¿ ØÖ Æ¿ ò

¿ ò¼ Ü °¿ Ú

C W n d

Πĵ µ

Πļ þ

Í ¼Ð ÎÉ è± ¸

G D I ¶ ÔÏ ó

² ˵ ¥

Ê ý¾ Ý¿ âÖ §³ Ö

Í ¬² ½¶ ÔÏ ó

Í Ð Å½ Ó¿ Ú

¼ º Ï

Ò ì³ £ ¦À í

CObj ect

Page 51: Visual  C++  MFC  编程基础

51

基于基本类的程序设计 程序结构

– 耦合在应用程序框架中根据应用需求设计窗口派生类

– 定义属性、编制消息响应成员函数 理解工作原理

– 程序设计与调试的需求

Page 52: Visual  C++  MFC  编程基础

52

常用容器类( 1/2 ) 数组类:

– 如: CWordArray 、 CPtrArray 、 CObArray... CWordArray ax;for( int i=0; i < ax.GetCount(); i++ ) WORD w = ax[ i ];

链表集合类:– 如: CObList 、 CPtrList 、 CStringList... CStringList sx;POSITION pos = sx.GetHeadPosition( );while( pos ) { CString s = sx.GetNext( pos ); ... }

Page 53: Visual  C++  MFC  编程基础

53

常用容器类( 2/2 ) 映射集合类:

– 如: CMapWordToPtr 、 CMapStringToOb... CMapWordToPtr wpx;POSITION pos = wpx.GetStartPosition( );while( pos ) { WORD w; void *p; wpx.GetNext( w, p, pos ); ... ...}

Page 54: Visual  C++  MFC  编程基础

54

MFC 对象的使用 定义方法:

1. 定义 MFC 派生类、定义其属性和成员函数 构造方法:

1. 构造 MFC 类对象或其派生类对象2. 或调用其 Create 函数,创建 Windows 对象

通信方法:1. 调用 MFC 对象的成员函数2. 响应来自其他对象的消息传递3. 向其他对象发送消息发送

Page 55: Visual  C++  MFC  编程基础

55

3.2 MFC 基本类库的应用框架 应用程序类 CWinApp

成员 Run( ) 提供消息循环要求派生类定义 InitInstance( )

自动提供 WinMain( )调用 InitInstance( ) 和 Run( )

各种窗口类通用基类 CWnd单文档界面 CFrameWnd多文档界面 CMDIFrameWnd

Page 56: Visual  C++  MFC  编程基础

56

最简单的 MFC 应用程序#include<afxwin..h>class CHelloApp // 应用程序派生类

: public CWinApp {public:

virtual BOOL InitInstance( ); // 实例初始化};class CHelloWnd // 主窗口派生类

: public CFrameWnd {public:

CHelloWnd( ) ; // 构造主窗口};

Page 57: Visual  C++  MFC  编程基础

57

最简单的 MFC 应用程序(续)CHelloApp HelloApp; // 应用程序BOOL CHelloApp::InitInstance() {

m_pMainWnd = new CHelloWnd( ); // 主窗口m_pMainWnd->ShowWindow( m_nCmdShow );m_pMainWnd->UpdateWindow( ); // 显示return TRUE;

}CHelloWnd::CHelloWnd( ) {

Create( NULL, “Hello World!” );} // 创建主窗口结构

Page 58: Visual  C++  MFC  编程基础

58

程序调用关系CW inApp::InitApplication

CW nd::Create

CHelloW nd::CHelloW nd

CW nd::Show W indow

CW nd::UpdateW indow

CHelloApp::InitInstance

CW inApp::Run

CW inApp::ExitInstance

W inM ain 程序入口构造窗口类实例初始化构造 CHelloWnd 对象调 CreatWindow()

调 UpdateWindow()

调消息循环

Page 59: Visual  C++  MFC  编程基础

59

应用框架的作用 提供 WinMain 函数的程序结构

– 包括主窗口类登记和消息循环 CWinApp 类提供可重载的函数:

– InitInstance 用于初始化– 如:构造单文档、多文档或对话框的主窗口– ExitInstance 用于结束处理

Page 60: Visual  C++  MFC  编程基础

60

3.3 CWnd 类和消息处理机制封装 API 中窗口处理的数据结构和相关函数 提供两类成员函数:

窗口 API 函数:代替 SDK API 函数消息响应函数:响应各种系统消息

窗口 API 函数例ShowWindow 、 ScrollWindow 、 SetWindowText

消息响应函数例OnPaint 、 OnLButtonDown 、 OnKeyUp 、OnMouseMove 、 OnClose 、 OnHScroll

Page 61: Visual  C++  MFC  编程基础

61

CWnd 的使用方法 *.CPP 文件中提供消息映射,指定消息响应函数

BEGIN_MESSAGE_MAP(派生类,窗口基类)ON_WM_PAINT( ) 各种消息的入口ON_WM_CLOSE( )ON_WM_KEYUP( )ON_WM_LBUTTONDOWN( )ON_COMMAND(菜单项标识,响应函数名 )END_MESSAGE_MAP( )

*.H 文件中加入以下语句:DECLARE_MESSAGE_MAP( )

Page 62: Visual  C++  MFC  编程基础

62

CWnd 中的消息响应 CWnd 提供窗口函数负责消息识别

– 调用规定的消息响应函数 多数系统消息由 CWnd 的消息响应成员函数处理;

– 例: ON_WM_PAINT( ) 规定– 函数 OnPaint 响应 WM_PAINT

菜单消息、通知消息等由指定响应函数处理– 例: ON_COMMAND( ItemID, OnAbout )– 规定 OnAbout 响应菜单项 ItemID

Page 63: Visual  C++  MFC  编程基础

63

CWnd 派生类的构造class 派生类名 : public CWnd{ 属性、状态的数据结构public: 构造函数、析构函数 一般的成员函数 afx_msg 消息响应成员函数 DECLARE_MESSAGE_MAP( )};

Page 64: Visual  C++  MFC  编程基础

64

3.4 一个消息映射应用例 类定义CTheApp 应用程序类CMainWin 主窗口类 程序代码theApp 应用程序对象CTheApp::InitInstance 实例初始化函数CMainWin::OnRButtonDown 左鼠标按下消息响应CMainWin::OnLButtonDown 右鼠标按下消息响应MESSAGE_MAP 主窗口消息映射

Page 65: Visual  C++  MFC  编程基础

65

运行中的事件流图用户 应用程序 主窗口

鼠标双击 启动 构造Windows

WM_CREATE WM_PAINT …

左鼠标按下 WM_LBUTTONDOWN

右鼠标按下 WM_RBUTTONDOWN

Page 66: Visual  C++  MFC  编程基础

66

函 数 调 用 关 系

CW nd::Create

CW nd::Show W indow

CW nd::UpdateW indow

CTheApp::InitInstance

W inM ain

CFram eW nd::O nLButtonDown

CM ainW in::O nLButtonDown

CFram eW nd::O nRButtonDow n

CM ainW in::O nRButtonDow n

CW nd::W indowProc

W indows Ï µÍ ³

Page 67: Visual  C++  MFC  编程基础

67

3.5 MFC 设备描述类 封装设备描述表和图形设备接口

– 抽象描述图形输出设备– ( 如 : 显示器 , 打印机 , 绘图仪 )

常用派生类– CPaintDC 类 用于 WM_PAINT 处理– CClientDC 类 用于其他消息处理– CWindowDC 类 用于整个窗口

Page 68: Visual  C++  MFC  编程基础

68

CClientDC 的应用void CMainWnd::OnLButtonDown(

UINT flg, CPoint pt ) {

CClientDC dc( this ); // 建立设备描述对象CRect rct;

GetClientRect( rct ); // 取得窗口矩形dc.Ellipse( rct ); // 画椭圆CFrameWnd::OnLButtonDown( cfg, pt );

}

Page 69: Visual  C++  MFC  编程基础

69

CPaintDC 的应用void CMainWnd::OnPaint(UINT flg, CPoint pt ){ // 处理 WM_PAINT 消息

CClientDC dc( this );CRect rct;GetClientRect( rct );dc.Ellipse( rct );CFrameWnd::OnLButtonDown( cfg, pt );

}// 当窗口重新显示时 , 自动产生此消息

Page 70: Visual  C++  MFC  编程基础

70

3.6 窗口输入消息处理 鼠标输入消息

– 鼠标左键按下: WM_LBUTTONDOWN– 鼠标左键释放: WM_LBUTTONUP– 鼠标左键双点: WM_LBUTTONDBLCLK– 鼠标移动: WM_MOUSEMOVE

键盘输入消息– 键按下: WM_KEYDOWN– 键释放: WM_KEYUP– 字符键输入: WM_CHAR

Page 71: Visual  C++  MFC  编程基础

71

鼠标消息处理 CWnd 的鼠标消息响应函数

afx_msg void OnLButtonDown( UINT flg, CPoint pt );afx_msg void OnMouseMove( UINT flg, CPoint pt );……– flg 虚拟键标志; pt 鼠标的屏幕坐标

鼠标的消息入口ON_WM_LBUTTONDOWN( )ON_WM_MOUSEMOVE( )……

Page 72: Visual  C++  MFC  编程基础

72

应用例:鼠标画线 OnLButtonDown( UINT flg, CPoint pt )

pDrag = new CClientDC( this );// 构造用户区设备对象

pDrag->MoveTo( pt.x, pt.y ); // 设输出位置(设备属性)

OnMouseMove( UINT flg, CPoint pt ) pDrag->LineTo( pt.x, pt.y );

// 画线到点 pt 、并改变输出位置 OnLButtonUp( UINT flg, CPoint pt )

delete pDrag; // 释放设备对象

Page 73: Visual  C++  MFC  编程基础

73

用户区设备类 ( 非 WM_PAINT 处理 )– CClientDC 封装 GetDC 和 ReleaseDC 等 API – 其基类 CDC 提供 GDI 输出函数

鼠标捕获与释放– 迫使所有鼠标消息发向当前窗口

无效区与 WM_PAINT– Invalidate 指定无效区,等效于 WM_PAINT

CWnd::Close – 提供关闭窗口的功能

Page 74: Visual  C++  MFC  编程基础

74

键盘输入处理 CWnd 的键盘输入消息响应函数

– afx_msg OnKeyDown( UINT ch, UINT rep, UINT flg );– afx_msg OnChar( ... );– afx_msg OnKeyUp( ... );– ……– ch 字符的 ASCII值, rep 重复次数, flg 虚拟键

键盘输入消息入口– ON_WM_KEYDOWN( )– ON_WM_CHAR( )– ON_WM_KEYUP( )

Page 75: Visual  C++  MFC  编程基础

75

应用例:光标状态的切换 系统光标的获得

hCursor = ::AfxGetApp( )->LoadStandardCursor( IDC_WAIT );

// AfxGetApp( ) 获得 CMyApp 指针 OnKeyDown( UINT ch, UINT rep, UINT flg )

hCursor = ::SetCursor( hCursor ); // 改变光标,并保存原光标

OnKeyUp( UINT ch, UINT rep, UINT flg )hCursor = ::SetCursor( hCursor ); // 恢复光标,并保存原光标

Page 76: Visual  C++  MFC  编程基础

76

本章小结 OOP 与消息驱动体系 MFC 类库应用框架 CWnd 类与消息处理 CDC 设备描述类及其派生类

Page 77: Visual  C++  MFC  编程基础

77

上机题 3扩充第 100页表 7-7 的程序 ,实现以下功能

– 1. 设置一菜单项,点击该菜单项时,在窗口正中央画出一个 30*50 的矩形 dc.Rectangle( top, left, bottom, right )

– 2. 当鼠标左键按下时,如果鼠标选在矩形内,则光标变为十字,矩形随着鼠标移动(以鼠标为矩形中心);直到释放鼠标,光标恢复到原状态。– 3. 再次选择该菜单项时,清屏,画出新矩形

Page 78: Visual  C++  MFC  编程基础

78

上机题 4

扩充上机题 3 ,实现以下功能:– 1 . 在矩形随鼠标时,在窗口中绘制出鼠标轨迹;

dc.MoveTo(x, y) dc.LineTo(x,y)

– 2 . 要求窗口被覆盖后,能够恢复窗口原有内容。

– 3 . 按动鼠标右键时,进行清屏。

Page 79: Visual  C++  MFC  编程基础

79

四、图形设备接口 4.1 图形设备描述表 4.2 图形输出 4.3 字体选择和文本输出 4.4 图象输出 4.5 调色板 4.6 图元文件和打印设备

Page 80: Visual  C++  MFC  编程基础

80

设备无关的图形设备接口– SDK 提供一组 API 函数

图形设备的描述:– 图形设备描述表– 句柄: HDC dc = BeginPaint( ) 或 GetDC( )– 保存图形输出相关的各种属性

GDI 对象:– 画笔: Pen ,刷子: Brush ,字体: Font ,– 调色板: Palette ,位图: Bitmap

Page 81: Visual  C++  MFC  编程基础

81

4.1 图形设备描述表 CDC 类支持图形设备描述表

– 属性的设置与获取: Get*** / Set***– 绘图工具的设置与获取:– 坐标变换与映射方式:– 图形输出函数: LineTo ...– 图像输出函数: BitBlt ...– 文本输出函数: TextOut ...

Page 82: Visual  C++  MFC  编程基础

82

设备坐标体系和逻辑坐标体系 设备坐标属性:

– 窗口原点: CDC::Set / GetWindowOrg( )– 窗口范围: CDC::Set / GetWindowExt( )

逻辑坐标属性:– 视口原点: CDC::Set / GetViewportOrg( )– 视口范围: CDC::Set / GetViewportExt( )

映射模式:– CDC::Set / GetMapMode– MM_TEXT 像素单位– MM_ISOTROPIC X,Y 度量相等

Page 83: Visual  C++  MFC  编程基础

83

坐标变换例dc.SetViewportOrg(10,70);dc.SetWindowExt(1000,1000);dc.SetViewportExt(1000,-1000);

逻辑坐标 (20,10) 相当于设备坐标 (30,60)

– CDC 成员多用逻辑坐标– CWnd 成员多用设备坐标

设备坐标=视口原点+ (逻辑坐标-窗口原点 )*视口范围/窗口范围

X

XY

Y

(10,70)

(20,10)

(0,0)

Page 84: Visual  C++  MFC  编程基础

84

4.2 图形输出 GDI 对象

– 画笔:画线;属性:宽度、线形; CPen 类支持

– 刷子:添色;属性:颜色、位图; CBrush 类支持

绘画模式– 画笔象素与目标象素的逻辑运算– SetROP2 / GetROP2

Page 85: Visual  C++  MFC  编程基础

85

图形输出函数当前输出位置

– MoveTo / GetCurrentPosition 图形输出函数

– 线输出: LineTo, PolyLine, Arc– 线输出并添色: Rectangle, Ellipse, RoundRe

ct, Chord, Pie, Polygon

Page 86: Visual  C++  MFC  编程基础

86

图形输出步骤(不用缺省值)构造 CDC 派生类对象 CPaint dc(this);

构造 CPen 对象 CPen pen(...);

将画笔选入设备描述表 p = dc.SelectObject(&pen);

构造 CBrush 对象 CBrush brs(...);

将刷子选入设备描述表 b = dc.SelectObject(&brs);

设置绘画模式 r = dc.SetROP2(...);

调用图形输出函数 dc.LineTo( ) ... ... ... ...

恢复原绘画模式 dc.SetROP2( r );

恢复原画笔 dc.SelectObject( p );

恢复原刷子 dc.SelectObject( b );

Page 87: Visual  C++  MFC  编程基础

87

4.3 图像输出 Windows 的两种位图

– Bitmap 位图是 GDI 对象,用于显示。– DIB 位图与显示设备无关,用于交换。

Bitmap 位图的使用– 创建 CBitmap 对象 CBitmap bmp– 创建位图 bmp::CreateBitmap– 或装入位图 bmp::LoadBitmap– 存取位图数据 bmp::Set / GetBitmapBits

Page 88: Visual  C++  MFC  编程基础

88

位图表面绘图方法( 1/2 ) 创建内存设备对象 (缓冲区)

– CDC memDC;

创建兼容的内存设备描述表– memDC.CreateCompatibleDC ( 输出设备);

创建 CBitmap 对象– CBitmap bmp;

创建兼容的位图(或装入位图)– bmp.CreateCompatibleBitmap( memDC, …

Page 89: Visual  C++  MFC  编程基础

89

位图表面绘图方法( 2/2 ) 将位图作为显示区选入内存设备

– memDC.SelectObject( &bmp ); 向内存设备的输出图形、图象

– 等效于对该位图的操作 主要特征

– 位图作为内存设备的显示区,参加运算与显示,没有直接显示的手段– 图象处理采用光栅操作:设备位图(显示区)之间按二进位的逻辑运算

Page 90: Visual  C++  MFC  编程基础

90

图像显示与处理函数 PatBlt(矩形,光栅操作 )

– 矩形区和当前刷子之间的光栅操作 BitBlt(矩形,源设备,矩形位置,光栅操作 )

– 矩形区和源设备矩形之间的光栅操作 StretchBlt(矩形,源设备,矩形,光栅操作 )

– 矩形区和源设备矩形之间的光栅操作及缩放 SetPixelV( 象素点位置,颜色 )

– 设置指定点的颜色

Page 91: Visual  C++  MFC  编程基础

91

应用例:位图输出void CMyDC::DrawBitmap( CBitmap *bmp, CPoint pt ){ CDC memDC;

memDC.CreateCompatibleDC( this ); // 内存设备memDC.SelectObject( bmp ); // 选入memDC.SetMapMode( GetMapMode( ) );BITMAP bm; // 获取尺寸bmp->GetObject( sizeof(BITMAP), (LPSTR)&bm );CPoint org( 0, 0 ), sz( bm.bmWidth, bm.bmHeight );memDC.DPtoLP( &org ); DPtoLP( &sz );BitBlt( pt.x, pt.y, sz.x, sz.y, &memDC, org.x, org.y, SRCCOPY);

}

Page 92: Visual  C++  MFC  编程基础

92

图像显示与处理函数(续) CDC::MaskBlt( 矩形,源设备,屏蔽位图,光栅操作)

– 屏蔽位图、源设备图像和目标矩形的光栅操作 CDC::PlgBlt( 平行四边形,源设备与矩形,屏蔽位图 )

– 屏蔽位图、源设备图像到平行四边形目标的数据传输 CDC::FloodFill( 指定点,边境颜色 )

– 指定点所在区域的颜色填充

Page 93: Visual  C++  MFC  编程基础

93

DIB 位图格式(文件格式)BITMAPFILEHEADER

BITMAPINFOHEADER

颜色表颜色屏蔽字

点阵数据

位图尺寸颜色平面数

象素位数。。。

16 位、 32 位图像无颜色屏蔽字 24 位、 32 位图像无颜色表

DIB头

Page 94: Visual  C++  MFC  编程基础

94

DIB 位图的使用 (1/2) DIB 位图的显示

::SetDIBitsToDevice( 设备,矩形,行范围,点阵, DIB头 ... 将 DIB 位图的指定行输出到设备显示区的矩形::StretchDIBits( 设备,矩形,源矩形,点阵,

DIB头 ...– 将 DIB 位图的指定矩形输出到设备显示区的矩形

Page 95: Visual  C++  MFC  编程基础

95

DIB 位图的使用 (2/2)

DIB 位图的变换– 从 GDI 位图到 DIB 位图::GetDIBits( 设备,位图,行范围,点阵, DIB头 ...– 从 DIB 位图到 GDI 位图CDC::CreateDIBitmap(DIB头,点阵, ...

Page 96: Visual  C++  MFC  编程基础

96

屏蔽位图生成方法从彩色位图产生单色位图,用于实现透明背景CBitmap bmp;bmp.CreatBitmap(宽度 , 高度 ,1,1,0); // 单色位图CDC memDC;memDC.CreateCompatibleDC( 输出设备 );memDC.SelectObject( &bmp );::SetDIBits( memDC.m_hDC, bmp.GetSafeHandle(), 首行,行数,点阵指针, DIB头指针, DIB_RGB_COLORS);

// 将指定的 DIB 位图变换成单色 GDI 位图

Page 97: Visual  C++  MFC  编程基础

97

五、对话框和控制框 5.1 资源编辑 5.2 对话框 5.3 控制框的使用 5.4 综合应用例

Page 98: Visual  C++  MFC  编程基础

98

5.1 资源编辑资源种类

对话框模板 DIALOG菜单模板 MENU图标 ICON光标 CURSOR位图 BITMAP加速键表 ACCELERATORS字符串表 STRINGTABLE工具条模板 TOOLBAR

Page 99: Visual  C++  MFC  编程基础

99

VC 的资源编辑器新建

– Insert --> Resouce --> 选择资源修改

– 直接双点指定资源的图标 编辑

– 不同资源采用不同编辑器 程序识别方法

– 资源标识符(整数)

Page 100: Visual  C++  MFC  编程基础

100

菜单模板的编辑 结构描述( 190页)

– 菜单 菜单标识符 MENU– 子菜单项 POPUP “ 字体 (&F)”– 菜单项 MENUITEM “宋体 \tCtrl-S” 标识符

指定菜单标识符菜单标识符 IDR_MAINMENUIDR_MAINMENU 选择菜单项

– 双点进入属性编辑– 编写显示文本等属性– 指定菜单项标识符菜单项标识符 ID_FONT_SONGTIID_FONT_SONGTI

Page 101: Visual  C++  MFC  编程基础

101

对话框模板的编辑 编辑窗

– 显示对话框和控制框工具条 编辑

– 指定对话框标识符对话框标识符和属性– 选择控制框,拖入对话框– 双点控制框,进入属性编辑– 编辑属性,指定控制框标识符控制框标识符

Page 102: Visual  C++  MFC  编程基础

102

对话框的资源描述 .RC

IDD_MYDIALOG DIALOG DISCARDABLE 0,0,230,104STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENUCAPTION “My Dialog”FONT 10, “System”BEGIN

DEFPUSHBUTTON “OK”,IDOK,173,7,50,14PUSHBUTTON “Cancel”,IDCANCEL,173,24,50,14CTEXT “This is a dialog”,IDC_STATIC,130,56,87,17CONTROL 103,IDC_STATIC,”Static”,SS_BITMAP,7,7,120,90

END// 225 页

Page 103: Visual  C++  MFC  编程基础

103

5.2 对话框编程支持 SDK 的支持 (API) :

– 使用特殊的窗口函数(指定对话框模板)– 系统提供窗口类

MFC 的支持:void CMainWnd::OnHelpAbout( ) {

CDialog CAboutdlog( IDD_MYDIALOG, this );// 创建对话框对象CAboutdlog.DoModal( );// 启动对话

}

Page 104: Visual  C++  MFC  编程基础

104

对话框的消息响应 定义 CDialog 派生类 CMyDialog

– 各种消息响应函数– OnInitDialog 对话框初始化– OnOK 确认按钮– OnCancel 取消按钮

获得控制框对象(界面元素)– CDialog::GetDlgItem( 控制框标识符 )– 在 ClassWizard 中设定

Page 105: Visual  C++  MFC  编程基础

105

窗口的分类 用户界面元素的容器

– 各种对话框( CDialog 派生类)– 各种视窗( CView 派生类)– 产生窗口状态变化消息

用户界面的基本元素– 各种控制框( CControl 的派生类)– 向上级窗口发送通知消息

Page 106: Visual  C++  MFC  编程基础

106

5.3 控制框的使用 六种主要的控制框按钮框(包括单选钮、复选钮、分组框)静态框(文本显示)编辑框(单行、多行编辑)列表框(单选、复选)滚动条框(水平、垂直)组合框(可编辑、不可编辑)

MFC 支持CButton

CStaticCEditCListBoxCScrollBarCComboBox

Page 107: Visual  C++  MFC  编程基础

107

两种使用方法 作为子窗口

– 控制框对象作为上级窗口类的成员变量 动态生成

– 在 OnCreate 中调用该对象的 Create 、指定风格与属性

作为对话框元素– 在对话框模板中定义控制框、描述其风格与属性

自动生成– 随对话框生成

Page 108: Visual  C++  MFC  编程基础

108

上级窗口和控制框的通信( 1/2 ) 控制框向上级窗口发通知消息 上级窗口操纵控制框的方法

– 获取控制框对象或控制框标始符– 调用其成员函数、或发送消息– 或其基类 CWnd 的控制框函数

CWnd 派生各种控制框类– 可利用控制框类生成各种特殊的控制框– MFC 4.2 已提供了二十二种控制框类

Page 109: Visual  C++  MFC  编程基础

109

上级窗口和控制框的通信( 2/2 ) 控制框发向上级窗口的通知消息

BN_* * * * 按钮操作通知LBN_* * * * 列表框操作通知EN_* * * * 编辑框操作通知CBN_* * * * 组合框操作通知WM_HSCROLL, WM_VSCOLL 滚动操作消息

上级窗口发向控制框的控制消息BM_* * * * 按钮框控制消息LB_* * * * 列表框控制消息EM_* * * * 编辑框控制消息CBM_* * * * 组合框控制消息

Page 110: Visual  C++  MFC  编程基础

110

5.4 综合应用例 输入各种数据的对话框( 298页)

– 利用编辑控制框画面设计

– 资源编辑生成对话框模板– 编辑控制框:数据输入– 静态控制框:文本说明– 按钮控制框:确认和取消

Page 111: Visual  C++  MFC  编程基础

111

程序实现方法 数据结构的设计

– 主窗口类 CMainWnd– 对话框类 CComputerDlg– 分别提供成员变量保存各个编辑结果

数据传输关系的确定– 在编辑框和成员变量之间– DoDataExchange( CDataExchange *pDX );

编辑结果的获取– 重定义 OnOK( )

Page 112: Visual  C++  MFC  编程基础

112

数据传输的实现void CComputerDlg::DoDataExchange( CDataExchange *pDX ){

CDialog::DoDataExchange( pDX );DDX_Text( pDX, IDC_CPUEDIT, m_CPU );

// CPU 编辑框 《 =》 成员变量DDV_MaxChars( pDX, m_CPU, 30 );

// 字符串长度限制DDX_Text( pDX, IDC_FREQEDIT, m_FreqEdit );

// 主频编辑框 《 =》 成员变量DDV_MinMaxUInt( pDX, m_MainFreq, 2, 450 );

// 无符号整数的上下限。。。}

Page 113: Visual  C++  MFC  编程基础

113

数据传输的控制( Dialog 类)DoModal

OnInitDialog

OnOK

UpdateData

DoDataExchage

自动调用

程序中直接调用

Page 114: Visual  C++  MFC  编程基础

114

主窗口的实现 消息映射

ON_WM_CREATE( ) // 创建消息ON_COMMAND( ID_FILEEXIT, OnFileExit ); // 菜单项ON_COMMAND( ID_FILEINFO, OnFileInfo );

菜单响应函数void CMainWnd::OnFileInfo( ) {– CComputerDlg dlg;– dlg.DoModel( ); // 启动对话框– CClientDC dc( this );– ShowMessage( &dc ); // 显示数据}

Page 115: Visual  C++  MFC  编程基础

115

上机题 5

设计一个 Windows 程序完成以下功能:– 提供菜单项来调用一个对话框来完成以下学生信息的输入:– 学号、姓名、出生年月日、籍贯、– 班级、毕业学校– 输入结束后,在主窗口显示所有输入信息

Page 116: Visual  C++  MFC  编程基础

116

上机题 6

扩充上机题 6 的功能– 在对话框中补充两个组合框– 实现性别、所属学院的输入– 以及在主窗口的显示

Page 117: Visual  C++  MFC  编程基础

117

六、程序设计专题 6.1 应用程序框架 6.2 持久性对象和序列化 6.3 多线程程序设计 6.4 抢先多任务和非抢先多任务

Page 118: Visual  C++  MFC  编程基础

118

6.1 应用程序框架 AppWizard 自动生成程序框架

– 程序类型(可执行、动态连接库、构件)– 各种主窗口– 界面风格(工具条、状态条)– 数据库支持、 Socket 支持、 OLE 支持

ClassWizard 自动生成类的框架– 指定类的生成– 消息映射、成员函数、成员变量– ActiveX 属性、方法和事件

Page 119: Visual  C++  MFC  编程基础

119

生成的程序框架 CDemoApp theApp;

– 继承 CWinApp, 提供消息循环和程序入口 CMainFrame

– 继承 CMDIFrameWnd, 提供多文档主窗口 CChildFrame

– 继承 CMDIChildWnd, 提供多文档子窗口 CDemoDocument

– 继承 CDocument 文档类 CDemoView

– 继承 CView 视窗类

Page 120: Visual  C++  MFC  编程基础

120

CDemoApp::InitInstanceCMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate( 文档模板

IDR_AX3TYPE, 模板描述RUNTIME_CLASS(CAX3Doc), 文档类RUNTIME_CLASS(CChildFrame), 窗口类RUNTIME_CLASS(CAX3View)); 视窗类

AddDocTemplate(pDocTemplate); 登记CMainFrame* pMainFrame = new CMainFrame; 主窗口if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) 创建

return FALSE;

Page 121: Visual  C++  MFC  编程基础

121

文档——视窗结构ÐÅÏ ¢´ ¦ Àí ÖеÄÊý¾Ý¼° Æä¶àÖÖÊÓÍ ¼

Êý¾ÝµÄÏ Ôʾ±í ¸ ñÊÓÍ ¼Ê¼þÏ ì Ó¦

Êý¾ÝÏ Ôʾֱ· ½ÊÓÍ ¼Ê¼þÏ ì Ó¦

Êý¾ÝÏ ÔʾÇúÏ ßÊÓÍ ¼Ê¼þÏ ì Ó¦

Êý¾ÝΠĵµ»º ³ åÇøÐÅÏ ¢´ ¦ Àí

Page 122: Visual  C++  MFC  编程基础

122

文档与视窗的分离 面向对象分析的基本观点:

信息处理和信息显示的分离 MFC 分别提供文档基类和视窗基类

CDocument 、 CView MFC 提供 SDI 和 MDI 应用框架

CSingleDocTemplate 类支持单文档: 建立主窗口、文档类和视窗类的关系CMultiDocTemplate 类支持多文档:

建立 MDI子窗口、文档类和视窗类的关系

Page 123: Visual  C++  MFC  编程基础

124

视窗类的功能继承窗口基类属性、 API 成员函数、消息响应函数

获得相应的文档对象CDocment *GetDocument( );

视窗初始化: InitUpdate( );视窗更新响应: OnUpdate( ); 窗口重画: OnDraw( CDC *pDC );

Page 124: Visual  C++  MFC  编程基础

125

文档与视窗的交互 (1/2)用户 应用框架 文档对象 视窗对象

1. 启动 创建 创建OnCreate OnInitUpdata OnUpdate

2. 编辑更新

UpdateAllView

OnUpdate

Page 125: Visual  C++  MFC  编程基础

126

文档与视窗的交互 (2/2)用户 应用框架 文档对象 视窗对象

3. 程序更新数据UpdateAllView

OnUpdate

4. 退出撤消 撤消