




已阅读5页,还剩437页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ppt简介,共14章、442页,涵盖了vc的基础介绍,以及mfc程序的创建,控件的使用、多线程、多媒体编程、网络编程、动态链接库的使用等等,是那些喜欢MFC但是不知道从何学起的MFC爱好者的最佳的基础教材!,第1章VisualC+集成开发环境,VisualC+是一个功能强大的可视化应用程序开发工具。其凭借强大功能,受大了广大程序员的欢迎。当今流行的VisualC+的开发工具是6.0版本。下面来介绍VisualC+6.0的一些基本情况。,1.1VisualC+6.0概述,VisualC+是一种C/C+语言的集成开发环境(IDE)。当最初还处于DOS时代的Borland公司推出了TurboPascal和TurboC,让程序员感受到了把编译器和编辑器集成在一起使用时的方便。Microsoft公司也看到了这一点,于是,两个公司开始合作,推出了QuickC和MicrosoftC/C+等多个DOS版本的C/C+集成开发环境。随着Windows的不断成熟,于是Microsoft开始开发Windows下的VisualC+。经过多次版本的修订与更新,现在大多数程序员使用的是VisualC+6.0版本。VisualC+是一个可视化的C+的集成开发环境。在使用VisualC+时,开发人员可以通过鼠标拖动方便地设计程序的界面,相应的代码系统会自动生成。MFC(MicrosoftFundermentalClasses)是微软提供的VisualC+可以调用的类库,其中封装了开发人员常用的类。使用MFC可以大大提高编程人员的工作效率。,1.2VisualC+6.0界面介绍,安装好VisualC+开发环境后,桌面上并没有其快捷图标,需读者自己修改。选择“开始”菜单,从所有程序中,找到MicrosoftVisualStudio6.0级联菜单下的MicrosoftVisualC+菜单项。选择该菜单项,并将其拖动到桌面上,则在桌面上创建了MicrosoftVisualStudio的快捷图标。双击快捷图标,即可启动VisualC+6.0集成开发环境。每次运行VisualC+6.0时,会弹出一个【Tipoftheday】对话框,如下图所示。,1.2VisualC+6.0界面介绍,技巧:【Tipoftheday】对话框中介绍了很多关于开发环境的使用方法以及编程方面的小技巧。如果想在下次启动VisualC+6.0时不再显示该提示对话框,可以选择下一次启动时不再显示它。,1.2VisualC+6.0界面介绍,为了便于说明,首先创建一个IDE的MFC项目(具体创建步骤,后面会详细介绍),如下图所示。,1.2VisualC+6.0界面介绍,从上图中可以看出,VisualC+的界面被分成了7部分。上面依次标题栏、菜单栏和工具栏。中间左侧部分是工作区窗口,右侧部分是编辑区。最下方是输出窗口和状态栏。,1.2.1工作区窗口和输出窗口,工作区窗口和输出窗口是在一个程序编译时使用最多的停靠式窗口。工作区窗口中显示了当前程序中的所有类、资源和文件信息。工作区窗口分为3个部分:ClassView(类视图)、ResourceView(资源视图)和FileView(文件视图)。ClassView:显示当前工作区中所有工程定义的C+类。双击某个类名,VisualC+会自动打开这个类的文件,并将编辑区定位到该类的定义处。双击类中的成员函数和变量,编辑区则定位到该成员函数或变量的定义处。,1.2.1工作区窗口和输出窗口,ResourceView:显示当前工作区中所有的资源。这些资源包括快捷键、对话框、图标、菜单、字符条编辑器、工具栏和版本信息。双击其中的ID号,会显示相应的资源信息。FileView:显示属于当前工程的所有文件,包括C/C+源文件、头文件、资源文件等。输出窗口与工作区一样,分为多个选择卡。其中最常用的选项卡被放在了最外面,分别为Build、Debug、FindinFiles1和FindinFiles2。,1.2.1工作区窗口和输出窗口,Build:Build显示工程在创建中,经过的每一个步骤及相应信息。如果出现编译链接错误,那么出现错误的文件、原因、行号等内容会显示在Build中。双击该错误信息行,编辑区则定位在该错误出现的行。Debug:工程通过编译后,运行调试版本时,Debug选项卡中会显示具体的调试信息。,1.2.1工作区窗口和输出窗口,FindinFiles1和FindinFiles2:两个选项卡的作用相同,用于显示从多个文件中查找字符串的结果。当用户想要查看某个函数或变量出现在哪些文件中,单击【Edit】|【FindinFiles】命令,弹出【FindinFiles】对话框,如下图所示。在【FindinFiles】对话框中的【Findwhat】后的编辑框中,输入想要查找的内容,单击【Find】按钮即可。查找到的内容会输出到FindinFiles选项卡中。,1.2.2菜单栏和工具栏,菜单栏位于集成开发环境的顶部。菜单栏由9个菜单项组成:File(文件)、Edit(编辑)、View(视图)、Insert(插入)、Project(工程)、Build(编译)、Tools(工具)、Windows(窗口)、Help(帮助)。每一个菜单项都有一个下拉式菜单,其中的菜单项用于完成特定的功能。工具栏位于菜单栏的下面。工具栏可以称作是美化的菜单栏,其由许多按钮构成。其中的按钮用于完成特定的功能。工具栏可以任意拖动,也可以成为一个浮动窗口。,1.2.3编辑区,在VisualC+中,编写应用程序代码的位置就是编辑区。该编辑区的功能十分强大,智能化程度也非常高。在编辑区内,除了能编写C/C+语言外,还能编写SQL、HTML和VBScript等其他编程语言。如下图所示。,1.2.4联机帮助,VisualC+6.0不像其他集成开发环境一样把帮助系统集成在开发环境内部,而是提供了一个专门为VisualC+设计的MSDN类库。MSDN虽然是一个独立的帮助系统,但却能很好地和VisualC+6.0集成在一起。MSDN的使用方式有以下几种:单击【Help】|【Contents】命令;单击【Help】|【Search】命令;单击【Help】|【Index】命令;按下【F2】键。通过上述几种命令方式,即可运行MSDN。,1.2.4VisualC+中的文件扩展名,打开程序HelloWorld所在的文件夹,看到该文件夹自动生成了许多扩展名不同的文件,如下图所示。,1.2.6VisualC+中的文件扩展名,了解这些不同的扩展名文件,对于理解VisualC+6.0如何组织和管理项目文件是很有必要的。有关这些文件扩展名及其说明,如下表所示。,第2章MFC与应用程序框架,在VisualC+集成开发环境下,使用微软基础类库MFC,可以开发出功能强大的Windows应用程序。另外,通过MFCAppWizard自动生成的MFC应用程序框架,还可以很方便地开发自己想要实现的功能。本章将先介绍有关MFC的基础知识,然后对MFC应用程序框架作具体介绍。,2.1微软基础类库MFC,MFC是一种重要的编程方法,它是微软公司的特定的应用程序包装接口。本节将讲解MFC概述及其类库结构。,2.1.1MFC概述,MFC的英文全称是MicrosoftFoundationClasses,即微软的基础类库。MFC的本质就是一个包含了许多微软公司已经定义好的对象的类库。虽然开发人员要编写的程序在功能上各有不同,但是从结构上讲,都可以化分为对用户界面的设计、对文件的操作、对数据库的访问及对多媒体的使用等一些最主要的方面。这一点正是微软提出MFC类库最重要的原因。在MFC类库中,大约有200个类。在进行程序设计时,只需简单地调用已有的类及类中的方法即可。另外,还可以利用“继承”方法从已有类中派生出自己想要的类。这时,派生出来的类不但拥有父类中的方法和属性,还可以根据自己的需求,自定义一些特殊的属性和方法,使得派生类功能更加强大。MFC有较好的移植性,可应用于众多平台。,2.1.2MFC类库结构,MFC中类可划分为基类、应用程序结构类、窗口类、OLE类、数据库类等10大类,而且在其中的一些大类的基础上又派生出许多子类。MFC的类库结构的层次图如下图所示。,2.1.2MFC类库结构,从上图中可以看出,CObject是一个原始基类。绝大多数MFC类的最终基类都是CObject。原始基类下面,主要包括以下几种类:MFC应用程序结构类,窗口、对话框和控件类,输出(设备文本)和绘图类,简单数据类型类,数组、列表和映射类,文件和数据库类,Internet和网络类,OLE类以及高度和异常类。MFC的应用程序结构类分为CWinApp和CWinThread。使用MFC创建的每一个应用程序都包含一个由类CWinApp派生而来的应用程序对象。该对象是一个全局对象。应用程序对象主要用于处理应用程序的初始化,同时也处理应用程序事件的消息循环。CCmdTarget和CCmdUI为MFC中常用的有关发送命令的类。CDocument为MFC中常用的应用程序文档的基类。CDocTemplate为文档模版类,通常是应用程序的单文档或多文档的基类。CView类是常用的视图类。,2.2MFC应用程序框架分析,在前面介绍过如何创建一个基于单文档的应用程序。对于如何选择性地创建基于多文档或是基于对话框的应用程序,将会在后续章节详细介绍。本节主要对MFC应用程序框进行简单的概括,使读者了解MFC应用程序框架的结构与工作机制。,2.2.1入口函数,入口函数就是指一个程序的入口点。WinMain函数是Windows程序的入口函数。为了便于讲解,首先要创建一个MFC应用程序,程序名命名为sample0201。具体创建步骤不再详细介绍。从创建好的sample0201程序中,并不能找到WinMain函数。这是因为典型Windows程序的大部分初始化工作都是标准化的,因此把WinMain函数隐藏在应用程序的框架中。当一个程序编译时,会自动将该函数链接到程序中。在计算机中找到VisualC+的安装目录,笔者安装在F盘,则按照下面这个路径依次打开文件夹,“F:ProgramFilesMicrosoftVisualStudioVC98MFCSRC”。打开后,会发现一个源文件“WinMain.cpp”。该文件中则定义了MFC应用程序的入口函数AfxWinMain。文件的源代码如下:,2.2.1入口函数,2.2.1入口函数,当一个应用程序启动时,会自动调用应用程序框架内部的AfxWinMain函数。根据其前缀Afx就知道WinMain是一个全局的MFC函数。从上述代码中可以看出,WinMain函数会查找该应用程序的一个全局构造对象。该对象是由CWinApp的派生类创建,因此有程序启动时,它就被创建好了。然后WinMain对该应用程序进行初始化,在此过程调用的是该程序全局构造对象的InitApplication()和InitInstance()函数。完成初始化后,WinMain调用Run()函数,运行应用程序的消息循环。最后结束应用程序时,WinMain调用AfxWinTerm()函数,做一些清理工作。,2.2.2InitInstance()函数,InitInstance()函数的作用是初始化程序。每次启动一个应用程序时,Winmain函数会自动调用InitInstance()函数。打开创建的程序sample0201,在该程序的CSample0201App类中,可以看到该程序对InitInstance()函数进行了重载。该重载代码如下:,2.2.2InitInstance()函数,从上述代码中可以看出,在ShowWindow和UpdateWindos之前,程序要做两个动作,一个是注册窗口类,另一个是构建窗口类。InitInstance()函数规定了生成的应用程序是基于单文档的、基于多文档的或是基于对话框的。因此在CWinApp中必须重载InitInstance()函数。,2.2.3应用类Run()函数,与查找WinMain函数类似,在VisualC+的安装目录下,按照下面这个路径依次打开文件夹,“F:ProgramFilesMicrosoftVisualStudioVC98MFCSRC”。打开后,会发现一个源文件“THRDCORE.CPP”。该文件中定义了应用类Run()函数,源代码如下:,2.2.3应用类Run()函数,从上述代码中可以看出,如果消息队列没有消息,则调用OnIdle()函数,并递增iIdleCount计数标志,该计数标志表示在两次消息处理过程只共调用了多少次OnIdle()函数。bIdle是消息队列空闲的标志,当消息队列有消息时,则调用PumpMessage()函数,进行消息翻译和消息派发。其中PreTranslateMessage(/关闭记录集m_pConnection-Close();/关闭连接,第13章多线程编程,Windows是一个多任务的操作系统。多线程运行可以提高系统的运行效率,因此使用比较广泛。本章将对进程与线程进行简单介绍。内容包括:进程与线程、线程的使用、线程的终止与通信等。通过本章的学习,读者可以在程序中调用其他应用程序,可以实现进程间的通信,可以实现线程的同步。下面对多线程技术进行详细介绍。,13.1进程与线程,进程(Process)是应用程序的执行实例。每个进行都可以访问进程中的所有资源。一个进程是由一个或多个进行、代码、数据和应用程序在内存中的其他资源组成。,当一个应用程序启动,相应的一个进程进行也会启动,这个进行称为父进程。一个应用程序还可以启动其他进程,被启动的其他进程称为子进程。想要查看进程,可以打开Windows的任务管理器。单击【进程】标签,在【进程】选择卡中可以查看当前系统中的各个进程,如右图所示。进程是资源的分配单位,每个进程都拥有自己的地址空间和上下文环境。,13.1进程与线程,进程是线程的容器,线程是进程内部的一个执行单元。一个进程可以有一个或是多个线程,但这些线程仅生存于该进程中。也就是说,线程是在它所属的进程地址空间里执行代码,并在进程的地址空间对数据进行操作。线程用于描述进程中的运行路径。当一个进程被启动时,系统就要创建一个主线程。该主线程是应用程序需要的唯一线程,但进程也可以创建其他线程来完善进程的其他操作。,13.2线程的分类,在MFC中,线程分为两类:用户界面线程(User-InterfaceThread)和工作者线程(WorkerThread)。用户界面线程:该线程通常用来处理用户的输入并响应用户生成的事件和消息。用户界面线程是从CWinThread类派生而来的。在MFC中,CWinApp对象就是一个用户界面线程。通常情况下,用户界面线程都是主线程。当应用程序启动时,用户界面线程随之启动。当应用程序退出时,用户界面线程也会随之终止。工作者线程:该线程通常不需要用户进行输入,由后台进行处理。因此,工作者线程又被称为后台线程。工作者线程和用户界面线程的区别在于,工作者线程不用从CWinThread类派生。,13.3线程类(CWinThread),在MFC上,CWinThread类封装了对线程的操作。下面对CWinThtead类中的成员函数和成员变量作具体介绍。其中,CWinThread类中常用的函数如下:(1)调用CreateThread()函数可以创建一个新的线程,该函数的原型如下:dwCreateFlags:表示线程创建的标志。nStackSize:表示线程堆栈的大小。lpSecurityAttrs:表示线程的安全属性。,13.3线程类(CWinThread),(2)调用SetThreadPriority()函数可以设置线程的优先级,该函数的原型如下:其中,nPriority参数定义了线程的优先级。其取值如下表所示。,13.3线程类(CWinThread),(3)调用GetThreadPriority()函数可以获取线程的优先级,该函数原型如下:(4)调用PostThreadMessage()函数可以向另一个CWinThread对象发送消息,该函数的原型如下:message:表示用户定义消息的标识。wParam:表示消息的第一个参数。lParam:表示消息的第二个参数。,13.3线程类(CWinThread),(5)调用SuspendThread()函数可以将线程的挂起计数加1,当线程的挂起计数大于0时,该线程将暂停执行,称之为挂起状态。该函数的原型如下:(6)调用ResumeThread()函数可以将线程的挂起计数减1。当线程的挂起计数减少到0时,恢复线程的执行。该函数的原型如下:,13.3线程类(CWinThread),在CWinThread类中,还需要重载一些函数来完成对线程的操作。(1)重载InitInstance()函数用于控制用户界面线程实例的初始化工作,该函数的原型如下:(2)重载ExitInstance()函数用于控制清理操作,该函数的原型如下:(3)重载OnIdle()函数用于控制线程空闲处理操作,该函数的原型如下:lCount:表示计数器。此外,CWinThread类中有以下几个重要的成员变量。m_hThread:表示当前线程的句柄。m_nThreadID:表示当前线程的ID。m_pMainWnd:表示指向应用程序主窗口的指针。,13.4线程的使用,在MFC中,创建一个新的线程时,可以使用全局函数AfxBeginThread()。AfxBeginThread()有两种原型,分别用于创建用户界面线程和工作者线程。,13.4.1启用用户界面线程,当启用用户界面线程时,调用AfxBeginThread()的原型如下:pThreadClass:表示用户界面线程对象运程时类结构指针。pParam:表示传递给控制函数的参数。nPriority:表示线程的优先级。nStackSize:表示线程堆栈的大小。dwCreateFlags:表示线程创建的标志。lpSecurityAttrs:表示安全属性(SECURITY_ATTRIBUTES)结构指针。,13.4.1启用用户界面线程,另外,启用用户界面线程还可以先创建一个CWinThread类的对象,然后调用CreateThread()函数。代码如下:,13.4.2启用工作者线程,当启用工作者线程时,调用AfxBeginThread()的原型如下:pfnThreadProc:表示工作者线程的控制函数指针。pParam:表示传递给控制函数的参数。nPriority:表示线程的优先级。nStackSize:表示线程堆栈的大小。dwCreateFlags:表示线程创建的标志。lpSecurityAttrs:表示安全属性(SECURITY_ATTRIBUTES)结构指针。注意:函数的返回值是一个线程指针。一般情况下,需要保存该指针,以便于以后根据该指针来终止该线程。,13.4.3用户界面线程,在实际应用过程中,有时需要在线程中创建对话框。此时,可以使用用户界面线程来实现。在MFC中,创建用户界面线程的具体步骤如下:(1)从CWinThread类派生一个子类。(2)在子类的InitInstance()函数中设置线程的主窗口。(3)调用AfxBeginThread()函数创建用户界面线程。,13.4.3用户界面线程,【示例13-1】创建用户界面线程。在一个基于对话框的MFC应用程序中,创建一个用户界面线程用来启动另外一个对话框。(1)创建一个基于对话框的MFC应用程序sample1301。(2)设计对话框资源,如下图所示。,13.4.3用户界面线程,(3)单击【Insert】|【Resource】命令,弹出【InsertResource】(插入资源)对话框。选择Dialog结点,如左图所示。(4)设计新插入的对话框资源,如右图所示。,13.4.3用户界面线程,(5)双击新添加的对话框资源,为其添加相应的类CSubDlg,如左图所示。(6)单击【Insert】|【NewClass】命令,弹出【NewClass】对话框。添加一个CWinThread类的子类CSubThread,如右图所示。,13.4.3用户界面线程,(7)添加并修改CSubThread类中的数据成员和成员函数。其中,SubThread.h文件中的代码如下:SubThread.cpp文件中的代码如下:,13.4.3用户界面线程,(8)在对话框类CSample1301Dlg的【创建用户界面线程】按钮中添加如下代码:在【取消】按钮中添加如下代码:,13.4.3用户界面线程,(9)运行程序sample1301,弹出主对话框。单击【创建用户界面线程】按钮,弹出【用户界面线程】对话框。当运行程序sample1301的同时,可以打开系统的任务管理器进行查看。当主对话框弹出时,进程中多了一个sample1301.exe进程。当弹出【用户界面线程】对话框时,没有相应的进程出现。从上述内容中可以看出,本例成功地创建了一个用户界面线程。,13.4.4工作者线程,创建工作者线程不需要使用CWinThread类的派生类,而是需要实现控制函数。在工作者线程的控制函数中,定义了线程的生命周期。当进入控制函数时,线程将被启动。而当退出函数时,线程将被终止。【示例13-2】创建工作者线程。在一个基于对话框的MFC应用程序中,创建工作者线程,并在对话框进行初始化时启用。(1)创建一个基于对话框的MFC应用程序sample1302。(2)设计对话框资源,如下图所示。,13.4.4工作者线程,(3)添加成员变量。为两个ListBox控件添加成员变量,分别为m_list1和m_list2。其中,类别为Control,类型为CListBox。(4)为CSample1302Dlg类添加两个自定义函数,分别如下:(5)为控制函数添加代码。其中,FirstThread()函数中添加的代码如下:SecondThread()函数中添加的代码如下:,13.4.4工作者线程,(6)在对话框类CSample1302Dlg的OnInitDialog()函数中添加如下代码:(7)修改Sample1302Dlg.h文件中的函数声明,将线程函数声明为static函数。,13.4.4工作者线程,(8)运行程序sample1302,结果如图13.8所示。注意:如果不按照第(7)步骤对Sample1302Dlg.h文件进行修改,会出现如下错误提示:AfxBeginThread:noneofthe2overloadscanconvertparameter1fromtypeunsignedint(void*)。,13.5线程的终止,当一个线程终止时,关闭该线程所属的所有对象句柄,将该线程对象状态变为有信息号状态,并将该线程对象终止状态STILL_ACTIVE改为退出码。通常情况下,线程终止分为两种:正常终止和异常终止。,13.5.1正常终止线程,对于用户界面线程而言,使其正常终止只需在用户界面线程中调用PostQuitMessage()即可。该函数的原型如下:nExitCode:表示线程的退出码。对于工作者线程而言,当控制函数正常执行到函数的结束点(return语句)后,该线程也就正常终止了。另外,用户也可以选择使用AfxEndThread()函数来终止该线程。AfxEndThread()函数的原型如下:,13.5.2异常终止线程,异常终止是指线程内部出现自身无法终止的情况,在其他线程中强行终止该线程。异常终止用于在紧急情况下安全退出控制。如果想要终止线程,可以使用TerminateThread()函数。该函数的原型如下:hThread:表示将要终止的线程句柄。该参数可以使用创建线程返回时返回的CWinThread从m_hThread成员变量中得到。dwExitCode:表示线程的退出码。,13.5.3线程的退出码,根据线程的退出码,可以判断线程的执行情况。使用GetExitCode()函数可以获取工作者线程或用户界面线程退出码。该函数的原型如下:hThread:表示线程句柄。该参数可以使用创建线程返回时返回的CWinThread从m_hThread成员变量中得到。lpExitCode:表示接收返回的终止状态的地址。,13.5.3线程的退出码,如果线程没有被终止,则终止状态返回STILL_ACTIVE。如果线程已经被终止,则返回的终止状态可以是以下取值中的一个:在ExitThread()或TerminateThread()函数中指定的退出值。在线程函数的return语句中的返回值。线程所属进程中的退出值。,13.5.3线程的退出码,想要获取线程的退出码,还要做一些其他工作。一般线程终止后,线程对象将被删除,用户不能获取m_hThread句柄。想要解决这个问题,可以采用以下两个办法。(1)在创建线程后,设置线程对象的m_bAutoDelete成员变量为FALSE。这样,CWinThread对象在线程终止后仍将存在。在退出应用程序之前,还需要手动添加删除CWinThread线程对象的代码。(2)单独选择保存线程句柄。在创建线程后,使用Win32函数DuplicateHandle()将m_hThread复制到另一个句柄。这样,尽管对象被自动删除了,但使用复制的句仍然可以获取线程的退出码。注意:采用第二种方法时,在复制句柄之前,线程不能终止。最安全的方法是在创建线程进使用CREATE_SUSPENDED挂起,复制好后,调用ResumeThread()函数恢复线程的执行。,13.6线程的通信,通常情况下,在次线程是为主线程服务的,这就预示着主线程和次线程之间会进行及时的通信。下面对线程间的通信作简单介绍。,13.6.1通信原理,在线程间进行通信的过程中,需要用到以下几个函数。其中,调用PostMessage()函数可以进行线程间的通信。该函数的原型如下:hWnd:表示消息发送的目的窗口句柄。Msg:表示将要发送的消息。wParam:表示消息的第1个参数。lParam:表示消息的第2个参数。,13.6.1通信原理,调用PostThreadMessage()函数可以向某个线程发送消息,该函数的原型如下:idThread:表示线程标识。Msg:表示将要发送的消息。wParam:表示消息的第1个参数。lParam:表示消息的第2个参数。,13.6.1通信原理,如果想要对消息进行外理,用户界面线程和工作者线程的处理方式不同。在用户界面线程中,有两种方式对消息进行处理。(1)使用消息映射宏ON_THREAD_MESSAGE。该宏的定义格式如下:message:表示消息标识ID。memberFxn:表示CWinThread消息处理函数的名称。(2)使用PreTranslateMessage()函数,直接对消息进行处理。该函数的原型如下:pMeg:表示包含消息的MSG结构指针。,13.6.1通信原理,在工作者线程中,可以使用GetMessage()函数对消息进行处理。该函数的原型如下:lpMsg:表示消息MSG结构指针。hWnd:表示窗口句柄。wMsgFilterMin:表示第1个消息。wMsgFilterMax:表示最后一个消息。,13.6.2用户界面线程通信,下面通过一个实例来介绍用户界面线程间的通信。【示例13-3】实现用户界面线程间的通信。(1)创建一个基于对话框的MFC应用程序sample1303。(2)设计对话框资源,如下图所示。(3)添加成员变量。其中,从上到下,各文本框对应的成员变量分别为m_edit1、m_edit2和m_edit3。其中,m_edit1、m_edit2的类别为Value,类型为int。m_edit3的类别为Control,类型为CEdit。,13.6.2用户界面线程通信,(4)添加CWinThread类的派生类。单击【Insert】|【NewClass】命令,弹出【NewClass】对话框。添加一个CWinThread类的子类CWinThread,如图13.10所示。,13.6.2用户界面线程通信,(5)在CompareThread.h文件中添加如下代码:在CompareThread.cpp文件中添加如下代码:(6)在CSample1303Dlg类中添加一条自定义消息,代码如下:,13.6.2用户界面线程通信,(7)重载CCompareThread类的PreTranslateMessage()函数。右击CCompareThread类,在弹出的弹出式菜单中选择【AddVirtualFunction】菜单项,弹出【NewVirtualOverrideforClassCCompareThread】对话框。从左边的列表框中双击【PreTranslateMessage】选项,将其移动到右边的列表框中,如下图所示。,13.6.2用户界面线程通信,(8)单击【AddandEdit】按钮,进入编辑区。在PreTranslateMessage()函数中添加代码如下:,13.6.2用户界面线程通信,(9)为对话框类CSample1303Dlg添加一个成员变量,如下图所示。该变量用于保存线程的标识。(10)在对话框类CSample1303Dlg的初始化函数中创建并启动用户界面线程,代码如下:,13.6.2用户界面线程通信,(11)在【比较】按钮的消息响应函数中添加如下代码:(12)运行程序sample1303,结果如下图所示。在运行程序时,单击【比较】按钮,并没有直接对a、b的值进行比较,而是发送一条WM_CPMPARE的消息,交由CCompareThread类的PreTranslateMessage()函数进行处理。,13.7线程的同步,在编写多线程应用程序时,经常会出现线程间同步访问共享资源的情况。多个线程同时访问同一个共享资源将可能发生无法预知的错误。例如,一个线程正在更新数据集,而同时另外一个线程正在读取数据。那么,第二个线程只会读取一部分正确的数据。为了解决这个问题,VisualC+6.0提供了同步类。同步类包括同步对象和同步访问对象。其中,同步对象分为4种,分别是CSemaphore(信号量)、CCriticalSection(临界区)、CMutex(互斥量)和CEvent(事件)。下面对这些同步类分别进行介绍。,13.7.1同步访问对象,同步访问对象提供了对同步对象的封装。同步访问对象分为两种,分别是CSingleLock和CMultiLock。1CSingleLock如果一次只需要等待一个同步对象,可以使用CSingleLock类的对象。CSingleLock类的构造函数如下:pObject:表示同步对象指针。该参数不能为NULL。bInitialLock:表示是否在初始化时对同步对象进行访问。如果想要获取同步对象,可以使用Lock()函数。该函数的原型如下:dwTimeOut:表示同步对象等待的时间。,13.7.1同步访问对象,如果想要释放同步对象,可以使用Unlock()函数。该函数的原型如下:lCount:表示要释放的对象数。lPrevCount:表示同步对象接收的前一次的个数。如果想要判断等待的同步对象是否被锁定,可以使用IsLocked()函数。该函数的原型如下:,13.7.1同步访问对象,2CMultiLock如果在某个特定的时刻要使用多个同步对象,可以使用CMultiLock类的对象。CMultiLock类的构造函数原型如下:ppObjects:表示同步对象数组指针。dwCount:表示同步对象数组元素的个数。bInitialLock:表示是否在初始化时对同步对象进行访问。,13.7.1同步访问对象,如果想要获取同步对象,可以使用Lock()函数。该函数的原型如下:dwTimeOut:表示同步对象等待的时间。bWaitForAll:表示是否等待所有的同步对象。dwWakeMask:指定其他放弃等待的条件。,13.7.1同步访问对象,如果想要释放同步对象,可以使用Unlock()函数。该函数的原型如下:lCount:表示要师范的对象数,该参数必须大于0。lPrevCount:表示同步对象接收的前一次的个数。如果想要判断等待的同步对象是否被锁定,可以使用IsLocked()函数。该函数的原型如下:,13.7.2使用信号量实现线程同步,CSemaphore类对象代表一个“信号量”,可以允许一定数目的线程访问某个共享资源。信号量对象中保存了当前同时访问某个共享资源的线程计数。如果该计数值为0,则所有对这个CSemaphore类对象所控制资源的访问将被放到一个队列中进行等待,直到超时或计数值不为0。,13.7.2使用信号量实现线程同步,CSemaphore类的构造函数原型如下:lInitialCount:表示信号量对象初始化计数。该参数的值决定了在信号量对象建成后,能同时访问其中资源的最大线程数目。该参数的取值在0IMaxCount之间。lMaxCount:表示信号量对象的最大计数。该参数必须大于0。pstrName:表示要创建的信号量对象的名称。lpsaAttributes:表示信号量对象的安全属性的指针。该参数一般设置为NULL。,13.7.3使用临界区对象实现线程同步,CCriticalSection类对象代表一个“临界区”。当多个线程访问一个独占性共享资源时,可以使用临界区对象。在同一时刻,只允许一个线程可以拥有临界区对象,进而访问资源或是代码段,而其他线程需要等待。CCriticalSection类的构造函数原型如下:,13.7.4使用互斥量对象实现线程同步,CMutex类对象代表一个“互斥量”。互斥量对象属于系统内核对象,它能够使线程拥有对某个资源的绝对访问权限。CMutex类的构造函数原型如下:bInitiallyOwn:表示互斥量对象的初始状态。lpszName:表示互斥量对象的名称。lpsaAttribute:表示互斥量对象的安全属性。,13.7.5使用事件对象实现线程同步,CEvent类对象代表一个“事件”。事件对象是最基本的内核对象,在处理线程同步时,其使用的最为广泛。事件对象主要分为两种:人工重置事件对象和自动重置事件对象。对于人工重置事件对象,可以同时拥有多个线程等待到事件对象,成为可调度线程。对于自动重置事件对象,等待该事件对象的多个线程只能有一个线程成为可调度线程。CEvent类的构造函数原型如下:bInitiallyOwn:表示初始化时是否允许同步访问对象拥有该对象。bManualReset:指定事件对象类型,即人工重置事件对象和自动重置事件对象。lpszName:表示事件对象的名称。lpsaAttribute:表示事件对象的安全属性。,13.7.5使用事件对象实现线程同步,Windows系统提供了CreateEvent()函数用于创建事件对象。该函数的原型如下:lpEventAttributes:表示事件对象的安全属性。bManualReset:指定事件对象类型,即人工重置事件对象和自动重置事件对象。bInitialState:表示事件对象的初始状态。lpName:表示事件对象的名称。,13.7.5使用事件对象实现线程同步,在事件对象创建后,可以使用SetEvent()函数设置事件对象为可用,并释放所有的等待线程。该函数的原型如下:hEvent:表示事件对象句柄。使用ResetEvent()函数设置事件对象为无信号状态。该函数的原型如下:hEvent:表示事件对象句柄。,第14章WinSock网络通信开发,Windows应用程序可以有无限的网络功能,都是建立在WinSock接口的基础上。WinSock是WindowsSockets的简称,也称为Windows套接字,是微软根据BSDUNIX操作系统中流行的Berkeley套接字规范而实现的一套MicosoftWindows下的网络编程接口。本章将具体介绍在VC中,基于Winsock接口进行网络通信程序的开发的基础知识。,14.1网络通信与WinSock基础,网络通信程序是指应用程序需要与网络中其他系统上的应用程序之间进行通讯。在介绍网络通信程序的开发之前,首先简单介绍一下网络通信和WinSock的基础知识和基本概念。,14.1.1WinSock的基本概念,Windows下网络编程的规范WindowsSockets(简称WinSock)是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。它经过不断完善,在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已成为Windows网络编程的事实上的标准。WindowsSockets规范意图在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。任何能够与WinSock兼容实现协同工作的应用程序就被认为是具有WinSock接口。称这种应用程序为WinSock应用程序。WinSock规范定义并记录了如何使用API与Internet协议族(IPS,通常指的是TCP/IP)连接,尤其要指出的是所有的WinSock实现都支持流套接字和数据报套接字。,14.1.1WinSock的基本概念,应用程序则通过调用WinSock提供的API实现相互之间的通讯,而WinSock又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。在ISO的OSI网络七层协议中,WinSock主要负责的是控制数据的输入和输出,也就是传输层和网络层。它屏蔽了数据链路层和物理层,给Windows下的网络编程带来了巨大的变化。,14.1.2TCP/IP协议与WinSock,Internet是建立在TCP/IP协议基础之上,采用了TCP/IP的网络体系结构。TCP/IP不是一个简单的协议,而是一组小的、专业化协议,包括TCP、IP、UDP、ARP、ICMP以及其它的一些被称为子协议的协议。大部分网络管理员将整组协议称为TCP/IP,有时简称为IP。其中的几个重要协议介绍如下:TCP(TransmissionControlProtocol,传送控制协议):这是一种提供给用户进程的可靠的全双工字节流面向连接的协议。它要为用户进程提供虚电路服务,并为数据可靠传输建立检查。大多数网络用户程序使用TCP。UDP(UserDatagramProtocol,用户数据报协议):这是提供给用户进程的无连接协议,用于传送数据而不执行正确性检查。IP(InternetProtocol,网间协议):负责主机间数据的路由和网络上数据的存储,同时为ICMP,TCP,UDP提供分组发送服务,用户进程通常不需要涉及这一层。TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现,因此用户一般不涉及。,14.1.2TCP/IP协议与WinSock,编程时,编程界面有两种形式:一是由内核心直接提供的系统调用;二是使用以库函数方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过核外的应用程序才能实现,所以要使用套接字(WinSock)来实现。TCP/IP协议核心与应用程序关系如下图所示。,14.1.3WinSock通信与C/S结构,WindowsSockets通信的基础是套接字(Socket)。与文件操作类似,当要读写一个文件时,必须用一个文件对象(文件指针或文件句柄)执行这个文件。而Socket就是在应用程序之间用来读(接收信息)或写(发送信息)的一个网络对象。WindowsSockets支持两种类型的套接字:流式套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)。流式套接字定义了一种可靠的面向连接的服务,实现了无差错无重复的顺序数据传输。数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠、无差错。,14.1.3WinSock通信与C/S结构,对于要求精确传输数据的WindowsSockets通信程序,一般采用流式套接字。采用流式套接字通信的一个最典型的应用就是客户机/服务器(C/S)模型,这也是在TCP/IP网络中,两个进程间的相互作用的主要模式。客户机/服务器模式在操作过程中采取的是主动请示方式,其具体工作流程如下图所示。,14.1.3WinSock通信与C/S结构,首先服务器方要先启动,并根据请示提供相应服务,具体过程如下:(1)打开一通信通道(Socket)并告知本地主机,它准备在某一个地址上接收客户的连接请求。(2)进入监听状态,等待客户请求到达该端口。(3)接收到客户服务请求,处理该请求并发送应答信号。(4)返回第二步,等待另一客户请求。(5)关闭服务器。,14.1.3WinSock通信与C/S结构,而客户方的工作过程如下:(1)打开一通信通道(Socket),并连接到服务器所在主机的特定端口。(2)向服务器发送服务请求报文,等待并接收应答,继续提出请求。(3)请求结束后关闭通信通道并终止。,14.1.4MFC中WinSock的封装类,当然,在VC6.0中,程序员可以直接使用WindowsSocketsAPI函数进行WinSock网络程序的开发。WindowsSocketsAPI是以BerkeleySocketsAPI为模型,提供了一个标准的API,Windows程序员可以使用它来编写网络应用程序。WindowsSocketsAPI函数共包括三大类:套接字函数、数据库函数和针对MicrosoftWindows的扩展函数。其具体使用本书不作详细介绍。MFC为套接字提供了封装类CAsyncSocket和CSocket,它们封装了WindowsSockets的API,从而程序员可以用面向对象的方法调用Socket。,14.1.4MFC中WinSock的封装类,CAsyncSocket类是在一个较低的层次上封装了WindowsSocketsAPI,它封装了异步、非阻塞Socket的基本功能,提供了Socket的基本操作,用它做常用的网络通信软件很方便。CSocket类由CAsyncSocket派生,是WindowsSocketsAPI的高层抽象,提供了更高层次的功能阻塞式的访问方式。有关函数的原型及使用,在下面将结合具体的实例开发来介绍。CSocket类新提供的主要成员函数及其功能如下表所示。,14.1.5WinSock网络编程的常用术语,对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手。许多概念,诸如同步(Sync)、异步(Async)、阻塞(Block)、非阻塞(Unblock)等,初学者往往迷惑不清,这里对一些常用术语作一下简单介绍。,1、套接字,套接字也就是前面多次提到的Socket,是可以被命名和寻址的通信端点,是网络的基本构件。实际上,套接字可以理解为在计算机中提供的一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输、接收的信息都通过这个Socket接口来实现的。使用中的每一个套接字都有其类型和一个与之相连的进程。WINDOWSSOCKET1.1版本支持两种类型的套接字:流套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)。,2、同步/异步,同步方式指的是发送方不
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 诗歌鉴赏|杜甫《将赴成都草堂途中有作先寄严郑公五首》注释+赏析+试题
- 国开学习网《软件设计与体系结构》形成性考核1-4答案
- 短视频制作合同履约金协议
- 绿色城市治理合同
- 基于环境感知和攻防博弈的容器集群风险分析
- 配件采购合同示例
- 智能供应链供应链咨询服务系统开发合同
- 硬件设备采购及安装服务合同
- 智能艺术创作服务系统开发合同
- 智能城市智能医疗系统开发合同
- 痛觉及其调制
- 七年级上册语文人教版全册文言文全文详解及翻译
- 北师大小学数学小升初《简便运算》复习课件
- 园艺植物种质资源图文
- 中央新疆税收政策解读
- “校园之星”评选实施方案
- 部编版二年级下册语文园地八(完美版)教学设计1
- 《安全生产法培训课件》(2021版)
- 库车中原石油化工有限公司11万吨年凝析油分离及轻烃芳构化项目环境影响评价报告书
- 石膏板吊顶施工方案
- WORD VBA编程 从零开始学VBA
评论
0/150
提交评论