交互式绘图软件开发_第1页
交互式绘图软件开发_第2页
交互式绘图软件开发_第3页
交互式绘图软件开发_第4页
交互式绘图软件开发_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、2021-4-282021-4-281 前言前言 什么是什么是Windows编程?编程? 1. 你编写的程序是否遵循了你编写的程序是否遵循了Windows的编的编 程模型程模型? 2.是否调用了是否调用了Windows操作系统的操作系统的应用程序应用程序 编程接口函数编程接口函数API,或者对其封装后的,或者对其封装后的 基础类库(如基础类库(如MFC)。)。 前言前言 关于关于Windows编程的三个问题编程的三个问题 1. 什么是什么是Windows API? 2. 什么是什么是MFC? 3. 为什么要使用为什么要使用MFC? 2021-4-282交互式绘图软件开发交互式绘图软件开发 前言

2、前言 1. 什么是什么是 Windows API? 从从WindowsWindows应用程序,操作系统,计算机硬件之间应用程序,操作系统,计算机硬件之间 的相互关系开始说起的相互关系开始说起 应用程序的机能就是:通知操作系统控制计算机硬应用程序的机能就是:通知操作系统控制计算机硬 件,执行某个具体的动作,完成特定的功能。件,执行某个具体的动作,完成特定的功能。 例如:操作系统能够控制声卡发出声音,但它并不例如:操作系统能够控制声卡发出声音,但它并不 知道应该何时发出何种声音,需要应用程序告诉操作系知道应该何时发出何种声音,需要应用程序告诉操作系 统该发出什么样的声音。统该发出什么样的声音。 那

3、么,应用程序是如何通知操作系统执行某个功能的呢?那么,应用程序是如何通知操作系统执行某个功能的呢? 2021-4-283交互式绘图软件开发交互式绘图软件开发 前言前言 1. 什么是什么是 Windows API?(续)?(续) 有过编程经验的同学都应该知道,在传统应用程序中有过编程经验的同学都应该知道,在传统应用程序中 要完成某个功能,都是以要完成某个功能,都是以函数调用函数调用的形式实现的,同样,的形式实现的,同样, Windows应用程序也是以函数调用的方式来通知操作系统应用程序也是以函数调用的方式来通知操作系统 执行相应的功能的。执行相应的功能的。 操作系统所能够完成的每一个特殊功能通常

4、都有一个操作系统所能够完成的每一个特殊功能通常都有一个 函数与其对应,也就是说,操作系统把它所能够完成的函数与其对应,也就是说,操作系统把它所能够完成的 功能以函数的形式提供给应用程序使用,应用程序对这功能以函数的形式提供给应用程序使用,应用程序对这 些函数的调用就叫做系统调用,这些函数的集合就是些函数的调用就叫做系统调用,这些函数的集合就是 Windows应用程序编程接口应用程序编程接口(Application Programming Interface),简称,简称Windows API。 如如CreateWindow就是一个就是一个API函数,应用程序中调用这个函数,操函数,应用程序中调

5、用这个函数,操 作系统就会按照该函数提供的参数信息产生一个相应的窗口。作系统就会按照该函数提供的参数信息产生一个相应的窗口。 2021-4-284交互式绘图软件开发交互式绘图软件开发 前言前言 1. 什么是什么是 Windows API?(续)?(续) Windows Windows编程的本质:编程的本质: 利用利用Windows API 函数编写应用程序,让操作系统完成某种特函数编写应用程序,让操作系统完成某种特 定的功能定的功能 。 Windows/System32/Kernel32.dll、 USER32.dll、GDI32.dll Windows API Windows API 函数在

6、哪里?函数在哪里? 怎样使用怎样使用Windows APIWindows API? C和和Windows SDK开发包(开发包( API函数是用纯函数是用纯C写的,都在写的,都在 windows.h中有声明)中有声明) 然而如今,然而如今,C+C+取代了取代了C C,成为专业,成为专业WindowsWindows程序员首选的程序员首选的 语言,所以语言,所以MFCMFC横空出世了横空出世了 2021-4-285交互式绘图软件开发交互式绘图软件开发 前言前言 2. 什么是什么是 MFC? MFC英文全称为英文全称为Microsoft Foundation Classes (微(微 软基础类库),

7、是把软基础类库),是把Windows API进行封装的类库,它是进行封装的类库,它是 一个类的集合,通过覆盖一个类的集合,通过覆盖Windows API,为编程提供了一,为编程提供了一 个个面向对象面向对象的界面。的界面。 MFC使使Windows程序员能够利用程序员能够利用C+面象对象的特面象对象的特 性进行编程。性进行编程。 2021-4-286交互式绘图软件开发交互式绘图软件开发 前言前言 3. 为什么要使用为什么要使用MFC? n 可重用性可重用性 n 封装后使方法和属性更紧密的捆绑封装后使方法和属性更紧密的捆绑 n 常用的功能自动化,减少编写代码的数量常用的功能自动化,减少编写代码的

