C++课程设计.ppt_第1页
C++课程设计.ppt_第2页
C++课程设计.ppt_第3页
C++课程设计.ppt_第4页
C++课程设计.ppt_第5页
已阅读5页,还剩104页未读 继续免费阅读

下载本文档

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

文档简介

1、C+课程设计,课程设计目的,通过本课程设计教学,为学生提供一个综合运用所学知识,解决实际问题的机会,增强其实践动手能力和工程实践能力,锻炼和培养学生的自学能力,使学生能利用C+语言设计功能较全的一个应用程序,得到程序设计方法、文献资料查询、设计报告写作的综合训练。同时加深对课程所学知识的理解,进一步巩固C+语言语法规则,学会编制结构清晰、风格良好、数据结构适当的C+语言程序。,课程设计任务,参照C+程序设计实践教程中P92的实例,从p106-108的 7-11题中任选一题,在vc+环境下实现(Win32 Console Application,25学时) 编写一个简单的基于MFC的应用程序(5

2、学时) 撰写设计报告,课程设计的基本步骤,分析问题及确定解决方案 综合运用模块化设计思想和面向对象设计思想,使系统结构清晰、合理、简单和易于调试。 详细设计 设计好每一个类及模块,画出程序框图。 编码 静态检查 上机调试 完成设计报告,设计报告包括的内容,问题描述:设计任务及系统需求 系统设计:系统的功能模块结构、各模块的功能;各功能模块的设计思路、主要算法思想(算法流程图或伪代码) 系统调试:调试过程中遇到的主要问题及解决的方法;对设计和编码的回顾讨论和分析;改进思想;收获和体会等 参考文献 附录:主要源程序清单,程序调试,语法错误,逻辑错误 1、插入调试语句 1)设置状态变量 2)设置计数

3、器 3)插入输出语句 2、利用调试工具,进入调试状态 选择“Build-Start Debug-Step Into”或者按“F11”键进入单步执行状态 设置需要观察的变量 选则适当的执行方式,第一章 链 表,链表是最简单也是最常用的一种动态数据结构。它是对动态获得的内存进行组织的一种结构;不同于数组,数组存储数据时,必须事先定义固定的长度(即数组元素个数)。,链表的结点是结构体变量,它可包含若干成员,其中有些成员可以是任何类型,如基本类型、数组类型、结构体类型等,一般用于存储数据元素的信息,称之为数据域;另一些成员是指针类型,是用来存储与之相连的结点的地址,称之为指针域,单向链表的结点只包含一

4、个这样的指针成员。,一、链表的概念,下面是一个单向链表结点的类型说明: struct node int data; struct node *next; /存放下一结点的地址 ; 其中,data成员用于存储一个整数,next成员是指针类型的,它指向struct node类型数据(这就是next所在的结构体类型,每一个结点都属于node类型,在它的成员next中存放下一个结点的地址,程序设计者不必知道各结点的具体地址,只要保证能将下一个结点的地址放到前一结点的成员next中即可。,链表有一个“头指针”变量,图中以head表示,二、内存动态管理运算符,申请一个存储指定数据类型的值的内存空间 = n

5、ew (); 为数组申请内存: = new ;,内存空间申请new new运算符的功能是根据指定数据类型的大小申请一块适当的动态存储区,并返回指向该动态存储空间的起始地址;若申请不成功,则会返回NULL值。 一般将new操作的结果赋给具有相应数据类型的指针变量。,二、内存动态管理运算符,2. 内存空间释放delete 使用new运算符动态分配给用户的存储空间,可以通过使用delete运算符重新归还给系统,若没有使用delete释放该内存区域,则只有等到整个程序运行结束才被系统重新自动回收。,用于释放先前申请到的内存空间: delete ; 用于释放先前为数组申请到的空间: delete ;,例

6、如: float *pf=new float(55.8); int *pa=new int20; int m; int *pi= /释放pa所指的动态数组内存空间,delete只能释放用new申请的动态内存空间。,三、链表的基本操作,链表的基本操作包括建立链表、链表的插入、删除、输出和查找等。 1. 建立链表 所谓建立链表是指一个一个地输入各结点数据,并建立起各结点前后相链的关系。 下面通过一个例子来说明如何建立一个链表。 两种方式:插链表尾、插链表头,三、链表的基本操作,插链表尾:是指新插入的结点总是放在链表尾部。一般地,链表是在一个空链表的基础上逐步插入新结点而成的,空链表是指没有一个结点

7、,此时链表的头指针为空。,用插表尾法建立链表的过程如下: 1) 建立空链表,head = last =NULL; head表示头表头,指向空,表示链表为空, last是表尾指针。 2) 产生新结点p,对新结点的数据域和指针域赋值。由于新插入的结点总是表尾结点,则它的后继结点为空。,三、链表的基本操作,3) 将p结点插入链表,如果head 为NULL,则 head = p; 新结点作为表头,这时链表只有一个结点,否则,last-next=p; 即插入链尾操作。 4) last = p;表示表尾指针last指向新结点p。 5) 循环执行2)4),可继续建立新结点直到结束为止,写一函数采用插表尾法建

