Visual C++ MFC 编程基础 .

Post on 15-Mar-2016

185 Views

Category:

Documents

9 Downloads

Preview:

Click to see full reader

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

Transcript

1

Visual C++ MFC 编程基础 .

2

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

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

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

3

主要学习内容Windows 系统引擎

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

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

4

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

5

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

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

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

6

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

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

– (Windows 95/NT)

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

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

7

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

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

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

8

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

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

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

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

9

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

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

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

10

交互控制手段 Windows 系统消息

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

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

11

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

12

1.4 软件开发策略 开发需求

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

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

13

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

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

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

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

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

14

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

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

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

15

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

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

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

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

16

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

17

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

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

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

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

Windows

应用程序 应用程序

18

控制关系 Windows 系统是主控方

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

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

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

– 也依靠消息驱动体系

19

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

源程序*.C/*.CPP

目标程序*.OBJ

可执行文件*.EXE

可执行程序*.EXE

资源描述*.RC

库函数*.LIB

模块定义*.DEF

资源文件*.RES

编译器

连接器 资源连接

开发工具

资源编译

20

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

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

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

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

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 Ó¦ Óó Ì Ðò ×é ³ É½á ¹ ¹

22

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

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

23

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

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

标题, … );

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

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

24

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

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

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

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

25

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

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

{if( 是首次实例 )

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

}

26

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

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

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

27

2.3 应用程序简例 WinMain 函数

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

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

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

28

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

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

消息识别 msg wParam

29

窗口函数的实现各 case 分支

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

30

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

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

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

31

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

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

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

窗口函数设计要领

32

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

33

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

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

END菜单的指定

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

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

34

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

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

35

程序的调试跟踪调试

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

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

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

36

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

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

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

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

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 代表窗口用户区

38

窗口重画显示原理

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

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

ateRect 等 API 函数调用时

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); // 释放设备句柄

40

补充说明 消息属性的获取

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

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

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

41

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

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

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

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

– 设备句柄、无效区与 WM_PAINT

42

上机题 1

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

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

43

上机题 2

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

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

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

44

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

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

45

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

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

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

46

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

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

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

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

47

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

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

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

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

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

48

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

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

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

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

49

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

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

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

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

50

MFC 的结构

Ó ¦Ó ó ÌÐ ò

¶ Ô» °¿ ò

Ê ÓÍ ¼

¿ ØÖ Æ¿ ò

¿ ò¼ Ü °¿ Ú

C W n d

Πĵ µ

Πļ þ

Í ¼Ð ÎÉ è± ¸

G D I ¶ ÔÏ ó

² ˵ ¥

Ê ý¾ Ý¿ âÖ §³ Ö

Í ¬² ½¶ ÔÏ ó

Í Ð Å½ Ó¿ Ú

¼ º Ï

Ò ì³ £ ¦À í

CObj ect

51

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

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

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

– 程序设计与调试的需求

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 ); ... }

53

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

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

54

MFC 对象的使用 定义方法:

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

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

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

55

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

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

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

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

56

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

: public CWinApp {public:

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

: public CFrameWnd {public:

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

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!” );} // 创建主窗口结构

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()

调消息循环

59

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

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

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

60

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

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

窗口 API 函数例ShowWindow 、 ScrollWindow 、 SetWindowText

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

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( )

62

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

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

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

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

63

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

64

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

65

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

鼠标双击 启动 构造Windows

WM_CREATE WM_PAINT …

左鼠标按下 WM_LBUTTONDOWN

右鼠标按下 WM_RBUTTONDOWN

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 Ï µÍ ³

67

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

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

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

68

CClientDC 的应用void CMainWnd::OnLButtonDown(

UINT flg, CPoint pt ) {

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

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

}

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 );

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

70

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

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

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

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( )……

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; // 释放设备对象

73

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

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

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

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

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( )

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 ); // 恢复光标,并保存原光标

76

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

77

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

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

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

78

上机题 4

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

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

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

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

79

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

80

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

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

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

81

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

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

82

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

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

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

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

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)

84

4.2 图形输出 GDI 对象

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

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

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

85

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

– MoveTo / GetCurrentPosition 图形输出函数

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

ct, Chord, Pie, Polygon

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 );

87

4.3 图像输出 Windows 的两种位图

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

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

88

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

– CDC memDC;

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

创建 CBitmap 对象– CBitmap bmp;

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

89

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

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

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

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

90

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

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

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

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

– 设置指定点的颜色

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);

}

92

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

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

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

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

93

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

BITMAPINFOHEADER

颜色表颜色屏蔽字

点阵数据

位图尺寸颜色平面数

象素位数。。。

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

DIB头

94

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

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

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

95

DIB 位图的使用 (2/2)

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

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 位图

97

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

98

5.1 资源编辑资源种类

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

99

VC 的资源编辑器新建

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

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

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

– 资源标识符(整数)

100

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

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

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

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

101

对话框模板的编辑 编辑窗

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

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

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 页

103

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

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

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

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

}

104

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

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

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

105

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

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

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

106

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

MFC 支持CButton

CStaticCEditCListBoxCScrollBarCComboBox

107

两种使用方法 作为子窗口

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

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

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

自动生成– 随对话框生成

108

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

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

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

109

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

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

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

110

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

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

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

111

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

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

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

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

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 );

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

113

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

OnInitDialog

OnOK

UpdateData

DoDataExchage

自动调用

程序中直接调用

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 ); // 显示数据}

115

上机题 5

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

116

上机题 6

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

117

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

118

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

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

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

119

生成的程序框架 CDemoApp theApp;

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

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

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

– 继承 CDocument 文档类 CDemoView

– 继承 CView 视窗类

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;

121

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

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

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

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

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

122

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

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

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

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

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

124

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

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

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

125

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

1. 启动 创建 创建OnCreate OnInitUpdata OnUpdate

2. 编辑更新

UpdateAllView

OnUpdate

126

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

3. 程序更新数据UpdateAllView

OnUpdate

4. 退出撤消 撤消

top related