8、数量 n 提供应用程序的框架结构提供应用程序的框架结构 框架结构提供了抽象功能,它远远超出了框架结构提供了抽象功能,它远远超出了Windows API的功能。例如:的功能。例如:MFC的文档的文档/视图体系结构在视图体系结构在API上上 建造了一个功能强大的基础结构,它把程序中数据的图建造了一个功能强大的基础结构,它把程序中数据的图 形表示(或称为视图)与数据本身分开。这种抽象对形表示(或称为视图)与数据本身分开。这种抽象对 API而言完全是陌生的,而且在而言完全是陌生的,而且在MFC框架结构之外或类框架结构之外或类 似的类库中也不存在。似的类库中也不存在。 2021-4-287交互式绘图软件

9、开发交互式绘图软件开发 关于教材关于教材 参考书籍(参考书籍(Windows 编程四大法宝)编程四大法宝) VC深入详解深入详解孙鑫著孙鑫著 电子工业出版社电子工业出版社 深入浅出深入浅出MFC(第二版)侯俊杰著(第二版)侯俊杰著 华中科技大学出版社华中科技大学出版社 Windows程序设计程序设计(第五版)(第五版)Charles Petzold著著 北京大学出版社(北京大学出版社( Microsoft Press ) Visual C+技术内幕技术内幕(第四版)(第四版)David J. Kruglinski著著 清华大学出版社(清华大学出版社( Microsoft Press ) 202

10、1-4-288交互式绘图软件开发交互式绘图软件开发 第一讲 Windows程序内部运行原理 2021-4-289交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 Windows编程模型编程模型 事件驱动编程模型事件驱动编程模型以消息为基础,事件驱动之以消息为基础,事件驱动之 WM_PAINT WM_KEYDOWN WM_LBUTTONDOWN 消息响应消息响应 消息响应消息响应 消息响应消息响应 DefWindowProc 来源于操作系统的消来源于操作系统的消 息息 消消息队列息队列 WinMain 消息循环消息循环 发送消息发送消息 窗口过程窗口过程 未

11、处理的消息未处理的消息 应用程序应用程序 窗口窗口 交还给操作系统交还给操作系统 操作系统操作系统 实现特定功能实现特定功能 2021-4-2810交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 消息、消息队列、消息循环消息、消息队列、消息循环 应用程序开始执行后,系统都会为该程序应用程序开始执行后,系统都会为该程序 创建一个创建一个消息队列消息队列,这个消息队列用来存放该,这个消息队列用来存放该 程序创建的窗口的消息(消息通常与窗口相程序创建的窗口的消息(消息通常与窗口相 关)。关)。 例如,当我们按下鼠标左键的时候,将会例如,当我们按下鼠标左键的时候

12、,将会 产生消息,系统会将这个消息放到窗口所属的产生消息,系统会将这个消息放到窗口所属的 应用程序的消息队列中,等待应用程序的处理。应用程序的消息队列中,等待应用程序的处理。 产生的消息都会依次放到消息队列中,而应用产生的消息都会依次放到消息队列中,而应用 程序则通过一个程序则通过一个消息循环消息循环不断地从消息队列中不断地从消息队列中 取出消息,并进行响应。取出消息,并进行响应。 2021-4-2811交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 消息响应与窗口过程消息响应与窗口过程 如用户在某个程序活动时按了一下键盘,如用户在某个程序活动时按了一下

13、键盘, 操作系统马上能够感知到这一事件,并且能够操作系统马上能够感知到这一事件,并且能够 知道用户按下的是哪一个键,操作系统并不决知道用户按下的是哪一个键,操作系统并不决 定对这一事件如何作出反应,而是将这一事件定对这一事件如何作出反应,而是将这一事件 转交给应用程序,由应用程序决定如何对这一转交给应用程序,由应用程序决定如何对这一 事件作出反应。对事件作出反应的过程就是事件作出反应。对事件作出反应的过程就是消消 息响应息响应,各种消息响应放在一起组成了,各种消息响应放在一起组成了窗口过窗口过 程程。 2021-4-2812交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制

14、程序内部运行机制 Windows API 中消息的定义中消息的定义 操作系统是怎样将感知到的事件传递给应用程序操作系统是怎样将感知到的事件传递给应用程序 的呢?这是通过消息机制的呢?这是通过消息机制(Message)来实现的。操作系来实现的。操作系 统将每个事件都包装成一个称为消息的统将每个事件都包装成一个称为消息的结构体结构体MSG来来 传递给应用程序,参看传递给应用程序,参看MSDN。 MSG结构定义如下:结构定义如下: typedef struct tagMSG HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD ti

15、me; POINT pt; MSG; 2021-4-2813交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 小小知识点小小知识点“句柄句柄” 句柄(句柄(HANDLE),资源的标识。),资源的标识。 操作系统要管理和操作各种各样的资源,都是通过操作系统要管理和操作各种各样的资源,都是通过 句柄来找到对应的资源。按资源的类型,又可将句柄细句柄来找到对应的资源。按资源的类型,又可将句柄细 分成图标句柄(分成图标句柄(HICON),光标句柄(),光标句柄(HCURSOR),), 窗口句柄(窗口句柄(HWND),应用程序实例句柄),应用程序实例句柄 (HINST

16、ANCE)等等各种类型的句柄。)等等各种类型的句柄。 操作系统给每一个窗口指定的一个唯一的标识号即操作系统给每一个窗口指定的一个唯一的标识号即 窗口句柄。窗口句柄。 2021-4-2814交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 小小知识点小小知识点API中对数据类型的宏定义中对数据类型的宏定义 好处:让数据类型具备语义信息,从变量的类型好处:让数据类型具备语义信息,从变量的类型 就可以区分变量的用途!就可以区分变量的用途! int x, y; x = 30; y = 30; /x和和y既可以用来表示坐标点,也可以用来表示宽度和高度,还可既可以用来

17、表示坐标点,也可以用来表示宽度和高度,还可 以用来表示身高和体重。以用来表示身高和体重。 typedef int WIDTH typedef int HEIGHT WIDTH x; HEIGHT y; /我们从变量的类型上就可以知道我们从变量的类型上就可以知道x和和y是用来表示宽度和高度。是用来表示宽度和高度。 2021-4-2815交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 编写编写Windows应用程序的要素应用程序的要素 消息响应消息响应 消息响应消息响应 消息响应消息响应 DefWindowProc WinMain 消息循环消息循环 发送消息

18、发送消息 窗口过程窗口过程 未处理的消息未处理的消息 应用程序应用程序 1 1 入口函数入口函数WinMain 2 2 创建窗口创建窗口 3 3 消息循环与发送消息消息循环与发送消息 4 4 窗口过程与消息响应窗口过程与消息响应 消息消息 窗口窗口 2021-4-2816交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 1.入口函数入口函数WinMain int WINAPI WinMain( HINSTANCE hInstance, / 当前应用程序实例句炳当前应用程序实例句炳 HINSTANCE hPrevInstance, / 永远为永远为NULL

19、LPSTR lpCmdLine, / 命令行参数命令行参数 int nCmdShow / 窗口显示时的状态窗口显示时的状态 ); 2021-4-2817交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 2. 创建窗口创建窗口 创建一个完整的窗口需要经过下面四个操作步骤:创建一个完整的窗口需要经过下面四个操作步骤: Step1: 设计一个窗口类;设计一个窗口类; Step2: 注册窗口类;注册窗口类; Step3: 创建窗口;创建窗口; Step4: 显示及更新窗口。显示及更新窗口。 2021-4-2818交互式绘图软件开发交互式绘图软件开发 Windows

20、 程序内部运行机制程序内部运行机制 设计窗口类设计窗口类 typedef struct _WNDCLASS UINT style; /窗口类样式窗口类样式 WNDPROClpfnWndProc; /窗口过程函数指针窗口过程函数指针 int cbClsExtra; /窗口类附加内存字节数,通常为窗口类附加内存字节数,通常为0 int cbWndExtra; /窗口附加内存字节数,通常为窗口附加内存字节数,通常为0 HANDLE hInstance; /应用程序实例句柄应用程序实例句柄 HICON hIcon; /标题栏图标标题栏图标 HCURSOR hCursor; /光标光标 HBRUSH h

21、brBackground; /窗口背景颜色窗口背景颜色 LPCTSTR lpszMenuName; /菜单资源名称菜单资源名称 LPCTSTR lpszClassName; /窗口类名称窗口类名称 WNDCLASS; 2021-4-2819交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 创建窗口创建窗口 HWND CreateWindow( LPCTSTR lpClassName, / 已注册的窗口类名称已注册的窗口类名称 LPCTSTR lpWindowName, / 窗口标题栏中显示的文本窗口标题栏中显示的文本 DWORD dwStyle, / 窗口

22、样式窗口样式 int x, / 水平坐标水平坐标 int y, / 垂直坐标垂直坐标 int nWidth, / 宽度宽度 int nHeight, / 高度高度 HWND hWndParent, / 父窗口句柄父窗口句柄 HMENU hMenu, / 菜单句柄菜单句柄 HINSTANCE hInstance, / 应用程序实例句柄应用程序实例句柄 LPVOID lpParam / 用于多文档程序的附加参数,单文档为用于多文档程序的附加参数,单文档为NULL ); 2021-4-2820交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 3. 消息循环与发送

23、消息消息循环与发送消息 MSG msg; while (GetMessage( /消息解释消息解释 DispatchMessage( /将消息发送到将消息发送到“窗口过程窗口过程” 2021-4-2821交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 GetMessage BOOL GetMessage( LPMSG lpMsg, / 消息结构体指针,返回消息信息消息结构体指针,返回消息信息 HWND hWnd, / 窗口句柄窗口句柄 ,通常设为,通常设为NULL UINT wMsgFilterMin, / 消息过滤最小值消息过滤最小值 UINT wMs

24、gFilterMax / 消息过滤最大值消息过滤最大值 ); GetMessage从线程的消息队列中取出消息,取出的消息从线程的消息队列中取出消息,取出的消息 保存在事先定义好的消息的结构体对象中。保存在事先定义好的消息的结构体对象中。 GetMessage函数取到除函数取到除WM_QUIT外的消息均返回非零外的消息均返回非零 值,只有在接收到值,只有在接收到WM_QUIT消息时,才返回消息时,才返回0。 什么时候才会收到什么时候才会收到WM_QUIT呢?(见窗口过程)呢?(见窗口过程) 2021-4-2822交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机

25、制 TranslateMessage TranslateMessage TranslateMessage函数用于将虚拟键消息转换函数用于将虚拟键消息转换 为字符消息。当我们敲击键盘上的某个字符键时,为字符消息。当我们敲击键盘上的某个字符键时, 系统将产生系统将产生WMWM_KEYDOWN_KEYDOWN和和WM_KEYUPWM_KEYUP消息。这两消息。这两 个消息的附加参数(个消息的附加参数(wParamwParam和和lParamlParam)包含的是虚)包含的是虚 拟键代码和扫描码等信息,而我们在程序中往往需拟键代码和扫描码等信息,而我们在程序中往往需 要得到某个字符的要得到某个字符的A

26、SCIIASCII码,码,TranslateMessageTranslateMessage这个这个 函数就可以将函数就可以将WM_KEYDOWNWM_KEYDOWN和和WM_KEYUPWM_KEYUP消息的组合转消息的组合转 换为一条换为一条WM_CHARWM_CHAR消息,该消息的消息,该消息的WParamWParam附加参数包附加参数包 含了字符的含了字符的ASCIIASCII码),并将转换后的新消息投递到码),并将转换后的新消息投递到 调用线程的消息队列中。注意,调用线程的消息队列中。注意,TranslateTranslate函数并不函数并不 会修改原有的信息,他只是产生新的消息并投递到

27、会修改原有的信息,他只是产生新的消息并投递到 消息队列中。消息队列中。 2021-4-2823交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 DispatchMessage DispatchMessage DispatchMessage分派一个消息到窗口过程。分派一个消息到窗口过程。 由窗口过程函数对消息进行处理。由窗口过程函数对消息进行处理。 DispatchMessageDispatchMessage实际上是将消息回传给操作实际上是将消息回传给操作 系统,再由操作系统调用窗口过程函数对消息进行系统,再由操作系统调用窗口过程函数对消息进行 处理。处理。

28、 2021-4-2824交互式绘图软件开发交互式绘图软件开发 对于一条消息,操作系统到底调用应用程序中的哪个函对于一条消息,操作系统到底调用应用程序中的哪个函 数来处理呢?数来处理呢? 操作系统调用的就是接受消息的窗口所属的类型中的操作系统调用的就是接受消息的窗口所属的类型中的 lpfnWndProclpfnWndProc成员(还记得窗口类的第二个成员吗?)指定的成员(还记得窗口类的第二个成员吗?)指定的 函数。每一种不同类型的窗口都有自己专用的回调函数,该函数。每一种不同类型的窗口都有自己专用的回调函数,该 函数就是通过函数就是通过lpfnWndProclpfnWndProc成员指定的,也称

29、回调函数。成员指定的,也称回调函数。 回调函数的原理是这样的,当应用程序收到给某一窗口回调函数的原理是这样的,当应用程序收到给某一窗口 的消息时,就应该调用某一函数来处理这条消息。这一调用的消息时,就应该调用某一函数来处理这条消息。这一调用 过程不用应用程序自己来实施,而由操作系统来完成,但是,过程不用应用程序自己来实施,而由操作系统来完成,但是, 回调函数本身的代码必须由应用程序自己完成。回调函数本身的代码必须由应用程序自己完成。 Windows 程序内部运行机制程序内部运行机制 窗口过程函数窗口过程函数 2021-4-282021-4-2825交互式绘图软件开发交互式绘图软件开发 Wind

30、ows 程序内部运行机制程序内部运行机制 5. 窗口过程与响应消息窗口过程与响应消息 LRESULT CALLBACK MyWndProc( HWND hwnd, / handle to window UINT uMsg, / message identifier WPARAM wParam, / first message parameter LPARAM lParam / second message parameter ) switch (uMsg) case WM_PAINT: /响应消息响应消息 case WM_KEYDOWN: /响应消息响应消息 case WM_LBUTTONDO

31、WN: /响应消息响应消息 default: return DefWindowProc(hwnd,uMsg,wParam,lParam); return 0; 2021-4-2826交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 回调函数回调函数 凡是由你设计而却由凡是由你设计而却由WindowsWindows系统调用的函数,系统调用的函数, 统称为统称为CallbackCallback函数。这些函数都有一定的类型,函数。这些函数都有一定的类型, 以配合以配合WindowsWindows的调用操作。的调用操作。 除了窗口过程函数,除了窗口过程函数,Win

32、dows API还有一些其还有一些其 它的回调函数,例如它的回调函数,例如SetTimer、LineDDA、 EnumObject。这种函数会在进行某种行为之后或满。这种函数会在进行某种行为之后或满 足某种状态之时,操作系统自动调用该函数。足某种状态之时,操作系统自动调用该函数。 2021-4-282021-4-2827交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 小小知识:函数的三种调用方式小小知识:函数的三种调用方式 n_cdecl 是是C/C+和和MFC程序默认使用的调用约定,也可以在函数声明程序默认使用的调用约定,也可以在函数声明 时加上时加上

33、_cdecl关键字来手工指定。采用关键字来手工指定。采用_cdecl约定时,函数参数按照从约定时,函数参数按照从 右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此, 实现可变参数的函数只能使用该调用约定。由于每一个使用实现可变参数的函数只能使用该调用约定。由于每一个使用_cdecl约定约定 的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。 n_stdcall 调用约定用于调用调用约定用于调用Win32 API函数。采用函数。采用_stdc

34、all约定时,函数约定时,函数 参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的 栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此 被调用的函数可以在返回前用一条被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。指令直接清理传递参数的堆栈。 n_fastcall 约定用于对性能要求非常高的场合。约定用于对性能要求非常高的场合。_fastcall约定将函数的从约定将函数的从 左边开始的两个大小不大于左边开始的两个大小不大于4个字

35、节(个字节(DWORD)的参数分别放在)的参数分别放在ECX 和和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返 回前清理传送参数的堆栈。回前清理传送参数的堆栈。_fastcall可以写成可以写成_fastcall。 2021-4-282021-4-2828交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 三种调用方式的特别说明三种调用方式的特别说明 n 在默认情况下,在默认情况下,VC采用采用_cdecl方式方式,因此可以省略因此可以省略. n WINAPI一般用于修饰动态链接库中导

36、出函数一般用于修饰动态链接库中导出函数 n CALLBACK仅用于修饰回调函数仅用于修饰回调函数 2021-4-282021-4-2829交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 DefWindowProc 我们的程序无论多大都不可能将所有的消息都处理,我们的程序无论多大都不可能将所有的消息都处理, 所以我们必须有一个机制让不感兴趣的、不需要我们所以我们必须有一个机制让不感兴趣的、不需要我们 处理的消息,交还给处理的消息,交还给WindowsWindows操作系统为我们处理,这操作系统为我们处理,这 个过程就是由个过程就是由DefWindowPro

37、cDefWindowProc函数来实现的,也是每函数来实现的,也是每 个程序所必备的。个程序所必备的。 2021-4-282021-4-2830交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 WM_DESTROY 当窗口被销毁时会产生这个消息(通常也是准备退出当窗口被销毁时会产生这个消息(通常也是准备退出 应用程序的时候),对于这个消息的响应是每个程序所应用程序的时候),对于这个消息的响应是每个程序所 必备的。怎样响应呢?必备的。怎样响应呢? 响应方式就是调用响应方式就是调用PostQuitMessagePostQuitMessage函数,该函数会函数,

38、该函数会 在消息队列中添加一个在消息队列中添加一个WM_QUITWM_QUIT消息,准备让由消息循环消息,准备让由消息循环 中的中的GetMessageGetMessage取得。当消息循环中的收到取得。当消息循环中的收到WM_QUITWM_QUIT消消 息时,息时,GetMessageGetMessage会传回会传回0 0,从而结束消息循环,进而,从而结束消息循环,进而 结束整个程序。结束整个程序。 2021-4-282021-4-2831交互式绘图软件开发交互式绘图软件开发 Windows 程序内部运行机制程序内部运行机制 WM_QUIT ASSERT_VALID(pDoc); if (!p

39、Doc) return; / TODO: 在此处为本机数据添加绘制代码 2021-4-282021-4-2837交互式绘图软件开发交互式绘图软件开发 每次需要重绘窗口时(程序启动/窗口大小改 变/全部或部分窗口重现/程序员调用 RedrawWindow或UpdateWindow),应用程序 框架都会调用该CWnd的消息响应成员函数 (的覆盖)来绘制窗口客户区。 在Windows中,绘图一般在视图窗口的客户区 进行,使用的是MFC的设备上下文(DC = Device-Context)类CDC中各种绘图函数。 在绘图前,必须先得到客户区大小和DC、设置 绘图颜色,然后再根据文档数据或用户操作来 绘

40、制图形。 2021-4-282021-4-2838交互式绘图软件开发交互式绘图软件开发 1 几何对象的结构和类 为了使用绘图函数,应该先了解绘图所用到的几种表示几何 对象的结构和类。这些结构和类分别定义在头文件windef.h 和afxwin.h中。 1点 1)点结构POINT 点数据结构POINT用来表示一点的x、y坐标: typedef struct tagPOINT LONG x; LONG y; POINT; 2021-4-282021-4-2839交互式绘图软件开发交互式绘图软件开发 2)点类CPoint 点类CPoint为一个没有基类的独立类,封装了 POINT结构,有成员变量x和