8、立一个有n个node结点的单向链表。 struct node int data; struct node *next; ; void creat(node * /置表头、表尾指针为空,此时为空链表,p=new node; /产生一个p所指的动态结点 cinx; p-data=x; p-next=NULL; head=last=p; if(n=1) return; for(i=1;inext=p; cinx; p-data=x; last=p; p-next=NULL; ,2.链表的输出 要依次输出链表中各结点的数据比较容易处理。首先要知道链表头结点的地址,也就是head的值,然后设一个指针变量

9、p,先指向第一个结点,输出p所指结点的数据域的值,然后使p后移一个结点,再输出其数据域的值;依链表顺序而行,依次输出相应结点数据域的值,直到链表的尾结点。,输出链表的函数traverse如下: void traverse (node *head) node *p; p=head; while(p) coutdatanext; /使p指针移动到下一个结点 coutendl; head的值由实参传过来也就是将已有的链表的头指针传给被调用的函数,在traverse函数中从head所指的第一个结点出发,顺序输出各个结点。,3.链表的删除操作 从一个链表中删去一个结点,首先从表头开始,找到被删结点后,只

10、要改变链接关系即可,即修改结点指针域的值,使被删结点的前驱结点的指针域指向被删结点的后继结点。,删除结点算法描述如下: 用指针p指向删除结点,p1指向其前驱结点, 1) p = head ;从第一个结点开始检查; 2) 当 p指向的结点不是满足删除条件的结点且没有到表尾,p1 = p; p = p-next; (移动指针p,继续找) 3) 如果找到了删除结点p,如果 p= = head 删除的是头结点,则 head = head-next ; /*删除头结点*/ else p1-next = p-next ; /*删除p指向的结点*/ 4)delete p; 释放删除结点的内存空间。,删除链表

11、中一个结点的函数erase如下: void erase(node* ,else while(p-data!=no) p1=p; p=p-next; if(p=NULL) coutnext=p-next; delete p; cout删除结点成功endl; ,实例:设计一个学生成绩管理系统。,第二章 MFC编程基础知识,本章介绍MFC的基本原理 Windows操作系统采用了图形用户界面,借助于它提供的API(Application Programming Interface)函数,用户可以编出具有漂亮图形界面的程序。 Windows本身是面向对象的,因此采用面向对象的程序设计更为自然。VC+的微

12、软基础类库(Microsoft Foundation Class Library,MFC)封装了大部分API函数,并提供了一个应用程序框架,简化和标准化了Windows程序设计,因此MFC编程被称为标准Windows程序设计。,第二章 MFC编程基础知识(选读),2.1 传统的Windows编程,2.3 MFC基础类及其层次结构,2.5 MFC对象和Windows对象,2.4 MFC编程,2.7 MFC中的文件处理,2.6 MFC的消息映射,2.2 Windows对象句柄,2.1 传统的Windows 编程,Windows操作系统的特征: Windows操作系统是多任务、图形界面的操作系统。W

13、indows拥有一个图形用户界面(GUI)。用户可以用键盘和鼠标与显示器上的图形实现直接交互。 Windows支持多任务操作,可在同一时刻运行多个程序,并可在程序间进行信息交互。每个程序只能在称为“窗口”的屏幕矩形区中实现输出。 Windows的图形设备接口(GDI),实现了程序与设备的无关性,即为Windows编写的应用程序可以运行于任何具有Windows设备驱动程序的硬件环境中,方便了使用。,2.1 传统的Windows 编程,API函数: 为使程序员在编写应用程序时实现这些特征,Windows提供了一个应用程序编程接口,称Windows API(Application Programmi

14、ng Interface),这是Windows支持的函数定义、参数定义和消息格式的集合,可供应用程序调用。 这上千个API函数包含了各种窗口类和系统资源(内存管理、文件、线程等等)。利用这些函数就可以编出具有Windows风格的程序。Windows API也是Windows操作系统自带的在Windows环境下运行的软件开发包(SDK)。程序员总是直接或间接引用API进行应用程序的开发,所以Windows应用程序就有大致相同的用户界面。,2.1 传统的Windows 编程,C/C+调用API函数的优势: Windows环境下的最佳编程语言就是C/C+语言,因为Windows API函数本身就是用

15、C语言编写的,C和C+调用C语言的API函数是直接调用,而其他语言则多一道转换。C/C+编程可以很方便地利用计算机的底层资源,其程序运行速度远远高于其他语言。,2.1 传统的Windows 编程,1) 系统服务,2) 通用控件库,3) 图形设备接口,4) 网络服务,5) 用户接口,6) 系统Shell,7) Windows 系统信息,标准Win32 API 函数分类:,2.1 传统的Windows 编程,传统的Windows编程 :直接采用API进行的C/C+程序设计 【例2.1】一个对话框的简单Windows程序: #include int APIENTRY WinMain(HINSTANC

