资源预览内容
第1页 / 共48页
第2页 / 共48页
第3页 / 共48页
第4页 / 共48页
第5页 / 共48页
第6页 / 共48页
第7页 / 共48页
第8页 / 共48页
第9页 / 共48页
第10页 / 共48页
亲,该文档总共48页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/151前言前言 什么是什么是 Windows API? 有过编程经验的读者都应该知道,在传统应用程序中要完成某个有过编程经验的读者都应该知道,在传统应用程序中要完成某个功能,都是以功能,都是以函数调用函数调用的形式实现的,同样,的形式实现的,同样,Windows应用程序也是应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。以函数调用的方式来通知操作系统执行相应的功能的。 操作系统所能够完成的每一个特殊功能通常都有一个函数与其对操作系统所能够完成的每一个特殊功能通常都有一个函数与其对应,也就是说,操作系统把它所能够完成的功能以函数的形式提供应,也就是说,操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是些函数的集合就是Windows操作系统提供给应用程序编程的接口操作系统提供给应用程序编程的接口(Application Programming Interface),简称,简称Windows API。 如如CreateWindow就是一个就是一个API函数,应用程序中调用这个函数,操函数,应用程序中调用这个函数,操作系统就会按照该函数提供的参数信息产生一个相应的窗口。这些作系统就会按照该函数提供的参数信息产生一个相应的窗口。这些API函数都在函数都在windows.h中声明。中声明。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/152什么是什么是 MFC? MFC英文全称为英文全称为Microsoft Foundation Classes (微(微软基础类库),是把软基础类库),是把Windows API进行封装的类库,它是进行封装的类库,它是一个类的集合,通过覆盖一个类的集合,通过覆盖Windows API,为编程提供了一,为编程提供了一个个面向对象面向对象的界面。的界面。 MFC使使Windows程序员能够利用程序员能够利用C+面象对象的特面象对象的特性进行编程。性进行编程。前言前言Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/153为什么要使用为什么要使用MFC?n可重用性可重用性n封装后使方法和属性更紧密的捆绑封装后使方法和属性更紧密的捆绑n常用的功能自动化,减少编写代码的数量常用的功能自动化,减少编写代码的数量n提供应用程序的框架结构提供应用程序的框架结构 框架结构提供了抽象功能,它远远超出了框架结构提供了抽象功能,它远远超出了Windows API的的功能。例如:功能。例如:MFC的文档的文档/视图体系结构在视图体系结构在API上建造了一个上建造了一个功能强大的基础结构,它把程序中数据的图形表示(或成为功能强大的基础结构,它把程序中数据的图形表示(或成为视图)与数据本身分开。这种抽象对视图)与数据本身分开。这种抽象对API而言完全是陌生的,而言完全是陌生的,而且在而且在MFC框架结构之外或类似的类库中也不存在。框架结构之外或类似的类库中也不存在。前言前言Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/154Windows 程序内部运行机制程序内部运行机制Windows编程模型编程模型事件驱动编程模型事件驱动编程模型以消息为基础,事件驱动之以消息为基础,事件驱动之WM_PAINTWM_KEYDOWNWM_LBUTTONDOWN消息响应消息响应消息响应消息响应消息响应消息响应DefWindowProc来源于操作系统的消来源于操作系统的消息息消消息队列息队列WinMain消息循环消息循环发送消息发送消息窗口过程窗口过程未处理的消息未处理的消息应用程序应用程序窗口窗口Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/155Windows 程序内部运行机制程序内部运行机制小小知识点小小知识点“句柄句柄” 句柄(句柄(HANDLE),资源的标识。),资源的标识。 操作系统要管理和操作这些资源,都是通过句柄来操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。按资源的类型,又可将句柄细分成图找到对应的资源。按资源的类型,又可将句柄细分成图标句柄(标句柄(HICON),光标句柄(),光标句柄(HCURSOR),窗口),窗口句柄(句柄(HWND),应用程序实例句柄(),应用程序实例句柄(HINSTANCE)等等各种类型的句柄。操作系统给每一个窗口指定的一等等各种类型的句柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句柄。个唯一的标识号即窗口句柄。 Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/156Windows 程序内部运行机制程序内部运行机制编写编写Windows应用程序的要素应用程序的要素消息响应消息响应消息响应消息响应消息响应消息响应DefWindowProcWinMain消息循环消息循环发送消息发送消息窗口过程窗口过程未处理的消息未处理的消息应用程序应用程序1 1 入口函数入口函数WinMain2 2 创建窗口创建窗口3 3发送消息与消息循环发送消息与消息循环4 4 窗口过程与消息响应窗口过程与消息响应消息消息窗口窗口Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/157 窗口类第二个成员变量窗口类第二个成员变量lpfnWndProclpfnWndProc指定了这一类型窗口的过指定了这一类型窗口的过程函数,也称程函数,也称回调函数回调函数。 回调函数的原理是这样的,当应用程序收到给某一窗口的消息回调函数的原理是这样的,当应用程序收到给某一窗口的消息时(还记得前面讲过的消息通常与窗口相关的吗?),就应该调用时(还记得前面讲过的消息通常与窗口相关的吗?),就应该调用某一函数来处理这条消息。这一某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,调用过程不用应用程序自己来实施,而由操作系统来完成而由操作系统来完成,但是,回调函数本身的代码必须由应用程序,但是,回调函数本身的代码必须由应用程序自己完成。自己完成。 对于一条消息,操作系统到底调用应用程序中的哪个函数(回对于一条消息,操作系统到底调用应用程序中的哪个函数(回调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类型中的型中的lpfnWndProclpfnWndProc成员指定的函数。每一种不同类型的窗口都有成员指定的函数。每一种不同类型的窗口都有自己专用的回调函数,该函数就是通过自己专用的回调函数,该函数就是通过lpfnWndProclpfnWndProc成员指定的。成员指定的。 Windows 程序内部运行机制程序内部运行机制窗口过程函数窗口过程函数Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/158Windows 程序内部运行机制程序内部运行机制创建窗口创建窗口 创建一个完整的窗口需要经过下面四个操作步骤:创建一个完整的窗口需要经过下面四个操作步骤: Step1: 设计一个窗口类;设计一个窗口类; Step2: 注册窗口类;注册窗口类; Step3: 创建窗口;创建窗口; Step4: 显示及更新窗口。显示及更新窗口。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/159Windows 程序内部运行机制程序内部运行机制WM_PAINT Windows 把一个最小的需要重绘的正方形区域叫做把一个最小的需要重绘的正方形区域叫做“无效区域无效区域”。当。当 Windows 发现了一个发现了一个“无效区域无效区域“后,它就会向该应用程后,它就会向该应用程序发送一个序发送一个 WM_PAINT 消息,通知应用程序重新绘制窗口。消息,通知应用程序重新绘制窗口。 当窗口从无到有、改变尺寸、最小化后再恢复、被其他窗口遮当窗口从无到有、改变尺寸、最小化后再恢复、被其他窗口遮盖后再显示时,窗口的客户区都将变为无效。盖后再显示时,窗口的客户区都将变为无效。那么,应用程序是如何通知操作系统执行某个功能的呢?那么,应用程序是如何通知操作系统执行某个功能的呢?Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1510Windows 程序内部运行机制程序内部运行机制自行发送消息的两种方式自行发送消息的两种方式发送消息可以使用发送消息可以使用SendMessage和和PostMessage函数。函数。SendMessage将消息将消息直接发送给窗口直接发送给窗口,并,并调用该窗口过程调用该窗口过程进行处理。在进行处理。在窗口过程对消息处理完毕后,该函数才返回。窗口过程对消息处理完毕后,该函数才返回。PostMessage函数函数将消息放入将消息放入与创建窗口的线程相关联的与创建窗口的线程相关联的消息队列消息队列后立后立即返回。即返回。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1511虚函数与多态性虚函数与多态性 当当C+编译器在编译的时候,发现基类的函数是虚函数,这编译器在编译的时候,发现基类的函数是虚函数,这个时候个时候C+就会采用迟绑定(就会采用迟绑定(late binding)的技术,在运行时,)的技术,在运行时,依据对象的类型(在示例程序中,我们传递的派生类对象的地址)依据对象的类型(在示例程序中,我们传递的派生类对象的地址)来确认调用的哪一个函数,这种能力就做来确认调用的哪一个函数,这种能力就做C+的的多态性多态性。 在基类的函数前加上在基类的函数前加上virtual关键字,该函数则为关键字,该函数则为虚函数虚函数。虚。虚函数派生下去仍为虚函数,而且可以省略函数派生下去仍为虚函数,而且可以省略virtual关键字。关键字。 在派生类中重写该函数,在派生类中重写该函数,运行时将会根据指针实际所指的对运行时将会根据指针实际所指的对象的类型来调用相应的函数象的类型来调用相应的函数。如果对象类型是派生类,就调用派。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。生类的函数;如果对象类型是基类,就调用基类的函数。掌握掌握C+Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1512纯虚函数与抽象类纯虚函数与抽象类 纯虚函数纯虚函数是指被标明为不具体实现的虚函数。纯虚函数可以是指被标明为不具体实现的虚函数。纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类抽象类。这种。这种可不能实例化对象,只能作为基类为派生类服务。可不能实例化对象,只能作为基类为派生类服务。 注意:注意:派生类中必须实现基类的纯虚函数,否则,派生类也派生类中必须实现基类的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。变成了抽象类,不能实例化对象。 纯虚函数多用在一些方法行为的实际上。在设计基类时,不纯虚函数多用在一些方法行为的实际上。在设计基类时,不太好确定或将来的行为多种多样,而此行为又是必需的,我们就太好确定或将来的行为多种多样,而此行为又是必需的,我们就可以在基类的设计中,以纯虚函数来声明次中行为,而不具体实可以在基类的设计中,以纯虚函数来声明次中行为,而不具体实现它。现它。掌握掌握C+Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1513const的使用方法的使用方法const成员函数成员函数 任何不会修改数据成员的函数都应该声明为任何不会修改数据成员的函数都应该声明为const类型类型。如。如果在编写果在编写const成员函数时,不慎修改了数据成员,或者调用了成员函数时,不慎修改了数据成员,或者调用了其它非其它非const成员函数,编译器将指出错误,这无疑会提高程序成员函数,编译器将指出错误,这无疑会提高程序的健壮性。的健壮性。 Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1514类中的类中的Static成员变量与函数成员变量与函数静态成员函数与变量的特性静态成员函数与变量的特性n 静态成员函数和静态成员变量属于类本身,在类加载的时候静态成员函数和静态成员变量属于类本身,在类加载的时候(编译阶段),即为它们分配了空间,因此可以通过(编译阶段),即为它们分配了空间,因此可以通过类名类名:函数名函数名或或类名类名:变量名变量名来访问。来访问。n 而非静态函数和非静态成员属于对象的方法和数据,也就是应而非静态函数和非静态成员属于对象的方法和数据,也就是应该首先产生类的对象,然后通过类的对象去引用。该首先产生类的对象,然后通过类的对象去引用。n 静态函数不属于某个具体的对象,也就是说,在还没有产生类静态函数不属于某个具体的对象,也就是说,在还没有产生类的任何一个具体对象时,静态函数就已经存在于程序的代码区了。的任何一个具体对象时,静态函数就已经存在于程序的代码区了。但这是类的非静态成员还没有分配内存空间,这样,在静态成员但这是类的非静态成员还没有分配内存空间,这样,在静态成员函数中是没有办法对类非静态成员进行操作的。因此,函数中是没有办法对类非静态成员进行操作的。因此,在静态成在静态成员函数中只能访问静态成员变量,不能访问非静态成员函数和非员函数中只能访问静态成员变量,不能访问非静态成员函数和非静态成员变量静态成员变量。非静态成员函数中可以调用静态成员函数。非静态成员函数中可以调用静态成员函数。 Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1515MFC框架程序剖析框架程序剖析MFC单文档界面程序初探(简答题)单文档界面程序初探(简答题)n test.h、test.cpp应用程序类:应用程序类:CTestApp(由(由CWinApp继承而来),每一个继承而来),每一个MFC程程序有且仅有一个主应用程序类对象序有且仅有一个主应用程序类对象 theApp,它代表一个程序本体,它代表一个程序本体,用于管理和维护主应用程序用于管理和维护主应用程序n MainFrm.h、MainFrm.cpp主框架类主框架类CMainFrame(由(由CWnd继承而来),主框架是应用程序继承而来),主框架是应用程序的主体窗口,其他的窗口(如视类窗口、工具条、状态条)都依附的主体窗口,其他的窗口(如视类窗口、工具条、状态条)都依附于主框架窗口(覆盖在它上面)。于主框架窗口(覆盖在它上面)。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1516MFC框架程序剖析框架程序剖析MFC单文档界面程序初探(续)单文档界面程序初探(续)n testView.h、testView.cpp视图类:视图类:CTestView(由(由CWnd继承而来),负责管理和维护图形继承而来),负责管理和维护图形显示操作。显示操作。n testDoc.h、testDoc.cpp文档类:文档类:CTestDoc(由(由CDocumet继承而来),负责显示数据的后继承而来),负责显示数据的后台管理和维护。台管理和维护。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1517MFC框架程序剖析框架程序剖析MFC中的全局对象中的全局对象theApp初始化初始化CTestAPP对象,应用程序内存获得配置对象,应用程序内存获得配置调用基类调用基类CWinApp构造函数(在构造函数(在MFC源码目录的文件中源码目录的文件中AppCore.cpp),初始化完成程序运行时的一些初始化工作。),初始化完成程序运行时的一些初始化工作。注意:注意:由于由于theApp是个全局对象,是个全局对象,所以所以CWinApp构造函数会在入构造函数会在入口函数口函数WinMain之前运行之前运行。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1518图形操作图形操作设备描述表设备描述表DCn在在Windows平台下,窗口的所有图形操作都是利用平台下,窗口的所有图形操作都是利用DC来完来完成的。成的。n如果使用如果使用GetDC来得到来得到DC的句柄,在完成图形操作后,必的句柄,在完成图形操作后,必须调用须调用ReleaseDC来释放来释放DC所占用的资源,以避免内存泄漏。所占用的资源,以避免内存泄漏。n利用计算机作图,窗口相当于画布,因此,在获取利用计算机作图,窗口相当于画布,因此,在获取DC的句的句柄时,总是和一个指定的窗口相关联。柄时,总是和一个指定的窗口相关联。 Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1519简单绘图简单绘图利用利用CClientDC、CWindowDC类绘图(简答题)类绘图(简答题)CClientDC派生于派生于CDC类,并且在构造时调用类,并且在构造时调用GetDC函数,在析函数,在析构时调用构时调用ReleaseDC函数。它与函数。它与CDC一样,都是实现在窗口的一样,都是实现在窗口的客客户区户区绘图。绘图。CWindowDC派生于派生于CDC类,并且在构造时调用类,并且在构造时调用GetWindowDC函数,在析构时调用函数,在析构时调用ReleaseDC函数。该对象可以访问整个窗口函数。该对象可以访问整个窗口区域,包括区域,包括客户区与非客户区客户区与非客户区。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1520简单绘图简单绘图绘制彩色线条绘制彩色线条使用使用CPen类类CPen pen(PS_SOLID,5,RGB(255,0,0);CClientDC dc(this);CPen* pOldPen = dc.SelectObject(&pen);dc.MoveTo(m_ptOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);注意:注意:当构造一个当构造一个GDI对象后,该对象并不会立即生效,必须通对象后,该对象并不会立即生效,必须通过过SelectObject函数选入设备描述表,它才会在以后的绘制操作中函数选入设备描述表,它才会在以后的绘制操作中生效。在完成绘图操作之后,都要利用生效。在完成绘图操作之后,都要利用SelectObject把先前的把先前的GDI对象选入设备描述表,以便使其恢复到先前的状态。对象选入设备描述表,以便使其恢复到先前的状态。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1521Windows消息的分类消息的分类n标准消息标准消息 除除WM_COMMAND之外之外,所有以所有以WM_开头的消息开头的消息。 从从CWnd派生的类,都可以接收到这类消息。派生的类,都可以接收到这类消息。n命令消息命令消息 来自来自菜单、加速键或工具栏菜单、加速键或工具栏按钮的消息。这类消息都以按钮的消息。这类消息都以WM_COMMAND呈现。在呈现。在MFC中,通过菜单项的标识(中,通过菜单项的标识(ID)来区分不同的命令消息;在)来区分不同的命令消息;在SDK中,通过消息的中,通过消息的wParam参数识别。参数识别。从从CCmdTarget派生的类,都可以接收到这类消息。派生的类,都可以接收到这类消息。n通告消息通告消息 由由控件控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。形式呈现。从从CCmdTarget派生的类,都可以接收到这类消息。派生的类,都可以接收到这类消息。菜单响应函数菜单响应函数Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1522菜单命令消息路由的过程(简答题)菜单命令消息路由的过程(简答题)当点击某菜单项时,最先接收到这个菜单命令消息的是当点击某菜单项时,最先接收到这个菜单命令消息的是框架类框架类。框架类把接收到的这个消息传给它的子窗口,即框架类把接收到的这个消息传给它的子窗口,即视类视类。视类根据。视类根据命令消息映射机制查找自身是否对这个消息进行了响应,如果响命令消息映射机制查找自身是否对这个消息进行了响应,如果响应了,则调用自身相应响应函数。应了,则调用自身相应响应函数。如果视类没有对此命令消息作出响应,就交由如果视类没有对此命令消息作出响应,就交由文档类文档类,文档类同,文档类同样查找自身是否这个消息进行了响应,如果响应了,则调用自身样查找自身是否这个消息进行了响应,如果响应了,则调用自身相应响应函数。相应响应函数。如果文档类也未做出响应,就把这个命令消息交还给视类,后者如果文档类也未做出响应,就把这个命令消息交还给视类,后者再交还给再交还给框架类框架类。框架类查看自己是否对这个命令消息进行了响应,如果它也没有框架类查看自己是否对这个命令消息进行了响应,如果它也没有相应,就把这个菜单命令消息交给相应,就把这个菜单命令消息交给应用程序类应用程序类,由后者来处理。,由后者来处理。菜单响应函数菜单响应函数Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1523对话框对话框 对话框是一个窗口,与对话框资源相关的类为对话框是一个窗口,与对话框资源相关的类为CDialog,由,由CWnd类派生而来。类派生而来。 可以将对话框看成是一个大容器,在它上面能够可以将对话框看成是一个大容器,在它上面能够放置各种标准和扩展放置各种标准和扩展控件控件,是用户与程序进行交互的,是用户与程序进行交互的重要手段。重要手段。 在在MFC中,所有的控件都是由中,所有的控件都是由CWnd派生而来,派生而来,因此,控件实际上也是窗口。因此,控件实际上也是窗口。对话框基本知识对话框基本知识Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1524对话框的种类对话框的种类n 模式对话框:模式对话框: 当其显示时,程序会当其显示时,程序会暂停执行暂停执行,直到关闭这个对话框后,直到关闭这个对话框后,才能继续执行程序中其他任务。例如才能继续执行程序中其他任务。例如“文件文件/打开打开” 对话框。对话框。n 无模式对话框:无模式对话框: 当其显示时,当其显示时,允许转而执行程序中其他任务允许转而执行程序中其他任务,而不用关闭,而不用关闭这个对话框。该类型对话框不会垄断用户的操作,用户仍可以这个对话框。该类型对话框不会垄断用户的操作,用户仍可以与其他界面对象进行交互。例如与其他界面对象进行交互。例如“查找查找”对话框。对话框。对话框基本知识对话框基本知识Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1525DoModal()函数函数 创建模式对话框需要调用创建模式对话框需要调用CDialog类的成员函数:类的成员函数:DoModal,该函数的功能就是创建并显示一个模式对,该函数的功能就是创建并显示一个模式对话框。话框。创建模式对话框创建模式对话框void CMainFrame:OnTest() / TODO: Add your command handler code hereCMyDialog dlg;dlg.DoModal();Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1526Create()函数函数 创建非模式对话框需要调用创建非模式对话框需要调用CDialog类的成员函数:类的成员函数:BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);创建非模式对话框创建非模式对话框void CMainFrame:OnTest() / TODO: Add your command handler code hereCMyDialog dlg;dlg.Create(IDD_DIALOG1, this);注意:注意:运行程序,对话框并未显示运行程序,对话框并未显示!Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1527ShowWindow()函数函数 当利用当利用Create函数创建非模式对话框时,还需要调用函数创建非模式对话框时,还需要调用ShowWindow函数将这个对话框显示出来。函数将这个对话框显示出来。创建非模式对话框创建非模式对话框void CMainFrame:OnTest() CMyDialog dlg;dlg.Create(IDD_DIALOG1, this);dlg.ShowWindow(SW_SHOW);注意:注意:运行程序,对话框仍未显示运行程序,对话框仍未显示!Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1528对话框未显示之原因分析对话框未显示之原因分析 这里创建的非模式对话框对象(这里创建的非模式对话框对象(dlg)是一个局部对象,当)是一个局部对象,当OnTest函数结束时,函数结束时,dlg这个对象的生命周期也就结束了,它会这个对象的生命周期也就结束了,它会销毁与之相关联的对话框资源,因此对话框不会显示。销毁与之相关联的对话框资源,因此对话框不会显示。 在创建模式对话框时,当执行到在创建模式对话框时,当执行到DoModal函数显示这个对话函数显示这个对话框时,程序会暂停执行,直到关闭模式对话框之后,程序才继续框时,程序会暂停执行,直到关闭模式对话框之后,程序才继续执行。也就是说,当模态对话框显示时,执行。也就是说,当模态对话框显示时,dlg这个对象的生命周这个对象的生命周期并未结束。期并未结束。 为什么模式对话框不会出现这样的问题?为什么模式对话框不会出现这样的问题? 结论:结论:在创建在创建非模式对话框非模式对话框时,时,不能不能把对话框对象定义为把对话框对象定义为局部对象局部对象。创建非模式对话框创建非模式对话框Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1529解决方法解决方法1使用成员变量使用成员变量把对话框对象定义为视类的把对话框对象定义为视类的成员变量成员变量。注意:在销毁对话框之前,注意:在销毁对话框之前,Create函数只能调用一次,否则会出错。函数只能调用一次,否则会出错。void CMainFrame:OnTest() static BOOL bFlag = TRUE;if (TRUE = bFlag)dlg.Create(IDD_DIALOG1, this);bFlag = FALSE;dlg.ShowWindow(SW_SHOW);创建非模式对话框创建非模式对话框Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1530解决方法解决方法2使用推内存使用推内存把对话框对象定义为把对话框对象定义为指针指针,在,在堆堆上分配内存。上分配内存。void CMainFrame :OnTest() CMyDialog* pDlg = new CMyDialog;pDlg-Create(IDD_DIALOG1, this);pDlg-ShowWindow(SW_SHOW);注意:注意:该程序存在问题。由于没有办法释放这个指针变量所指向该程序存在问题。由于没有办法释放这个指针变量所指向的那块内存,会出现内存泄漏的那块内存,会出现内存泄漏!消除内存泄漏的办法:消除内存泄漏的办法:1.指针变量定义成全局变量;或者指针变量定义成全局变量;或者 2.重载重载对话框的对话框的PostNcDestroy函数,添加代码函数,添加代码 delete this.创建非模式对话框创建非模式对话框Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1531利用利用GetDlgItemGetDlgItem改变控件文本内容改变控件文本内容void CMyDialog:OnNumber1() CString str;GetDlgItem(IDC_NUMBER1)-GetWindowText(str);if (str = Number1:)GetDlgItem(IDC_NUMBER1)-SetWindowText(数值数值1:);elseGetDlgItem(IDC_NUMBER1)-SetWindowText(Number1:);注意:注意:静态文本框在默认状态下是不发送通告消息的。静态文本框在默认状态下是不发送通告消息的。改变这一默认状态,必须在属性窗口选中改变这一默认状态,必须在属性窗口选中Notify这个这个选项。选项。访问控件的七种方法访问控件的七种方法Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1532在窗口创建之前更改在窗口创建之前更改更改窗口大小、标题、风格更改窗口大小、标题、风格 如果希望在应用程序窗口创建之前修改它的大小、标题和风格,如果希望在应用程序窗口创建之前修改它的大小、标题和风格,应该在应该在CMainFrame类的类的PreCreateWindow成员函数进行。成员函数进行。 该函数有个类型是该函数有个类型是CREATESTRUCT结构的参数,如果在修改结构的参数,如果在修改了这个参数中的成员变量的值,那么这种改变会反映到了这个参数中的成员变量的值,那么这种改变会反映到MFC底层代底层代码中,当码中,当MFC底层代码调用底层代码调用CreateWindowEx函数去创建窗口时,函数去创建窗口时,它就会使用改变后的参数值去创建这个窗口。它就会使用改变后的参数值去创建这个窗口。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1533在窗口创建之后更改其风格在窗口创建之后更改其风格 在应用程序窗口创建之后修改它的风格属性,可在在应用程序窗口创建之后修改它的风格属性,可在CMainFrame类的类的ONCreate函数中调用函数中调用SetWindowLong函数实现。函数实现。SetWindowLong(HWND hWnd, int nIndex, LONG dwNewLong) 该函数的作用是改变制定窗口的属性(包括设置新的该函数的作用是改变制定窗口的属性(包括设置新的窗口风格窗口风格、设置新的设置新的窗口过程窗口过程、设置新的应用程序、设置新的应用程序实例局柄实例局柄等)。要改变窗口等)。要改变窗口的风格,则将该函数的第二个参数指定为的风格,则将该函数的第二个参数指定为GWL_STYLE,然后由第,然后由第三个参数指定新的窗口风格。三个参数指定新的窗口风格。更改窗口大小、标题、风格更改窗口大小、标题、风格Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1534在窗口创建之后更改在窗口创建之后更改更改光标、标题栏图标、窗口背景更改光标、标题栏图标、窗口背景 要在应用程序窗口创建之后修改它的光标、图标和背景,可在要在应用程序窗口创建之后修改它的光标、图标和背景,可在OnCreate函数中调用函数中调用SetClassLong函数实现。函数实现。SetClassLong(HWND hWnd, int nIndex, LONG dwNewLong) 该函数的作用是:重新设置指定窗口所属窗口类的该函数的作用是:重新设置指定窗口所属窗口类的WNDCLASS结构体中指定数据成员的属性(包括设置新的结构体中指定数据成员的属性(包括设置新的窗口背窗口背景画刷、光标景画刷、光标、图标和窗口类样式图标和窗口类样式)。)。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1535注意事项注意事项更改光标、标题栏图标、窗口背景更改光标、标题栏图标、窗口背景在在MFC中,如果要修改应用程序窗口的中,如果要修改应用程序窗口的图标图标,则应该,则应该框架类框架类中进行,中进行,因为框架窗口才有标题栏;如果要修改程序窗口的因为框架窗口才有标题栏;如果要修改程序窗口的背景和光标背景和光标,则,则应该在应该在视类视类中进行。中进行。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1536程序与进程(简答)程序与进程(简答)进程与线程进程与线程程序程序:计算机指令的集合,它以:计算机指令的集合,它以文件的形式文件的形式存储在磁盘上。存储在磁盘上。进程进程:通常被定义为一个:通常被定义为一个正在运行的程序的实例正在运行的程序的实例,是一个程序在其,是一个程序在其自身的地址空间中的一次执行自身的地址空间中的一次执行活动活动。进程是活的,是资源申请、调度和独立运行的单位,因此,它使用进程是活的,是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序是死的,它不占用系统的运行资源。系统中的运行资源;而程序是死的,它不占用系统的运行资源。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1537进程与线程进程与线程进程与线程进程与线程 进程进程是不活泼的。进程从来不执行任何东西,它是不活泼的。进程从来不执行任何东西,它只是线程的容只是线程的容器器。若要使进程完成某项操作,它必须拥有一个在它的环境中运行。若要使进程完成某项操作,它必须拥有一个在它的环境中运行的线程,此线程负责执行包含在进程的地址空间中的代码。的线程,此线程负责执行包含在进程的地址空间中的代码。 单个进程可能包含若干个线程单个进程可能包含若干个线程,这些线程都,这些线程都“同时同时” 执行进程执行进程地址空间中的代码。地址空间中的代码。 每个进程至少拥有一个线程每个进程至少拥有一个线程,来执行进程的地址空间中的代码。,来执行进程的地址空间中的代码。当创建一个进程时,操作系统会自动创建这个进程的当创建一个进程时,操作系统会自动创建这个进程的第一个线程,第一个线程,称为主线程称为主线程。此后,该线程可以创建其他的线程。此后,该线程可以创建其他的线程。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1538获得互斥对象所有权获得互斥对象所有权利用互斥对象实现线程同步利用互斥对象实现线程同步 线程必须主动请求共享对象的使用权才能获得该所有权,这可以通线程必须主动请求共享对象的使用权才能获得该所有权,这可以通过调用过调用WaitForSingleObject函数实现。函数实现。DWORD WatiForSingleObject(HANDLE hHandle, DWORD dwMillisecond); n HANDLE hHandle所请求对象的句柄。本例为互斥对象句柄:所请求对象的句柄。本例为互斥对象句柄:hMutex。一旦互斥对象处于。一旦互斥对象处于有有信号状态,则该函数返回信号状态,则该函数返回,接着,操作系统会将这个互斥对象设为未通知,接着,操作系统会将这个互斥对象设为未通知状态。如果该互斥对象处于状态。如果该互斥对象处于无信号状态,则该函数会一直等待,这样会暂无信号状态,则该函数会一直等待,这样会暂停线程的执行停线程的执行。n DWORD dwMillisecond指定等待的时间,如果指定的时间间隔已过,即使所请求的对象处于无信指定等待的时间,如果指定的时间间隔已过,即使所请求的对象处于无信号状态,该函数也返回。如果该参数为号状态,该函数也返回。如果该参数为0,该函数立即返回。如果该参数为,该函数立即返回。如果该参数为INFINTE,则该函数永远等待,直到互斥对象处于由信号状态才返回。,则该函数永远等待,直到互斥对象处于由信号状态才返回。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1539利用互斥对象实现线程同步利用互斥对象实现线程同步#include #include DWORD WINAPI ThreadProc1( LPVOID lpParameter); DWORD WINAPI ThreadProc2( LPVOID lpParameter); int tickets = 1;HANDLE hMutex;void main()HANDLE hThread1;HANDLE hThread2;hThread1 = CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);hThread2 = CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);CloseHandle(hThread1);CloseHandle(hThread2);hMutex = CreateMutex(NULL, FALSE, NULL);Sleep(5000);火车站售票系统模拟程序火车站售票系统模拟程序Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1540利用互斥对象实现线程同步利用互斥对象实现线程同步/线程线程1 1的入口函数(售票窗口的入口函数(售票窗口1 1)DWORD WINAPI ThreadProc1(LPVOID lpParameter)while (TRUE) WaitForSingleObject(hMutex,INFINITE);if (tickets = 100)Sleep(1);cout thread1 sell ticket : tickets + endl;elsebreak;ReleaseMutex(hMutex); return 0;火车站售票系统模拟程序火车站售票系统模拟程序Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1541利用互斥对象实现线程同步利用互斥对象实现线程同步/线程线程2 2的入口函数(售票窗口的入口函数(售票窗口2 2)DWORD WINAPI ThreadProc2(LPVOID lpParameter)while (TRUE) WaitForSingleObject(hMutex,INFINITE);if (tickets = 100)Sleep(1);cout thread2 sell ticket : tickets + endl;elsebreak;ReleaseMutex(hMutex); return 0;火车站售票系统模拟程序火车站售票系统模拟程序Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1542动态链接库概述动态链接库概述n 微软任何一个版本的微软任何一个版本的Windows操作系统,操作系统,动态链接库动态链接库(DLL)都)都是其是其核心核心和和基础基础。n 动态链接库动态链接库不能直接运行不能直接运行。它们是一些独立的文件,其中包含能。它们是一些独立的文件,其中包含能被可执行程序或其它被可执行程序或其它DLL调用来完成某项工作的函数。调用来完成某项工作的函数。只有在其它只有在其它模块调用动态链接库中的函数时,它才发挥作用模块调用动态链接库中的函数时,它才发挥作用。n Windows API中的所有函数都包含在中的所有函数都包含在DLL中。其中有中。其中有3个最重要的个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个,它包含用于画图和显示文本的各个函数。函数。Dll 概述概述Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1543动态链接库概述动态链接库概述使用动态链接库的好处(简答)使用动态链接库的好处(简答)增强程序的扩展性增强程序的扩展性可以采用多种编程语言来写可以采用多种编程语言来写提供二次开发的平台提供二次开发的平台简化项目管理简化项目管理节省磁盘空间和内存节省磁盘空间和内存有助于资源共享有助于资源共享Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1544Win32 DLL 的创建的创建导出导出DLL中的函数中的函数 注意注意:应用程序如果想要访问:应用程序如果想要访问 DLL中的函数,那么该函数中的函数,那么该函数必须是已经必须是已经被导出被导出的函数。的函数。 为了让为了让DLL 导出函数,需要在每一个将要被导出的导出函数,需要在每一个将要被导出的函数前函数前添加标识符:添加标识符:_declspec (dllexport)。_declspec (dllexport) int add(int a, int b)return a + b;_declspec (dllexport) int subtract(int a, int b)return a - b;Build后,在后,在Debug目录下会产生一个动态库目录下会产生一个动态库Dll1.dll文件和一个引文件和一个引入库文件入库文件Dll1.lib。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1545Win32 DLL 的创建的创建导出导出DLL中的类中的类 在动态链接库中,除了函数能被导出,在动态链接库中,除了函数能被导出,C+类同样也能够被类同样也能够被导出。导出。 为了让为了让DLL导出类,在导出类,在DLL中定义类时,需要在中定义类时,需要在class关键关键字和类名之间字和类名之间加入标识符:加入标识符:_declspec (dllexport)。 注意:注意:在访问导出类的函数时,仍受限于函数自身的访问权在访问导出类的函数时,仍受限于函数自身的访问权限。也就是说,如果该类的某个函数访问权限不是限。也就是说,如果该类的某个函数访问权限不是Pubilc,那么,那么外部程序仍无法访问这个函数。外部程序仍无法访问这个函数。 另外,在实现动态链接库时,可以不导出整个类,而只导另外,在实现动态链接库时,可以不导出整个类,而只导出该类中的某些成员函数。具体做法是将标识符添加到成员函出该类中的某些成员函数。具体做法是将标识符添加到成员函数前。数前。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1546隐式链接方式加载隐式链接方式加载DLL 以上程序能够成功通过编译,但在程序链接时会产生三个错以上程序能够成功通过编译,但在程序链接时会产生三个错误,因为此时链接器不知道这两个函数是在哪个地方实现的。误,因为此时链接器不知道这两个函数是在哪个地方实现的。 为了解决这个问题,就需要利用动态链接库的为了解决这个问题,就需要利用动态链接库的引入库文件引入库文件。引入库文件并没有包含实际的代码,它是用来为链接程序提供必引入库文件并没有包含实际的代码,它是用来为链接程序提供必要的信息,以便在可执行文件中建立动态链接时需要用到的重定要的信息,以便在可执行文件中建立动态链接时需要用到的重定位表。位表。使用引入库文件使用引入库文件加载引入库文件的两种方法加载引入库文件的两种方法(加载之前先把(加载之前先把dll1.lib复制到复制到dlltest工程目录中)工程目录中): 选择选择“projectSettings”命令,选择命令,选择link选项卡,在选项卡,在“Object/library modules”选项编辑框中输入:选项编辑框中输入:dll1.lib 通过通过“add files to project”直接将直接将dll1.lib加入到工程中。加入到工程中。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1547显式加载方式加载显式加载方式加载DLL名字改编问题名字改编问题 如果希望动态链接库在编译时,导出函数的名称不要发生改如果希望动态链接库在编译时,导出函数的名称不要发生改变,在定义导出函数时,需要加上限定符:变,在定义导出函数时,需要加上限定符:extern “C”extern C _declspec (dllexport) int add(int a, int b)return a + b;extern C _declspec (dllexport) int subtract(int a, int b)return a - b; extern “C”可以解决可以解决C+对对C语言之间的函数名改编问题,但这语言之间的函数名改编问题,但这种方法有一个缺陷,就是不能用于导出一个类的成员函数,种方法有一个缺陷,就是不能用于导出一个类的成员函数,只能只能用于导出全局函数这种情况用于导出全局函数这种情况。Fundamentals of Computers制作:刘晓翔JINAN University暨南大学电气信息学院Windows编程2024/8/1548DllMain函数函数DllMain函数介绍函数介绍 一个一个Win32程序,对可执行模块来说,其入口函数是程序,对可执行模块来说,其入口函数是WinMain;而对而对DLL来说,其入口函数是来说,其入口函数是DllMain,该函数是可选的。也就是说,该函数是可选的。也就是说,在编写在编写DLL程序时,可以提供也程序时,可以提供也可以不提供可以不提供DllMain函数函数。 注意:注意:如果提供了如果提供了DllMain函数,那么在此函数中不要进行太复函数,那么在此函数中不要进行太复杂的调用。因为在加载该动态链接库时,杂的调用。因为在加载该动态链接库时,user32.dll 或或 GDI32.dll等等一些一些Windows核心核心DLL还没有加载,这时会导致程序终止。还没有加载,这时会导致程序终止。
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号