41、y,其构造函数有 5种: CPoint( ); CPoint( int initX, int initY ); CPoint( POINT initPt ); CPoint( SIZE initSize ); CPoint( LPARAM dwPoint ); / 低字设为x、高字 设为y 2021-4-282021-4-2840交互式绘图软件开发交互式绘图软件开发 CPoint类还定义了4个平移和设置函数: void Offset(int xOffset, int yOffset); void Offset(POINT point); void Offset(SIZE size); void

42、 SetPoint(int X, int Y); CPoint类还重载了+、-、+=、-=、=、!=等 运算符来支持CPoint对象和CPoint、POINT、 SIZE对象之间的运算。 2021-4-282021-4-2841交互式绘图软件开发交互式绘图软件开发 2大小 1)大小结构SIZE 大小(size尺寸)结构SIZE用来表示矩形的宽cx和 高cy: typedef struct tagSIZE LONG cx; LONG cy; SIZE; 2021-4-282021-4-2842交互式绘图软件开发交互式绘图软件开发 2)大小类CSize 大小类CSize也为一个没有基类的独立类,封

43、装了 SIZE结构,有成员变量cx和cy,其构造函数也有5 种: CSize( ); CSize( int initCX, int initCY ); CSize( SIZE initSize ); CSize( POINT initPt ); CSize( DWORD dwSize ); / 低字设为cx、高字设为 cy CSizet类也重载了+、-、+=、-=、=、!=等运算符 来支持CSize对象和CSize、POINT、SIZE、RECT对 象之间的运算。 2021-4-282021-4-2843交互式绘图软件开发交互式绘图软件开发 3矩形 1)矩形结构RECT 矩形结构RECT定义了

