• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 實現操作過程提示對話框

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    ---- 在使用Windows95 進行文件拷貝或者刪除操作時,您一定見到過那種具有飛 文件動畫的操作過程提示對話框。這一功能的加入不僅使我們能夠在操作過程當 中隨時取消操作,而且也使文件拷貝或者刪除操作變得生動活潑。其實,在使 用Visual C++ 進行應用程序設
    ---- 在使用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)。 

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>