16、E hInstance, HINSTANCE hPreinstance, LPSTR lpCmdLine, int nCmdshow) MessageBox(NULL,This is a MessageBox windows example,Ex2_1,MB_OK); return 0; ,2.1 传统的Windows 编程,说明: (1) windows.h是windows程序最基本的头文件,它包含了其它几个windows头文件,它们定义了windows的所有数据类型、数据结构、符号常量和API函数原型声明。 (2) MessageBox 是一个API函数,显示一个消息框。其中:第一个参数指

17、明此消息框的父窗口句柄,为NULL则说明没有父窗口; 第二、三个参数类型均为字符型指针,分别指向消息框中要显示的字符串和消息框标题栏显示的字符串; 第四个参数是一个无符号整数,表明消息框中显示的按钮和风格。 #define MB_OK 0 x00000000L / OK按钮 #define MB_OKCANCEL 0 x00000001L / OK和CANCEL两个按钮 #define MB_ABORTRETYRIGNORE 0 x00000002L /ABORT,RETRY和IGNORE3个按钮 #define MB_YESNOCANCEL0 x00000003L / YES、NO和CANC

18、EL共3个按钮,2.1 传统的Windows 编程,(3) WinMain函数是windows程序的入口函数,包含4个参数: hInstance是唯一标识本程序的实例句柄,系统和其它应用程序通过该句柄与本程序通讯。 hPrevInstance是本程序的前一个实例句柄,由于32位windows采用进程线程模式,每一线程拥有自己的句柄,因此该参数始终为空。 lpCmdLine是一个字符串指针,指向命令行参数字符串,没有命令行参数时为空。 nCmdShow指明程序最初运行时窗口打开方式,如正常方式、最大化或最小化运行。 WinMain返回一个整数值,作为退出代码。 APIENTRY表示函数调用约定,

19、函数调用时参数按从左至右的顺序压入栈,由被调用者将参数弹出栈。,2.1 传统的Windows 编程,典型的Windows程序结构: Windows程序采用事件驱动、消息传递方式,由入口函数和窗口函数两部分组成。 入口函数中有一个由while语句组成的消息循环,其中调用了诸如获取消息、键盘消息转换、派送消息和窗口处理函数等API函数,循环直到取得退出消息(WIN-QUIT)结束。 在应用程序中还有由操作系统的API函数回调(callback)的窗口处理函数(简称窗口函数),根据消息值转向相应的消息处理,这是由switch语句组成的多向选择。如果不能处理则转缺省的窗口函数。参见图2.3。,2.1

20、传统的Windows 编程,图2.3 Windows消息流程,2.1 传统的Windows 编程,【例2.2】显示一个窗口的Windows应用程序。,#include /包含windows.h头文件 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM ); /窗口函数声明 /*入口函数 WinMain()*/ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow) WNDCLASS wndclass; /定

21、义窗口类结构变量 HWND hwnd; /定义窗口句柄 MSG msg; /定义消息结构变量,2.1 传统的Windows 编程,/*窗口类使用步骤*/ /*定义窗口类的各属性*/ wndclass.style = CS_HREDRAW|CS_VREDRAW; /改变窗口大小则重画 wndclass.lpfnWndProc = WndProc; /窗口函数为 WndProc wndclass.cbClsExtra = 0;/窗口类无扩展 wndclass.cbWndExtra = 0;/窗口实例无扩展 wndclass.hInstance = hInstance; /注册窗口类实例句柄 wnd