44、矩形的左上角与右下角 的坐标: typedef struct tagRECT LONG left; LONG top; LONG right; LONG bottom; RECT; 2021-4-282021-4-2844交互式绘图软件开发交互式绘图软件开发 2)矩形类CRect 矩形类CRect也为一个没有基类的独立类,封装了RECT 结构,有成员变量left、top、right和bottom,其构造 函数有6种: CRect( ); CRect( int l, int t, int r, int b ); CRect( const RECT CRect( LPCRECT lpSrcRect

45、 ); CRect( POINT point, SIZE size ); CRect( POINT topLeft, POINT bottomRight ); CRect类重载了=,+、-,+=、-=,=、!=, int Height( ) const; CSize Size( ) const; CPoint CPoint CPoint CenterPoint( ) const; void S(); BOOL IsRectEmpty( ) const; BOOL PtInRect( POINT point ) const; void SetRect( int x1, int y1, int x

46、2, int y2 ); void SetRect(POINT topLeft, POINT bottomRight); void OffsetRect(int x, int y); void MoveToXY(int x, int y); 2021-4-282021-4-2846交互式绘图软件开发交互式绘图软件开发 3) 判断点是否在矩形中 有时需要判断某点(如鼠标位置)是否在某一矩形区域中, 这可以调用CRect类的PtInRect函数来做: BOOL PtInRect( POINT point ) const; 该函数当点point在其矩形区域内时,返回真。注意,该矩 形区域不包括矩形的

