当前位置:松语文学 > 其他类型 >VC++_6.0程序设计从入门到精通最新章节 > VC++_6.0程序设计从入门到精通TXT下载
错误举报

第 45 章

  本的文件对话框

  //这里将两类版本的文件对话框模板都进行设置

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·206·

  SetTemplate(IDD_MYFILEDIALOG,IDD_MYFILEDIALOG);

  }

  然后在ClassWizard 中为CMyFileDialog 添加IDC_DEL 控件的BN_CLICKED 处理函数

  OnDel(),代码如下:

  void CMyFileDialog::OnDel()

  {

  // TODO: Add your control notification handler code here

  // 提示用户是否删除文件

  if (MessageBox("确定删除文件?","提示",MB_OKCANCEL)!=IDOK)

  {

  //不删除文件则退出

  return;

  }

  CFile::Remove(GetPathNcom()); //删除选定的文件

  }

  3.使用重载的文件对话框

  创建好CMyFileDialog 就可以在程序中使用重载后的对话框,使用方法跟普通的文件对

  话框类似,代码如下:

  CMyFileDialog dlg; //创建CMyFileDialog 对象

  if (dlg.DoModal()==IDOK) //打开对话框

  {

  ?? //进行用户选定文件后的处理

  }

  这样就能打开如图8-4 所示的对话框,在选择文件打开的同时还可以通过单击“删除”

  按钮删除一个选定的文件,为文件对话框提供了附加的功能。

  本小节给出的例子稍加修改就可以添加更多更复杂的功能。同时CFileDialog 还提供了一

  些虚函数用于自定义处理文件对话框原有控件产生的消息,重载这些函数就可以为

  CFileDialog 原有的功能进行重新设计,从而大大提高文件对话框的灵活xìng。

  8.4 本章小结

  本章主要介绍了在MFC 中如何对文件进行读写cāo作和一些管理cāo作,主要内容包括以

  下几个方面:

  ? 在文档视图结构中对文档进行串行化;

  ? 用CFile 类和相关类对磁盘文件进行读写和管理;

  ? 文件对话框CFileDialog 的一些高级使用方法。

  总之,文件cāo作是应用程序保存和使用数据的基本方法。只有熟练使用本章中介绍的各

  种文件cāo作的类和函数才能在程序中体现出更大的灵活xìng。

  枫叶文学网www.fywxw.com

  第9 章 多线程

  本章主要介绍Windows cāo作系统下多线程的基本概念、创建管理线程的方法,以及线程

  的同步问题。Windows 提供了大量的线程同步技术,这些技术可以应用于不同的实际情况。

  同时,MFC 对线程cāo作进行了封装,提供了支持线程cāo作的类库。本章主要讨论这些技术,

  并且给出相应的实例。主要包括以下几个方面的内容:

  ? Windows 下多线程的基本概念;

  ? 用户界面线程和工作者线程;

  ? 线程的管理cāo作;

  ? 线程的同步;

  ? 多线程编程实例。

  9.1 多线程的基本概念

  在Win32 下,一个应用程序由一个或多个进程组成。一个进程由一个或多个线程以及代

  码、数据和其他内存中的程序资源组成。典型的程序资源包括打开的文件、信号量、动态分

  配的内存等。线程在进程空间中执行。

  线程是cāo作系统分配处理器时间的最小单位。每个线程有自己的堆栈,CPU 寄存器,以

  及程序入口。每个线程共享所有处理器的资源。

  进程中的每个线程都独立执行,不会影响该进程中的其他线程。所有线程共享公共的资

  源。因此必须采用信号量或者其他进程间通信方法来调整线程的工作。

  9.2 两种重要的线程

  Windows 提供了两种线程,用户界面线程和工作者线程。用户界面线程通常用来处理消

  息循环、与用户jiāo互,工作者线程用来处理后台的计算。下面分别介绍这两种线程。

  9.2.1 用户界面线程

  每一个Windows 应用程序都有一个主线程。这里的用户界面线程是指用来和用户进行jiāo

  互的线程。接收用户传送的数据,并且做出响应。用户界面线程通常包含自己的窗口,有自

  己的消息循环,独立于应用程序的其他部分。

  创建一个用户界面线程需要首先继承线程类CWinThread,重载它的成员函数,如表9-1

  所示。最后调用AfxBeginThread 创建线程对象。

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·208·

  表9-1 需要重载的CWinThread 的成员函数

  函数名称 作用

  InitInstance 线程的初始化,通常需要重载

  ExitInstance 释放线程占用的资源,通常需要重载

  OnIdle 空闲时间的处理,不一定重载

  PreTranslateMessage 过滤消息,不一定重载

  ProcessWndProcException 处理线程抛出的意外

  Run 线程控制函数,通常不重载

  9.2.2 工作者线程

  工作者线程通常用来处理后台运行的任务。在后台任务运行的同时,用户可进行其他cāo

  作,不必等待后台任务的结束。例如一个三维模型编辑软件,用户要对两个模型做布尔运算。

  在进行计算的同时,用户希望可以观察两个模型,对模型进行旋转,缩放的cāo作。再如文本

  浏览软件的打印功能,在打印文本的工程中,用户仍然会继续浏览文本内容。这些都属于工

  作者线程。

  创建一个工作者线程只需要两个步骤。首先实现工作者线程的功能函数,然后启动线程

  即可。可以调用Win32 提供的API 函数CreateThread 创建一个线程,MFC 对Win32 的线程

  cāo作做了封装,也可以通过调用AfxBeginThread 创建一个线程对象。这些函数及其调用方法

  将在下一节详细介绍。

  9.3 线程的cāo作

  本小节介绍Windows 线程的cāo作方法,包括线程的创建、线程的管理、线程的同步、线

  程的终止等。

  9.3.1 线程的创建

  线程的创建方法有3 种,分别介绍如下:

  1.调用Win32API 函数CreateThread 和CreateRemoteThread

  (1)CreateThread

  函数CreateThread 用来创建线程。如果调用成功则返回非0,否则返回0。它的函数原型

  如下:

  HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes,

  SIZE_T dwStackSize,

  LPTHREAD_START_ROUTINE lpStartAddress,

  LPVOID lpParcomter,

  DWORD dwCreationFlags,

  枫叶文学网www.fywxw.com

  第9 章 多线程

  ·209·

  LPDWORD lpThreadId

  );

  函数中主要参数的意义如下:

  ? lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,决定返回的句柄是否

  可以被继承。

  ? dwStackSize:设定堆栈的大小。

  ? lpStartAddress:线程函数的名称,它的参数是第4 个参数。

  ? lpParcomter:线程函数的参数。

  ? dwCreationFlags:线程创建标志。如果是CREATE_SUSPENDED,则线程的初始状态

  为挂起,直到调用了RescomThread 才开始执行,如果为0,线程创建后即开始执行。

  ? lpThreadId:存放线程标志的变量指针。

  (2)CreateRemoteThread

  函数CreateRemoteThread 用来创建在另外一个进程的虚拟空间中执行的线程,它的函数

  原型如下:

  HANDLE CreateRemoteThread(

  HANDLE hProcess,

  LPSECURITY_ATTRIBUTES lpThreadAttributes,

  SIZE_T dwStackSize,

  LPTHREAD_START_ROUTINE lpStartAddress,

  LPVOID lpParcomter,

  DWORD dwCreationFlags,

  LPDWORD lpThreadId

  );

  函数中主要参数的意义如下。

  ? hProcess:进程的句柄。

  ? lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,决定返回的句柄是否

  可以被继承。

  ? dwStackSize:设定堆栈的大小。

  ? lpStartAddress:线程函数的名称,它的参数是第四个参数。

  ? lpParcomter:线程函数的参数。

  ? dwCreationFlags:线程创建标志。如果是CREATE_SUSPENDED,则线程的初始状态

  为挂起,直到调用了RescomThread才开始执行。如果为0,线程创建后即开始执行。

  ? lpThreadId:存放线程标志的变量指针。

  2.C 运行库函数_beginthreadex

  _beginthreadex 和Win32API 函数CreateThread 非常类似。如果调用成功,返回新创建线

  程的句柄,否则返回-1。它们的参数几乎完全相同。函数原型如下:

  unsigned long _beginthread(

  void( __cdecl *start_address )( void * ),

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·210·

  unsigned stack_size,

  void *arglist

  );

  unsigned long _beginthreadex(

  void *security, unsigned stack_size,

  unsigned ( __stdcall *start_address )( void * ),

  void *arglist,

  unsigned initflag,

  unsigned *thrdaddr

  );

  函数中主要参数的意义如下。

  ? start_address:线程的入口地址。

  ? stack_size:初始堆栈大小。

  ? arglist:传给线程的参数。

  ? security:安全属xìng。

  ? initflag:线程创建标志。

  ? thrdaddr:存放线程标志的变量指针。

  3.调用函数AfxBeginThread

  MFC 对Win32 的线程cāo作做了封装,可以通过调用AfxBeginThread 创建一个线程对象,

  函数AfxBeginThread 有两种调用方式,函数原型如下:

  CWinThread* AfxBeginThread(

  AFX_THREADPROC pfnThreadProc,

  LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL,

  UINT nStackSize = 0,

  DWORD dwCreateFlags = 0,

  LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL

  );

  CWinThread* AfxBeginThread(

  CRuntcomClass* pThreadClass,

  int nPriority = THREAD_PRIORITY_NORMAL,

  UINT nStackSize = 0,

  DWORD dwCreateFlags = 0,

  LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL

  );

  函数中主要参数的意义如下。

  ? pfnThreadProc:指向工作者线程的控制函数指针,该参数不能为空,这个函数必须按

  如下方式声明:

  UINT MyControllingFunction( LPVOID pParam )

  ? PThreadClass:继承自CWinThread 的RUNTIME_CLASS对象。

  枫叶文学网www.fywxw.com

  第9 章 多线程

  ·211·

  ? PParam:传给线程函数的参数。

  ? nPriority:指定线程优先级。

  ? nStackSize:初始堆栈大小。

  ? dwCreateFlags:线程创建标志。

  ? lpSecurityAttrs:安全属xìng。

  如果线程创建失败,可以调用GetLastError 得到错误信息,该函数没有参数,返回值是

  调用线程的最后错误返回值。

  9.3.2 线程的终止

  1.调用Win32API 函数E

  松语文学免费小说阅读_www.16sy.com