22、class.hIcon = LoadIcon(NULL,IDI_APPLICATION); /用默认光标 wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); /用箭头光标 wdclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); /背景为白色 wndclass.lpszMenuName = NULL;/窗口缺省无菜单 wndclass.lpszClassName = Ex2_2; /窗口类名为Ex2_2,2.1 传统的Windows 编程,/*设置后,必须注册窗口类设置才生效*/ if(!

23、 RegisterClass( /此窗口无创建参数,2.1 传统的Windows 编程,/*显示并更新窗口*/ ShowWindow(hwnd,nCmdShow); /显示窗口 UpdateWindow (hwnd); /更新窗口的客户区 /*消息循环*/ /获取消息,遇WM_QUIT退出循环 while(GetMessage ( /返回退出值 ,2.1 传统的Windows 编程,/*窗口函数*/ LRESULT CALLBACK WndProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam) /根据消息值转相应的消息处理 swit

24、ch (message) case WM_PAINT: /重画窗口客户区消息处理 HDC hdc; /定义设备描述表句柄 PAINTSTRUCT ps; /定义绘图信息结构变量 /获取要重画的窗口的设备描述表句柄 hdc = BeginPaint (hwnd,2.1 传统的Windows 编程,case WM_DESTROY:/撤消窗口消息处理 PostQuitMessage (0); /产生退出程序消息WM_QUIT return 0; return DefWindowProc (hwnd, message, wParam, lParam); /其它转缺省窗口函数 ,程序的运行结果:,事件驱

25、动、消息传递,事件与消息: 事件-在Windows环境下,应用程序启动后,系统等待用户在图形用户界面内的输入选择,如鼠标按键、键盘按键、窗口被创建、关闭、改变大小、移动等,对系统来说,这都是事件。 只要有事件发生,系统即产生特定的消息。消息描述了事件的类别,包含了相关信息,Windows应用程序利用消息与系统及其它应用程序进行信息交换。 由于windows事件的发生的是随机的,程序的执行先后顺序也无法预测,系统采用消息队列来存放事件发生的消息,然后从消息队列中依次取出消息进行相应的处理。,事件驱动、消息传递,消息结构的定义如下: typedef struct tagMSG HWND hWnd;

26、/指定消息发向的窗口句柄 UINTmessage;/标识消息的消息值 WPARAMwParam;/消息参数 LPARAMlParam;/消息参数 DWORDtime;/消息进入队列的时间 POINTpt;/消息进入队列时鼠标指针 的屏幕坐标 MSG,*PMSG,NEAR *NPMSG, FAR * LPMSG;,事件驱动、消息传递,消息结构中各个成员的意义: message是标识消息的消息值或消息名。每个消息都有唯一一个数值标识,常用不同前缀的符号常量以示区别。例如,WM_表示窗口消息 。,Windows常用的窗口消息和消息值定义于winuser.h中 #define WM_CREATE 0X

27、0001 /创建窗口产生的消息 #define WM_DESTROY 0X0002 /撤销窗口产生的消息 #define WM_PAINT 0X000F /重画窗口产生的消息 #define WM_CLOSE 0X0010 /关闭窗口产生的消息 #define WM_CHAR 0X0102 /按下非系统键产生的字符消息 #define WM_USER 0X0400 /用户自定义消息,事件驱动、消息传递,wParam,lParam消息参数,均为32位 其数据类型在windef.h中定义如下: typedef UINT WPARAM; typedef LONG LPARAM;,pt表示消息进入消息

28、队列时鼠标指针的屏幕坐标, 数据类型POINT是定义在windef.h中的结构体,表示屏 幕上一点,定义如下: typedef struct tagPOINT LONG x;/表示点的屏幕横坐标 LONGy;/表示点的屏幕纵坐标 POINT, *PPOINT,NEAR *NPPOINT,FAR *LPPOINT;,Windows数据类型,常用windows数据类型:,Windows数据类型,窗口类及其使用步骤,窗口结构类型: typedef struct tagWNDCLASS UINT style; /窗口风格 WNDPROC lpfnWndProc; /指向窗口处理函数的函数指针 int

29、cbClsExtra; /窗口结构中的预留字节数 int cbWndExtra; /为其它创建窗口预留字节数 HINSTANCE hInstance; /注册该窗口类的实例句柄 HICON hIcon; /代表该窗口类的图标句柄 HCURSOR hCursor; / 该窗口客户区鼠标光标句柄 HBRUSH hbrBackGround; /该窗口背景颜色句柄 LPCSTR lpszMenuName; /指向窗口菜单名的字符指针 LPCSTR lpszClassName; /指向窗口名的字符指针 WNDCLASS, *PWNDCLASS,NEAR *NPWNDCLASS, FAR *LPWNDCL

30、ASS;,窗口类及其使用步骤,WinMain()函数完成第一项工作建立一个窗口 (1) 定义一个窗口类,包括定义窗口对象并对它的相关成员赋值。 (2) 注册窗口类,调用RegisterClass()注册窗口类,并判断是否注册成功。其参数是WNDCLASS结构类型指针,用需要注册的窗口对象地址进行调用。 (3) 创建窗口,定义注册窗口后,可以创建一个或多个同类型的窗口;由API函数CreateWindow()创建窗口,并返回所创建窗口的句柄。 (4) 调用API函数ShowWindow()和UpdateWindow()显示并更新窗口,它们的参数相同,第一个参数是要显示的窗口句柄,第二个参数是窗口

31、显示的方式。,消息循环与消息传递,消息循环(while循环) GetMessage()函数从应用程序消息队列中读取消息, TranslateMessage()函数进行键盘消息转换,然后由DispatchMessag()将消息派送给相应的窗口函数进行处理;当消息队列为空时,应用程序进入等待状态,等待用户输入。 GetMessage()函数声明如下: BOOL WINAPI GetMessage (LPMSG, HWND, UINT, UINT ); 其中第1个参数为存放消息的MSG结构指针,第2个参数表示接收消息的窗口句柄,第3、4个参数分别表示要获取的最大和最小消息值。当后3个参数值设为NUL

32、L或0时,表示应用程序接收它所创建的所有窗口的所有消息。 当GetMessage()获取到WM_QUIT消息时,返回FALSE,结束消息循环。,消息循环与消息传递,TranslateMessage()函数负责键盘消息转换。 击键消息除字符键消息外,其它击键操作产生虚拟键消息,包括WM_KEYDOWN,WM_SYSKEYDOWN,WM_KEYUP,WM_SYSKEYUP,这些虚拟键消息必须通过转换成字符消息程序才能响应。,消息循环与消息传递,消息派送流程,DispatchMessage函数 根据消息所包含的信息,将消息派送到相应的窗口函数,过程如图:,hWnd Message wParaw Ip

33、aram Time Pt,MSG,Ex2_2 Ex2_2 ,HWND,Style Wndproc Ex2_2 Ex2_2,WNDCLASS,窗口处理函数 WndProc(),应用程序创建的每一个窗口或对话框都对应一个窗口处理函数,处理来自窗口的消息。对于应用程序,WinMain()函数都差不多,编程的主要任务就是编写窗口函数。WndProc()的原型如下: LRESULT CALLBACK WndProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam); 其中,第一个参数表示对应窗口的句柄,第二个参数是需要处理的消息的消息值,第三、四

34、个参数包含了相应消息的某些信息,如消息发生时鼠标位置等。 WndProc()函数的结构是一个switch语句,根据消息值不同,选择不同的case子句执行,如WM_PAINT消息表示窗口客户区需要重画,WM_DESTROY消息表示窗口要被撤销等。如果message参数的值与各个case子句的常量都不同,则调用DefWindowProc()函数处理。,进队和不进队消息,窗口函数一般由系统调用,应用程序不直接调用它,而是通过PostMessage()和SendMessage()函数传递消息来间接调用窗口函数。消息分为进队消息和不进队消息。 (1) 进队消息是由windows放入应用程序消息队列、由应

35、用程序消息循环从消息队列中取出并派送到窗口函数的消息。进队消息一般由用户操作产生,如鼠标移动、点击产生的消息,键盘按键消息,重画窗口消息等。调用API函数PostMessage()可以邮送(post)一条消息到指定窗口的消息队列,其原型如下: BOOL WINAPI PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) ; 其中Msg参数指定了要发送的消息值(名)。PostQuitMessage()调用本函数邮送消息。,进队和不进队消息,(2) 不进队消息,直接发送(send)给指定窗口的窗口函数进行处理。程序中调用某些特

36、定的API函数会产生不进队消息。如调用CreateWindow()创建窗口时发送的WM_CREATE消息,调用UpdateWindow()更新窗口时发送的WM_PAINT消息及调用DestroyWindow()时发送的WM_DESTROY消息都是不进队消息。 可以通过调用SendMessage()函数直接发送消息给窗口: LRESULT WINAPI SendMessage(HWND hWnd,UINT Msg, WPARAM wParam,LPARAM lParam); 有的不进队消息来自进队消息,如退出应用程序时会产生一条进队消息WM_CLOSE,消息循环将其派送到窗口函数,处理这一消息一

37、般是调用DestroyWindow()函数撤销并关闭窗口,并发送不进队消息WM_DESTROY到窗口函数。有的用户操作可能既产生进队消息,又产生不进队消息。消息是否进入队列由Windows自行操作,程序设计人员只要关心窗口函数的编写。,设备描述表,绘图信息数据结构定义: typedef struct tagPAINTSTRUCT HDC hdc;/ 设备描述表句柄 BOOL fErase; / 布尔值,若背景要重画,则为非0,否则为0 RECT rcPaint;/ 指定窗口客户区无效区域 BOOL fRestore;/ 保留 BOOL fIncUpdate;/ 保留 BYTE rgbReser

38、ved32;/ 保留 PAINTSTRUCT,* PPAINTSTRUCT,* NPPAINTSTRUCT, *lPPAINTSTRUCT;,设备描述表,WM_PAINT是重画窗口客户区消息,当窗口内容被改变、移动或窗口被覆盖后,需要对窗口进行重画,一般应用程序都需要处理这个消息,处理这一消息需要获取设备描述表句柄。 Windows的图形设备接口GDI是一组API函数,它提供与设备无关的图形功能,使应用程序在不同图形设备(如打印机,显示器、绘图仪等)上进行相同的操作(调用GDI函数),而无需考虑设备的硬件差异,设备无关性是通过设备描述表实现的。,设备描述表,设备描述表 (Device Cont

39、ext,DC)也称为设备上下文,是GDI内部定义的一个有图形对象、图形方式及其属性的一个数据结构,与特定设备相关,描述了硬件设备的具体特征信息。如需要执行显示任务,就构造一个显示设备的DC,获得其句柄;例如,需要执行打印任务,则构造一个打印设备的DC,获得其句柄,GDI函数以该句柄为参数完成相应任务。与具体设备相关的操作交给DC,将应用程序的设备无关图形功能调用转换为在设备驱动程序下执行的设备相关操作。 应用程序不能直接访问设备描述表,为了进行图形输出,必须先获取设备描述表句柄,然后以设备描述表句柄为参数调用GDI函数,实现图形功能。,2.2 Windows对象句柄,句柄的概念: 早期的句柄H

40、andle是一个16位的代号。在DOS操作系统中,必须用带路径的文件名,句柄是文件的代号,文件读/写时只用这个代号就行了,而不必用很长的路径名。 文件句柄只是一个代号,它不是文件的地址。地址信息放在文件句柄指向的内存中特定的文件管理区域的一个单元中,那里存放了入口地址和有关文件的其它信息。 句柄的数据类型在winnt.h中说明如下: typedef void * HANDLE; 所以从物理上看句柄是一个泛型(无类型)指针。但它不是指向一个Windows对象的存储首地址,而是指向包含了使用该对象有关信息的一块内存单元。所以从逻辑上说它是一个代号,一个对象的代号。,2.2 Windows对象句柄,

41、句柄的使用: 句柄所指向的内容是不能由句柄操作来改变的,只能由系统来改变。句柄允许做的唯一操作是检查它是否是一个有效句柄。不等于零是一个有效句柄,等于零是无效句柄。 Windows操作系统中所谓“句柄”(handle)是唯一标识某个Windows对象(如程序实例、窗口、图标、光标、画刷、菜单等)的一个32位无符号整数,句柄是Windows对象的代号。 Windows程序通常通过调用win32 API函数来获得某个Windows对象的句柄,只有有了句柄,程序才能使用与其对应的Windows对象。形象地讲,对象是学生,句柄是学号。 建立一个Windows对象,自然就建立起一个实例句柄。要使一个句柄

42、无效只须撤消对该对象的引用,不要销毁句柄。,2.2 Windows对象句柄,表2.1 常用Windows句柄类型,2.3 MFC基础类及其层次结构,AFX小组的MFC开发设计的原则:,1. 使用C+进行Windows应用程序设计的过程应简单和直观。 2. 用类封装Windows API和Windows对象,并按照API的方式进行工作。 3. 使用标准的Windows命令的约定和编码风格。 4. 类库应有足够的可扩展性,以便跟随Windows的更新发展。 5. 能更方便地使用API函数,采用Windows API的概念,函数和编程风格。 从这里可以看出MFC和Windows很好地连接起来,使Wi

43、ndows下的C语言程序设计,成为面向对象的MFC。这里没有追求纯粹,而是包容和实用!,MFC是采用单一继承,从根类Cobject层层派生出绝大多数MFC中的类,其层次结构是最典型。参见图2.8,图2.6 根类CObject分类派生图,2.3 MFC基础类及其层次结构,Cobject根类,CCmdTarget 命令相关类,CDC设备环境类,CClientDC、CWindowDC、CPaintDC、,CGdiObject 绘画工具类,CPen、CBrush、CFont、CBitmap、CPalette、,CMenu菜单,CArray、CList、CMap、 群(集合)类,CDatabase、CR

44、ecordset、 ODBC数据库支持,CDatabase、CDataRecordset、 DAO数据库支持,CFile 文件类,CMemFile、COleStreamFile、CSocketFile、,CException 异常类,CSyncObject 同步对象类,CInternetSession 因特网会话类,CInternetConnection 因特网连接类,CFtpConnection、CGopherConnection、CHelpConnection,图2.7 Cobject派生类层次示意图,CObject根类,CCmdTarget 命令处理类,CWinThread 线程类,CD

45、ocument 文档类,CDocTemplate 文档模板类,CWnd 窗口类,CWinApp Windows应用程序类,CSingleDocTemplate 单文档模板类,CMultiDocTemplate 多文档模板类,图2.8 应用程序结构,Cobject根类派生的最重要的类组成一个应用程序结构(Application Architecture)的集合,它是由CCmdTarget为基类派生出来的,其中主要部分参见图2.10。,CFrameWnd 框架窗口类,CControlBar 控制条类,CSplitterWnd 窗口分割类,CPropertSheet 属性表类,CMDIFrameWn

46、d、CMDIChildWnd、CMiniFrameWnd,CDialogBar、CToolBar、CStatusBar,CWnd 窗口类,CDialog 对话框类,CCommonDialog 公用对话框类,CProperty 属性页表,CFileDialog、CColorDialog、,图2.8 应用程序结构,CView 视图类,控制类 CButton、CEdit、CListBox、CScrollBar、CStatic、CComboBox,CCtrlView,CFormView,CEditView、CListView、CTreeView、CRichEditView,CRecordView,图2

47、.8 应用程序结构,基类Cobject的最基本功能: 1. 支持序列化(serialization)。序列化指如何让一个对象保持持久不变,即把对象成员数据内容存入一个文件或从一个文件中读取内容重构对象的过程。 2. 运行时(Run-time)类的信息获取。 3. 提供特定的new,delete和=操作符,完成对象的建立与删除。,2.4 MFC 编程,标准Windows程序设计: VC+的微软基础类库(Microsoft Foundation Class Library,MFC)封装了大部分API函数,并提供了一个应用程序框架,简化了和标准了Windows程序设计,所以用MFC编写Windows

48、应用程序也称为标准Windows程序设计。 标准Windows程序设计把传统的Windows程序设计转向C+面向对象的Windows程序设计,2.4 MFC 编程,MFC简介: MFC约有200个类,提供了Windows应用程序框架和创建应用程序的组件。其中只有5个核心类对应用程序框架有影响: Cwinapp,Cdocument,Cview,CFrameWnd和CDocTemplate。 五个之中只有Cwinapp是必不可少的类,Cwinapp的对象在应用程序中必须有一个,也只有一个,并是一个全局对象,它建立了应用程序执行的主线程(线程的概念参见本节后的附录)。全局对象是在MFC初始化之前,也

49、即当Windows操作系统调用WinMain( )时,这个对象就先已建立,即主线程已建立。形象地说,执行程序的通路已经开通。,2.4 MFC 编程,入口函数: 在MFC编程中,入口函数WinMain( )被封装在MFC的应用程序框架内,已经不用也不可以再定义另一个WinMain()函数。 应用程序向导: MFC编程使用MFC的应用程序向导工具: AppWizard AppWizard为程序员提供了一种快捷方便的工具来定制基于MFC的应用程序框架,程序员只需以此为基础,添加与修改程序代码来实现所需功能。MFC编程包含三种类型的应用程序:单文档界面(SDI)应用程序、多文档界面(MDI)应用程序和

50、基于对话框(Dialog Based)的应用程序,它们都可以由AppWizard引导建立起来。,2.4 MFC 编程,接口与封装: 在类中必须有一部分成员函数置为公有,专供类外程序语句访问,这些函数亦称接口函数。 其余成员函数是故意对外隐蔽起来的操作,它们是最复杂最关键的部分,越是复杂越是关键就越能体现出使用类封装的必要和优越。 类中故意的隐藏也为以后的升级扩展留下了余地,只要接口不变,内部再变,也不必修改原来的程序,就象MFC(微软基础类)升级后,由MFC底层类所编的程序完全不必修改,自动升级。,2.4 MFC 编程,封装有助于编程人员在处理好简单接口后,集中精力处理高层次开发的工作,MFC

51、能被广泛使用也正是有此优点。用户界面等的编程是底层的十分复杂和困难的事,MFC给解决了。程序员只管自己特定的任务,编程的效率和可靠性大大提高。,使用接口的优点:,2.4 MFC 编程进程和线程,进程(process) : 运行中的程序称为进程,程序是一个静态的概念,进程是一个动态的概念。 进程的组成: (1)一段可执行程序(代码) (2)程序所需的相关数据(变量、工作空间、缓冲区等) (3)程序执行的上下文环境 其中执行上下文环境(Execution Context)亦称进程状态(Process State),是最为重要的。它包括操作系统管理进程以及处理器执行进程所需要的所有信息,包括处理器的

52、各寄存器的内容,还包括操作系统使用的信息,如进程优先级以及进程是否在等待特定的输入输出事件完成。,2.4 MFC 编程进程和线程,进程的属性与线程(thread) : (1)资源所有权:一个进程包括一个保存进程映像的虚拟地址空间,并随时分配对资源的控制或所有权,包括内存、I/O通道、I/O设备和文件。 (2)调度/执行:进程沿着通过一个或多个程序间的执行路径运行,它与其他进程的执行路径相互交错。 把两者分开,执行部分(它实际是被操作系统调度并分配的实体)称为线程(thread)。而资源所有权的部分仍称作进程。一个进程可以拥有多个线程。,2.4 MFC 编程进程和线程,线程的优点: 与无线程的进

53、程相比速度大为提高,原因是: (1)在已有进程中创建一个新线程速度比创建一个全新的进程快得多(可达10倍)。 (2)终止一个线程比终止一个进程花费时间少。 (3)线程间切换比进程间切换花费时间少。 (4)同一进程的线程共享存储空间和文件,无需调用操作系统内核就可进行通信,效率大大提高。 所以现代的操作系统多为多进程多线程的操作系统。,2.4 MFC 编程进程和线程,进程-线程-窗口: 32位Windows管理运行的程序的模式。当创建一个进程的同时也创建了第一个线程,称为“主线程”。主线程的入口函数是WinMain (相当于控制台应用程序的main函数)。之后,主线程可以在进程中再创建一个或多个

54、线程,即“多线程”,多个线程共享进程的静态部分(资源,地址等)。,图2.9 进程、线程与窗口,2.5 MFC对象和Windows对象,MFC对象:特指封装了Window对象的C+对象。 本节讨论MFC对象与Window对象的联系,以最典型的的窗口类(CWnd)为例,讨论CWnd类对象与Windows窗口对象的关系。,图2.10 MFC窗口对象与Windows窗口对象的关系,MFC的窗口对象wnd是C+类的实例,即CWnd类或其派生类的实例。 hwnd是HWND句柄类型的实例,为它建立了一个Windows操作系统的对象。然后把这个句柄放入CWnd类对象wnd的成员数据m_hwnd中。这样wnd就

55、包含了一个Windows操作系统的窗口对象。,参考程序段如下: CWnd wnd; /定义窗口类(CWnd)的对象wnd HWND hwnd; /定义窗口句柄hwnd hwnd=CreateWindows(.); /调用API函数CreateWindows(.)建立一个Windows窗口类实例 wnd.Attach(hwd); /把Windows窗口实例的句柄链到CWnd对象hwnd上 . Destrory Window(hwnd); /调用API函数撤消Windows窗口,2.5 MFC对象和Windows对象,MFC对象和对应Windows对象: MFC封装了几乎所有Windows的API

56、函数,所以上面的API函数,可以用CWnd的成员函数代替。成员函数Create()可以代替API函数CreateWindows()并加上另一个成员函数Attach()的全部功能,建立一个Windows操作系统的窗口对象,并把句柄自动保存在MFC窗口对象wnd的m_hwnd成员数据中。通常MFC程序员直接使用CWnd的成员函数就可以了。 其它的MFC对象和对应Windows对象也有类似的关系。见表2.1,2.5 MFC对象和Windows对象,表2.2 常用MFC类与Windows对象句柄对应关系,2.5 MFC对象和Windows对象,Windows窗口句柄通常是全局量,动态建立的Window

57、s窗口对象也是全局性的。所以一个进程或线程可以取得另一个进程或线程的窗口句柄,并给它发送消息。 注意: 一个线程只能使用本线程创建的MFC窗口对象,不能使用其它线程创建的MFC窗口对象。,2.5 MFC对象和Windows对象,小结: Windows对象是Windows操作系统的一个内部数据结构的实例,由一个Windows系统全局的窗口句柄来唯一标志,由API函数CreatWindow()创建,而由DestroyWindow()撤消。 在MFC编程中,Windows对象通常在MFC对象建立以后,调用Create() 建立Windows对象,并链接在MFC对象上。,建立应用程序的主框架窗口的程序

58、段: CFrameWnd *pFrame=new CFrameWnd; /动态建立框架窗口对象 pFrame-Create(NULL,”Ex2_xx”, ws_OVERLAPPENDWINDOW,rect,NULL, MAKEINTRESOURCE(IDR_MENUI),0,NULL); /建立与动态框架窗口对象相连的Windows框架窗口,2.6 MFC的消息映射,消息映射的概念: MFC由CWinApp类检索和派送消息给相应的窗口函数,但是所有的MFC窗口函数都使用同一个窗口函数。 MFC把设计窗口的任务细化为设计若干消息处理函数,程序员要做的是为每一个要处理的消息提供一个消息处理(Handling Messages)函数,然后系统通过MFC提供的一套消息映射系统(messages mapping system)来调用相应的消

温馨提示

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

评论

0/150

提交评论