47、右边界和底边界。例如: CRect rect( 10, 10, 371, 267 ); void CDrawView:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default if ( rect.PtInRect( point ) ) . . . . CView:OnLButtonUp(nFlags, point); 2021-4-282021-4-2847交互式绘图软件开发交互式绘图软件开发 2 客户区大小和DC 在绘图前,必须先得到客户区大小和设

48、备上 下文DC。 1获得客户区 绘图一般都是在视图窗口的客户区进行,而 客户区的大小在运行时可由用户改变,为了 使绘制的图形能随窗口大小自动改变,必须 先得到当前客户区大小的数据(宽w和高h)。 2021-4-282021-4-2848交互式绘图软件开发交互式绘图软件开发 获取客户区大小的方法有如下两种: 1)在消息响应函数OnSize中获得 利用属性窗口的信息页,在视图类中添加 WM_SIZE消息的响应函数OnSize。该函数在窗口 第一次显示或窗口大小被改变时会被Windows系 统调用。其输入参数中的cx和cy就是客户区大小 的宽和高,可将它们赋值给类变量(如m_iW和 m_iH)供绘图

49、时使用。例如 void CDrawView:OnSize(UINT nType, int cx, int cy) CView:OnSize(nType, cx, cy); / TODO: 在此处添加消息处理程序代码 m_iW = cx; m_iH = cy; 2021-4-282021-4-2849交互式绘图软件开发交互式绘图软件开发 其中,nType的值为: SIZE_MAXIMIZED(窗口已被最大化) SIZE_MINIMIZED(窗口已被最小化) SIZE_RESTORED(窗口已被改变大小) SIZE_MAXHIDE(其他窗口被最大化) SIZE_MAXSHOW(其他窗口从最大化还原

50、) 2021-4-282021-4-2850交互式绘图软件开发交互式绘图软件开发 2)调用成员函数GetClientRect得到 可在绘图前,定义一个矩形变量rect,然后再 调用CWnd类的成员函数GetClientRect: void GetClientRect( LPRECT lpRect ) const; 得到当前客户区矩形的数据,其中的右(right) 与底(bottom)就是客户区的宽与高(其左left 与顶top都为0)。例如: RECT rect; GetClientRect( int w = rect.right, h = rect.bottom; 2021-4-282021

51、-4-2851交互式绘图软件开发交互式绘图软件开发 2DC 在Windows中,绘图使用的是MFC的DC(Device- Context, 设备上下文)类CDC中各种绘图函数。 1)CDC类 CDC是CObject的直接派生类,CDC类自己也有若 干派生类,其中包括窗口客户区DC所对应的 CClientDC类、OnPaint和OnDraw消息响应函数的 输入参数中使用的CPaintDC类、图元文件对应的 CMetaFileDC类和整个窗口所对应的CWindowDC 类。 CDC类中有许多成员函数,可以用来设置各种绘 图环境、属性和参数,以及绘制各种图形和图像 等,将在后面陆续加以介绍。 202

