在使用Windows 95進行文件拷貝或刪除操作時,用戶一定見到過那種具有飛行文件動畫的操作過程提示對話框。這一功能的加入不僅使我們能夠在操作過程中隨時取消操作,而且也使文件拷貝或刪除操作變得生動活潑。其實,在使用Visual C++進行應用程序設計時,我們也可以使用下述方法在適當位置加入自己的操作過程提示對話框,步驟如下。
1. 為每一個操作過程提示對話框創建一個對話框類。為敘述方便,我們只假設應用程序需要一個操作過程提示對話框並以“CModel”作為對應的對話框類的名字。
2. 使用Visual C++提供的資源編輯器編輯提示對話框,比如加入一些文字說明和動畫等。
3. 在CModel類的頭文件(Model.h)中,首先加入兩個成員變量:
CWnd* m_pParent;
//指向調用該提示對話框的框架類(或對話框類), 即它的“父類”
int m_nID;//記錄該提示對話框的ID號
其次再加入下面兩個成員函數:
CModel(CWnd* pParent = NULL);
//捨棄原有的構造函數,或者把原函數修改成這種 無模式對話框的構造函數
BOOL Create();
//該函數將調用創建基類的Create()函數創建對話 框
4. 在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);
}
5. 同時按下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();
}
6. 在要調用提示對話框類的頭文件中,先包含(#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等,並以進程的形式調用它,再在適當時候關閉它。下面將以此為例,具體介紹後一種方法的實現過程。
1. 在需要調用ARJ.EXE進行壓縮/解壓縮的類中,創建一個成員函數,不妨稱作CreateBat(),其作用是生成一個批處理文件。由該批處理文件調用ARJ.EXE,並給出具體壓縮/解壓縮參數。然後,利用MS-DOS的DIR命令生成一個臨時文件,以作為壓縮/解壓縮工作完成的標志。
編者注:Createbat源代碼發表http://www.computerworld.com.cn/98/skill/default.htm。下同。歡迎訪問!
該函數執行後,將生成一個批處理文件,內容大致是:
ARJ A -V1440 壓縮後文件的路徑名+文件名 被壓縮文件的路徑名+文件名 -Y -JM
DIR >臨時文件名
或者是:
ARJ E -V1440 被解壓縮文件的路徑名+文件名 解壓縮後文件的路徑名+文件名 -Y -JM
DIR >臨時文件名
2. 在需要調用ARJ.EXE進行壓縮/解壓縮的類中,再創建一個成員函數,不妨稱作RunBat(),其作用是創建和執行進程來運行上述所生成的批處理文件,並在適當時候撤消進程。
3. 同時按下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();
}
}
得到並修改各驅動器信息
在設計與文件輸入/輸出有關的應用程序時,我們需要在輸入/輸出文件前,了解一下源驅動器或者目標驅動器的各項信息,比如是否有磁盤在軟驅中、它是否已打開寫保護、現有磁盤的容量等。遺憾的是,MFC類庫中沒有提供支持這些功能的類,所以我們只能通過Win32 提供的函數來完成我們的要求。下面,筆者根據自己的編程實踐,通過幾段程序,來說明如何利用Win32提供的函數實現對驅動器的操作。讀者可以根據自己的需要,把介紹的函數稍加修改後,即可插入到自己設計的應用程序中去。
*S FindDriverInfo()函數的功能是搜索計算機中所有驅動器,選擇出其中軟盤驅動器的驅動器號,依次加入到一個下拉列表框中。
*S EmptyDiskSpace()函數主要負責清空指定驅動器中的磁盤,同時它還負責記錄指定驅動器中磁盤的容量,並得到該磁盤的序列號。在該函數中,還將調用上文中的DeletTree()的PreRemoveDirectory()函數,來完成清空工作。
*S 在MS-DOS和Windows95中,磁盤卷標最多由11個字符組成,並且字母的大小寫不加區分。當需要設定指定驅動器中磁盤的卷標時,只要調用Win32的SetVolumeLabel()函數即可,在第一個參數中指明磁盤所在的驅動器號,在第二個參數中指明新的卷標號,例如:SetVolumeLabel(DriverNum, NewVolumeLabel)。
自編刪除目錄及其下屬文件的函數
高版本的MS-DOS和Windows 95都提供了一個可以刪除一個或多個目錄及其下屬文件和目錄的命令,即DeleteTree命令。然而,無論在MFC類庫還是在Win32函數庫中,都沒有相應的函數。這樣,當我們在自己設計的應用程序中需要用到DeleteTree的功能時,自然想到的方法是通過進程調用或者系統調用的方式(如上文所述)調用MD-DOS或Windows 95下的DeleteTree命令。但實際上,Win32函數庫已經為我們提供了其它的用於文件和目錄操作的函數,利用它們不難設計出自己的DeleteTree()函數。
讀者也許會感到有些疑惑,為什麼前文強調進程調用優於自我設計的函數,而這裡又反了過來?是的,在通常情況下,調用應用程序內部的函數比使用進程或者調用外部函數更靈活並且可以提高執行效率,也便於修改,DeleteTree()就是這種情況。然而,像設計壓縮/解壓縮這樣的函數工作量大、算法復雜,而且調試和維護也需要一定代價,於是這時候還是采用“拿來主義”為好。
本文給出筆者設計的DeleteTree()函數,僅供參考。