<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      完成設置過程提示對話框

      [摘要]---- 在使用Windows95 進行文件拷貝或者刪除操作時,您一定見到過那種具有飛 文件動畫的操作過程提示對話框。這一功能的加入不僅使我們能夠在操作過程當 中隨時取消操作,而且也使文件拷貝或者刪...
      ---- 在使用Windows95 進行文件拷貝或者刪除操作時,您一定見到過那種具有飛
      文件動畫的操作過程提示對話框。這一功能的加入不僅使我們能夠在操作過程當
      中隨時取消操作,而且也使文件拷貝或者刪除操作變得生動活潑。其實,在使
      用Visual C++ 進行應用程序設計時,我們也可以使用下述方法在適當位置加入自
      己的操作過程提示對話框。
      為每一個操作過程提示對話框創建一個對話框類。為了下面敘述方便,我們
      只假設應用程序需要一個操作過程提示對話框并以“CModel”作為對應的對
      話框類的名字。

      使用Visual C++ 提供的資源編輯器編輯提示對話框,比如加入一些文字說明
      和動畫等。

      在CModel 類的頭文件(Model.h) 中,加入兩個成員變量,
      CWnd* m_pParent; // 指向調用該提示對話框的框架類( 或對話框類),即它
      的“父類”int m_nID;// 記錄該提示對話框的ID 號
      以及下面兩個成員函數:
      CModel(CWnd* pParent = NULL); // 舍棄原有的構造函數,或者把原函數
      修改成這種無模式對話框的構造函數
      BOOL Create(); // 該函數將調用創建基類的Create() 函數創建對話框
      在Model.cpp 文件中,加入相應函數的實現部分。
      CModel::CModel(CWnd* pParent /*=NULL*/)
      : CDialog(CModel::IDD, pParent)
      {
      m_pParent=pParent;
      m_nID=CModel::IDD;
      //{{AFX_DATA_INIT(CModel)
      // NOTE: the ClassWizard will add member initialization here
      //}}AFX_DATA_INIT
      }

      BOOL CModel::Create()
      {
      return CDialog::Create(m_nID,m_pParent);
      }
      同時按下Ctrl 和W 鍵或直接單擊工具條上的ClassWizard 按鈕,打
      開ClassWizard 對話框。在類名(Class name) 列表框中選擇該提示對話框類,
      在Object IDs 列表框中選擇該類的類名后,在消息(Messages) 列表框中選
      擇PostNcDestroy 消息并雙擊它,這時ClassWizard 就會在該對話框類中加入
      一個PostNcDestroy() 函數。該函數將會在對話框窗口消失后,
      由OnNcDestroy() 函數調用。因此,可以在該函數中加入一些掃尾工作,例如
      數據傳送,釋放指針空間等。
      void CModel::PostNcDestroy()
      {
      // TODO: Add your specialized code here and/or call the base class
      delete this;
      CDialog::PostNcDestroy();
      }
      在要調用提示對話框類的類的頭文件中,先包含(#include)CModel 類的頭文
      件,再聲明一個指向CModel 類的對象的指針,如m_Dlg,并在該類的構造函數
      中,加入“m_Dlg = NULL;”一句。然后,在打開和關閉提示對話框的函數中加
      入如下一段程序:
      if (m_Dlg==NULL) {//如果當前沒用提示對話框在活動,就創建一個
      m_Dlg = new CModel(this);
      m_Dlg->Create();
      GetDlgItem(IDC_EXPORT)->EnableWindow(FALSE);
      }
      else//否則就激活它
      m_Dlg->SetActiveWindow();
      另外,再在要關閉提示對話框的地方,加入如下語句:
      m_Dlg->DestroyWindow();
      m_Dlg=NULL;
      ---- 至此,您已經擁有了自己的過程操作提示對話框。不過,它還不具有動畫和
      隨時取消操作的功能。您不妨嘗試著加入這些功能。另外,筆者也曾嘗試過用下面
      介紹的方法實現過程操作提示對話框。兩種方法比較,可謂各有千秋。如果您希望
      上面設計的過程提示對話框能夠被多個應用程序共享,那么最好把提示對話框作
      為獨立的進程來調用。但是,當您還希望在提示對話框與調用者之間傳輸數據的
      話,似乎這一部分介紹的實現方法更簡潔且更有效。
      應用進程實現對其他應用程序的調用
      ---- 在我們設計的應用程序中,很可能會用到其他應用程序來完成某一特定功
      能。例如,當我們為了便于數據的傳輸而對諸多文件進行壓縮和解壓縮時,一種作
      法是我們自己設計一個這樣的壓縮/ 解壓縮程序,然后以動態鏈接庫(DLL) 或者函
      數庫的形式由主應用程序調用。但更方便而且高效的作法是利用現有的這方面的
      優秀軟件,比如ARJ.EXE,并以進程的形式調用它,再在適當時候關閉它。下面將以
      上面所述為例,具體介紹后一種方法的實現過程。
      在需要調用ARJ.EXE 進行壓縮/ 解壓縮的類中,創建一個成員函數,不妨稱
      作CreateBat(),其作用是生成一個批處理文件。由該批處理文件調
      用ARJ.EXE,并給出具體壓縮/ 解壓縮參數。之后,再利用MS-DOS 的DIR 命令生
      成一個臨時文件,以作為壓縮/ 解壓縮工作完成的標志。
      void CMyCompress:: CreateBat(CString BatPath,CString ArjPath,
      CString BatName,CString ArjFileName,
      CString TempPath,CString ExitFlag,BOOL out)
      {
      LPTSTR lpBuffer;
      UINT uSize;
      HANDLE hHeap;
      uSize=(GetCurrentDirectory(0,NULL))*sizeof(TCHAR);
      hHeap=GetProcessHeap();
      lpBuffer=(LPSTR)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,uSize);
      GetCurrentDirectory(uSize,lpBuffer);
      //得知當前目錄信息,以便根據需要變換目錄
      if (lpBuffer!=BatPath) //diferent dir
      SetCurrentDirectory(BatPath);
      CStdioFile f;
      CFileException e;
      if (!f.Open( BatName, CFile::modeCreate CFile::modeWrite, &e))
      //以BatName的內容創建一個批處理文件
      {
      AfxMessageBox("不能創建文件"+BatName);
      return ;
      }
      char density[6];
      sprintf(density,"%d",mTotalBytes);
      ---- //mTotalBytes 是由其他函數設定的變量,用于記錄用于拷入或拷出文件
      的磁盤所具有的最大可用空間
      CString Density=density;
      CString string;
      if (out)//說明是生成做壓縮工作的批處理文件
      string="arj a -v"+Density;
      else //說明是生成做解壓縮工作的批處理文件
      string="arj e -v"+Density;

      string+=" ..\\"+ArjPath+"\\"+ArjFileName+" ";
      if (out)
      string=string+"..\\"+TempPath+"\\*.* -y -jm\n";
      else
      string=string+"..\\"+TempPath+"\\ -y -jm\n";

      f.WriteString(string);
      string="dir >"+ExitFlag+"\n";
      f.WriteString(string);
      f.Close();
      SetCurrentDirectory(lpBuffer);//回復到原來的目錄下
      }
      ---- 該函數執行后,將生成一個批處理文件,內容大致是:
      ---- ARJ A -V1440 壓縮后文件的路徑名+ 文件名被壓縮文件的路徑名+ 文件名
      -Y -JM
      ---- DIR > 臨時文件名
      ---- 或者是:
      ---- ARJ E -V1440 被解壓縮文件的路徑名+ 文件名解壓縮后文件的路徑名+ 文
      件名-Y -JM
      ---- DIR > 臨時文件名
      在需要調用ARJ.EXE 進行壓縮/ 解壓縮的類中,再創建一個成員函數,不妨稱
      作RunBat(),其作用是創建和執行進程來運行上述所生成的批處理文件,并
      在適當時候撤消進程。
      void CMyCompress::RunBat(CString
      BatPath,CString fileName,CString ExitFlag)
      {
      CString lpApplicationName=BatPath+"\\"+fileName;
      // 進程執行的應用程序的完全路徑名
      STARTUPINFO StartupInfo;// 創建進程所需的信息結構變量
      GetStartupInfo(&StartupInfo);
      StartupInfo.lpReserved=NULL;
      StartupInfo.lpDesktop=NULL;
      StartupInfo.lpTitle=NULL;
      StartupInfo.dwX=0;
      StartupInfo.dwY=0;
      StartupInfo.dwXSize=200;
      StartupInfo.dwYSize=300;
      StartupInfo.dwXCountChars=500;
      StartupInfo.dwYCountChars=500;
      StartupInfo.dwFlags=STARTF_USESHOWWINDOW;
      StartupInfo.wShowWindow=SW_HIDE;
      // 說明進程將以隱藏的方式在后臺執行
      StartupInfo.cbReserved2=0;
      StartupInfo.lpReserved2=NULL;
      StartupInfo.hStdInput=stdin;
      StartupInfo.hStdOutput=stdout;
      StartupInfo.hStdError=stderr;
      LPTSTR lpBuffer;
      UINT uSize;
      HANDLE hHeap;

      uSize=(GetCurrentDirectory(0,NULL))*sizeof(TCHAR);
      hHeap=GetProcessHeap();
      lpBuffer=(LPSTR)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,uSize);

      GetCurrentDirectory(uSize,lpBuffer);
      // 得知當前目錄信息,以便根據需要變換目錄
      if (lpBuffer!=BatPath) //diferent dir
      SetCurrentDirectory(BatPath);
      // 創建進程
      if (CreateProcess(lpApplicationName,NULL,NULL,
      NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,
      NULL,NULL,&StartupInfo,&pro_info))
      {
      MSG Message;
      DeleteFile(ExitFlag);
      SetTimer(1,100,NULL);// 設置計時器
      Search=TRUE;
      while(Search) {
      if (::PeekMessage(&Message,NULL,0,0,PM_REMOVE)) {
      ::TranslateMessage(&Message);
      ::DispatchMessage(&Message);
      }
      }
      // 進程結束前后的處理工作
      DWORDExitCode;
      if (!GetExitCodeProcess(pro_info.hProcess,&ExitCode))
      AfxMessageBox("GetExitCodeProcess is Failed!");
      if (!TerminateProcess(pro_info.hProcess,(UINT)ExitCode))
      // 終止進程
      AfxMessageBox("TerminateProcess is Failed!");
      if (!CloseHandle(pro_info.hProcess))
      // 釋放被終止進程的句柄
      AfxMessageBox("CloseHandle is Failed!");
      KillTimer(1);// 撤消計時器
      }
      else AfxMessageBox("Process Is Not Created!");
      SetCurrentDirectory(lpBuffer);// 回復到原來的目錄下
      }
      同時按下Ctrl 和W 鍵或直接單擊工具條上的ClassWizard 按鈕,打
      開ClassWizard 對話框。在類名(Class name) 列表框中選擇需要調用ARJ.EXE
      進行壓縮/ 解壓縮的類,在Object IDs 列表框中選擇該類的類名后,在消
      息(Messages) 列表框中選擇WM_TIMER 消息并雙擊它,這時ClassWizard 就會
      在該類中加入一個OnTimer() 函數。該函數將以一定的時間間隔檢查壓縮/ 解
      壓縮程序是否已經執行完畢,即檢查作為標志的臨時文件是否已經存在,并
      及時修改狀態變量“Search”,以便通知RunBat() 函數結束進程。
      void CMyCompress::OnTimer(UINT nIDEvent)
      {
      // TODO: Add your message handler code here and/or call default
      CFile file;
      CFileException Error;
      if (file.Open(ExitFlag,CFile::modeRead,&Error)) {
      Search=FALSE;
      file.Close();
      }
      }
      自編刪除目錄及其下屬文件的函數
      ---- 高版本的MS-DOS 和Windows 95 都提供了一個可以刪除一個或多個目錄及其
      下屬文件和目錄的命令,即DeleteTree 命令。然而,無論在MFC 類庫還是在Win32 函
      數庫中,都沒有相應的函數與之對應。這樣,當我們在自己設計的應用程序中需要
      用到DeleteTree 的功能時,自然想到的方法是通過進程調用或者系統調用的方
      式( 正如上面部分所述的那樣) 調用MD-DOS 或Windows 95 下的DeleteTree 命令。然
      而,Win32 函數庫已經為我們提供了多種用于文件和目錄操作的函數,利用它們不
      難設計出自己的DeleteTree() 函數。
      ---- 讀者讀到這里,也許會感到有些疑惑,為什么第六部分強調進程調用優于自
      我設計的函數,而這一部分又反了過來?是的,在通常情況下,調用應用程序內部
      的函數比使用進程或者調用外部函數更靈活并且可以提高執行效率,也便于修
      改。所以,象DeleteTree() 這樣的功能,利用現有的函數并不難實現,自然就最好
      通過內部函數的方式來完成。然而,象設計一個壓縮/ 解壓縮這樣的函數的工作
      量,并不比通過進程調用來使用現成品的開銷更合算,因為它至少需要我們了解
      壓縮/ 解壓縮的復雜算法,而且調試和維護它也需要一定代價。于是,這個時候,還
      是采用“拿來主義”為好。
      ---- 下面,給出我自己設計的DeleteTree() 函數,僅供參考。
      BOOL DeleteTree(CString DirName)
      { //成功:返回TRUE;否則,返回FALSE
      BOOL Result;
      Result=PreRemoveDirectory(DirName)
      && RemoveDirectory(DirName);
      return Result;
      }
      BOOL PreRemoveDirectory(CString DirName)
      {//成功:返回TRUE;否則,返回FALSE
      LPTSTR lpBuffer;
      UINT uSize;
      CString fileName;
      HANDLE hHeap;
      BOOL result;
      HANDLE hFindFile;
      WIN32_FIND_DATA FindFileData;
      uSize=(GetCurrentDirectory(0,NULL))*sizeof(TCHAR);
      hHeap=GetProcessHeap();
      lpBuffer=(LPSTR)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,uSize);
      GetCurrentDirectory(uSize,lpBuffer);
      if (lpBuffer!=DirName) {//調整當前目錄
      SetCurrentDirectory(DirName);
      }
      hFindFile=FindFirstFile("*.*",&FindFileData);
      CString tFile;
      if (hFindFile!=INVALID_HANDLE_VALUE) {
      do {
      tFile=FindFileData.cFileName;
      if ((tFile==".") (tFile=="..")) continue;
      if (FindFileData.dwFileAttributes==
      FILE_ATTRIBUTE_DIRECTORY){
      if (DirName[DirName.GetLength()-1]!='\\')
      PreRemoveDirectory(DirName+'\\'+tFile);
      else
      PreRemoveDirectory(DirName+tFile);
      if (!RemoveDirectory(tFile))
      result=FALSE;
      else
      result=TRUE;
      }
      else
      if (!DeleteFile(tFile)) result=FALSE;
      else result=TRUE;
      }
      while (FindNextFile(hFindFile,&FindFileData));
      FindClose(hFindFile);
      }
      else {
      SetCurrentDirectory(lpBuffer);
      return FALSE;
      }
      SetCurrentDirectory(lpBuffer); //回復到原來的目錄下
      return result;
      }
      如何得到并修改各驅動器的信息
      ---- 在設計和文件輸入/ 輸出有關的應用程序時,我們很可能在輸入/ 輸出文件
      前,需要了解一下源驅動器或者目標驅動器的各項信息,比如是否有磁盤在軟驅
      中,它是否已打開寫保護,以及現有磁盤的容量等。遺憾的是,MFC 類庫中沒有提供
      支持這些功能的類,所以我們只能通過Win32 提供的函數來完成我們的要求。下
      面,我根據自己的編程實踐,通過幾段程序,來說明如何利用Win32 提供的函數實
      現對驅動器的操作。讀者可以根據自己的需要,把介紹的函數稍加修改后,即可插
      入到自己設計的應用程序中去。
      下面程序的功能是搜索計算機中所有驅動器,選擇出其中軟盤驅動器的驅動
      器號,依次加入到一個下拉列表框中。
      void FindDriverInfo()
      {
      CComboBox* Driver=(CComboBox*)GetDlgItem(IDC_DRIVER);
      DWORD dwNumBytesForDriveStrings;
      HANDLE hHeap;
      LPSTR lp;
      CString strLogdrive;
      int nNumDrives=0, nDriveNum;
      dwNumBytesForDriveStrings=GetLogicalDriveStrings(0,NULL)
      *sizeof(TCHAR);//實際存儲驅動器號的字符串長度
      if (dwNumBytesForDriveStrings!=0) {
      hHeap=GetProcessHeap();
      lp=(LPSTR)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,
      dwNumBytesForDriveStrings);//
      GetLogicalDriveStrings(HeapSize(hHeap,0,lp),lp);
      StringBox.SetSize(dwNumBytesForDriveStrings/sizeof(TCHAR)+1);
      while (*lp!=0) {
      if (GetDriveType(lp)==DRIVE_REMOVABLE){
      Driver->AddString(lp);
      StringBox[nNumDrives]=lp;
      nNumDrives++;
      }
      lp=_tcschr(lp,0)+1;
      }
      }
      else AfxMessageBox("Can't Use The Function GetLogicalDriveStrings!");
      }
      下面介紹的EmptyDiskSpace() 函數主要負責清空指定驅動器中的磁盤,同時
      它還負責記錄指定驅動器中磁盤的容量,并得到該磁盤的序列號。在該函數
      中,還將調用第七部分提到的PreRemoveDirectory() 函數,來完成清空工作。

      BOOL EmptyDiskSpace(CString Driver)
      {
      BOOL result=TRUE;
      DWORDSectorsPerCluster; // address of sectors per cluster
      DWORDBytesPerSector; // address of bytes per sector
      DWORDNumberOfFreeClusters; // address of number of free clusters
      DWORDTotalNumberOfClusters;
      DWORDTotalBytes;
      DWORDFreeBytes;
      int bContinue=1;
      char DiskVolumeSerialNumber[30];
      //存儲驅動器內當前磁盤的序列號
      LPCTSTRlpRootPathName;
      // address of root directory of the file system
      LPTSTRlpVolumeNameBuffer=new char[12];
      // address of name of the volume
      DWORDnVolumeNameSize=12;
      // length of lpVolumeNameBuffer
      DWORD VolumeSerialNumber;
      // address of volume serial number
      DWORD MaximumComponentLength;
      // address of system's maximum filename length
      DWORD FileSystemFlags;
      // address of file system flags
      LPTSTRlpFileSystemNameBuffer=new char[10];
      // address of name of file system
      DWORDnFileSystemNameSize=10;
      // length of lpFileSystemNameBuffer
      lpRootPathName=Driver;
      while (1){
      if (GetDiskFreeSpace(Driver, &SectorsPerCluster,
      &BytesPerSector, &NumberOfFreeClusters,
      &TotalNumberOfClusters))
      {//驅動器中有磁盤
      TotalBytes=SectorsPerCluster*BytesPerSector
      *TotalNumberOfClusters;//磁盤總容量
      FreeBytes=SectorsPerCluster*BytesPerSector
      *NumberOfFreeClusters;//磁盤空閑空間容量
      GetVolumeInformation(lpRootPathName,
      lpVolumeNameBuffer, nVolumeNameSize,
      &VolumeSerialNumber,
      &MaximumComponentLength,
      &FileSystemFlags,
      lpFileSystemNameBuffer, nFileSystemNameSize);
      sprintf(DiskVolumeSerialNumber,"%X",VolumeSerialNumber);
      //得到驅動器內當前磁盤的序列號
      SetmTotalBytes(TotalBytes/1024);//存儲指定驅動器中磁盤的容量
      if (TotalBytes!=FreeBytes){//當磁盤總容量不等于空閑空間容量時,
      應該執行清空操作
      while (bContinue) {
      if ((bContinue==2) (MessageBox
      ("在驅動器"+m_Driver+"中的磁盤尚存有數據.
      \n您愿意讓系統為您刪除它們嗎?",
      "提問",MB_YESNO MB_ICONQUESTION)==IDYES))
      if (!PreRemoveDirectory(Driver))//無法執行清空操作
      if (MessageBox("因某種原因系統無法刪除
      在驅動器"+m_Driver+"中的磁盤上的數據.
      \n請檢查磁盤是否沒有關閉寫保護.
      \n您愿意再試一次嗎?",
      "問題",MB_YESNO MB_ICONERROR)==IDYES) {
      bContinue=2;
      continue;
      }
      else {
      bContinue=0;
      result=FALSE;
      }
      else {
      MessageBox("成功刪除磁盤上的數據!",
      "提示信息",MB_OK MB_ICONINFORMATION);
      bContinue=0;
      result=TRUE;
      }
      else {//THE FIRST IF'S ELSE
      bContinue=0;
      result=FALSE;
      }
      }
      }
      else result=TRUE;
      break;
      }
      else {
      if (MessageBox("沒有磁盤在驅動器"+m_Driver+"中.
      \n您愿意插入一張磁盤再來一次嗎?",
      "問題",MB_YESNO MB_ICONASTERISK)==IDYES) continue;
      else break;
      }
      }//END OF WHILE
      return result;
      }
      在MS-DOS 和Windows95 中,磁盤卷標最多由11 個字符組成,并且字母的大小寫
      不加區分。當需要設定指定驅動器中磁盤的卷標時,只要調用Win32
      的SetVolumeLabel() 函數即可,并在第一個參數中指明磁盤所在的驅動器
      號,在第二個參數中指明新的卷標號。例如,SetVolumeLabel(DriverNum,
      NewVolumeLabel)。 


      日韩精品一区二区三区高清