52、1-4-282021-4-2852交互式绘图软件开发交互式绘图软件开发 2)获得DC 可以从OnDraw函数的输入参数pDC或调用CWnd的成员函 数GetDC: CDC* GetDC( );来获得DC的指针。 3)释放DC 因为Windows限制可用DC的数量,所以DC属于稀缺的公用 资源。因此,对每次获得的DC,在使用完成后必须立即释 放。 从OnDraw函数的输入参数pDC获得的DC,在该函数运行结 束后,系统会自动释放。但由GetDC所获得的DC,必须自 己来释放,这可以通过调用CWnd的成员函数ReleaseDC来 完成: int ReleaseDC( CDC* pDC ); / 成

53、功返回非0 2021-4-282021-4-2853交互式绘图软件开发交互式绘图软件开发 例如: void CDrawView:OnLButtonUp(UINT nFlags, CPoint point) ReleaseCapture(); if (m_bLButtonDown) CDC* pDC = GetDC(); pDC-SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0); pDC-SelectStockObject(NULL_BRUSH); pDC- Ellipse (rect); ReleaseDC(pDC); m_bLButtonDo

54、wn = FALSE; CView:OnLButtonUp(nFlags, point); 2021-4-282021-4-2854交互式绘图软件开发交互式绘图软件开发 3 CDC绘图工具绘图工具 1颜色颜色 Windows中的颜色一般用中的颜色一般用4个字节表示个字节表示(0BGR(整(整 数)数) = R G B 0(字节序)(字节序) Intel CPU低位字节在低位字节在 前前),Win32 API中定义了一个专门表示颜色索引中定义了一个专门表示颜色索引 值的变量类型值的变量类型COLORREF:(windef.h) typedef DWORD COLORREF; / 0 x00bbg

55、grr 和一个由红绿蓝三原色构造颜色值的宏和一个由红绿蓝三原色构造颜色值的宏RGB: (wingdi.h) #define RGB(r,g,b) (COLORREF)(BYTE)(r)|(WORD)(BYTE)(g)8)| (DWORD)(BYTE)(b) 8) #define GetBValue(rgb) (LOBYTE(rgb)16) 其中:其中: typedef unsigned long ULONG_PTR; typedef ULONG_PTR DWORD_PTR; #define LOBYTE(w) (BYTE)(DWORD_PTR)(w) / DWORD rgb COLORREF

56、col BYTE GetGValue(DWORD rgb); BYTE GetBValue(DWORD rgb); 2021-4-282021-4-2858交互式绘图软件开发交互式绘图软件开发 2)画笔 在Windows中,用笔(PEN)来绘制线状图形。 在MFC中,笔的属性和功能由Cpen类提供。笔的 创建与使用的步骤如下: a)创建笔类Cpen对象方法 方法一:使用构造函数Cpen: Cpen(int nPenStyle,int nWidth,COLORREF crColor) 其中:nPenStyle为笔的图线种类,如下表 2021-4-282021-4-2859交互式绘图软件开发交互式

57、绘图软件开发 符号常量符号常量数值数值图线种类名称图线种类名称 PS_SOLD0实线 PS_DASH1虚线 PS_DOT2点线 PS_DASHDOT3点划线 PS_DASHDOTDOT4双点划线 PS_NULL5空笔 PS_INSIDEFRME6框内 注意:注意:14号笔风格只有在笔宽号笔风格只有在笔宽=0或或1时有效,笔宽时有效,笔宽1时总为实心的。时总为实心的。 2021-4-282021-4-2860交互式绘图软件开发交互式绘图软件开发 nWidth为笔宽,与映射模式有关,使用默认映射时为像素, 若nWidth=0,则不论什么映射模式,笔宽都为一个像素; crColor为笔的颜色值。 例

58、如: Cpen * pGrayPen = new Cpen(PS_SOLID,0,RGB(128,128,128); Cpen grayPen(PS_SOLID,0,RGB(128,128,128); 2021-4-282021-4-2861交互式绘图软件开发交互式绘图软件开发 方法二:使用CDC成员函数CreatePen: BOOL CreatePen(int nPenStyle,int nWidth,COLORREF crColor); 例如: Cpen grayPen; grayPen.CreatePen(PS_SOLID,0,RGB(128,128,128); b)将画笔对象选入设备上

59、下文 为了能使用我们所创建的笔对象,必须先将它选入设备上下 文,方法如下。 调用CDC的成员函数SelectObject来完成: CPen * SelectObject(CPen *pPen); 返回值为指向原来笔对象的指针(一般将其保存下来,供下 次再装入时使用)。例如: pOldPen=pDC- SelectObject( 2021-4-282021-4-2862交互式绘图软件开发交互式绘图软件开发 调用CDC的另一个成员函数SelectStockObject将 其选入DC,其函数原型为: Virtual CGdiObject * SelectStockObject(int nIndex)

60、; 画笔中nIndex含义如下表: 例如: pDC-SelectStockObject(BLACK_PEN); 符号常数符号常数数值数值笔笔 BLACK_PEN7黑色笔 WHITE_PEN6白色笔 NULL_PEN8空笔 2021-4-282021-4-2863交互式绘图软件开发交互式绘图软件开发 C)删除使用过的画笔对象 要删除使用过的笔对象,必须先将它从设备 上下文中释放出来后,然后才能删除。释放的方法 是装入其他的笔对象(一般是重新装入原来的笔对 象)。例如: pDC-SelectObject(pOldPen); 删除比对象方法有如下几种: 方法一:调用笔类CDC的成员函数DeleteO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论