MFC記住上次路徑---遇到的一些問題


    今天完成一個需求,就是記住用戶選擇的文件路徑,先是熟悉代碼,然后在網上找解決方法,一開始感覺沒什么,網上的方法差不多,應該很容易做出來,結果真是卡了一半天,到晚上自己才慢慢的搞清楚了。

遇到的問題真不少,記錄一下好多細節,真是不寫不知道。

2016-08-18 21:35:36補充:

MFC選擇文件夾的對話框

VC++------------MFC選擇文件夾和文件對話框

1.基本方法

http://blog.csdn.net/shuilan0066/article/details/7302904

http://www.cnblogs.com/Hisin/archive/2012/02/27/2370614.html

這兩篇是比較清楚的。

先認識了

SHBrowseForFolder打開文件夾時,每次都是從根目錄打開。要記住上次的路徑或者設置默認路徑,需要寫個回掉函數。

CFileDialog會自動記住上次路徑

int CALLBACK BrowseCallBackFun(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)  
{  
    switch(uMsg)  
    {  
    case BFFM_INITIALIZED:  //選擇文件夾對話框初始化  
     //設置默認路徑為lpData即'D:\'  
        ::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);  
        //在STATUSTEXT區域顯示當前路徑  
        ::SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, lpData);  
        //設置選擇文件夾對話框的標題  
        ::SetWindowText(hwnd, TEXT("請先設置個工作目錄"));   
        break;  
    case BFFM_SELCHANGED:   //選擇文件夾變更時  
        {  
            TCHAR pszPath[MAX_PATH];  
            //獲取當前選擇路徑  
            SHGetPathFromIDList((LPCITEMIDLIST)lParam, pszPath);  
            //在STATUSTEXT區域顯示當前路徑  
            ::SendMessage(hwnd, BFFM_SETSTATUSTEXT, TRUE, (LPARAM)pszPath);  
        }  
        break;  
    }  
    return 0;  
}  
  

回掉函數首先搞清楚參數的意義

2.SHBrowseForFolder函數

 

     打開文件目錄對話框,我找到的方法就是使用SHBrowseForFolder函數,這個函數的原型是LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO lpbi)。函數很簡單,就一個返回值和一個參數。參數簡單羅列如下

 

typedef struct _browseinfo {

 

     HWND hwndOwner;            // 父窗口句柄

 

     LPCITEMIDLIST pidlRoot;    // 要顯示的文件目錄對話框的根(Root)

 

     LPTSTR pszDisplayName;     // 保存被選取的文件夾路徑的緩沖區

 

     LPCTSTR lpszTitle;         // 顯示位於對話框左上部的標題

 

     UINT ulFlags;              // 指定對話框的外觀和功能的標志

 

     BFFCALLBACK lpfn;          // 處理事件的回調函數

 

     LPARAM lParam;             // 應用程序傳給回調函數的參數

 

     int iImage;                // 文件夾對話框的圖片索引

 

} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO

 

     一般而言父窗口句柄(hwndOwner)和根(pidlRoot)設置為Null就可以了,pszDisplayName設定一塊MAX_PATH大小的緩沖區,跟顯示相關的參數就是對話框提示標題(lpszTitle)、對話框樣式(ulFlags)、設定對話框的缺省路徑的操作(lpfn和lParam)以及對話框任務欄上顯示的圖標(iImage)。

 

     由於返回值LPITEMIDLIST是一個指向ITEMIDLIST的指針,這個ITEMIDLIST涉及到Windows Shell中關於管理諸如文件、網絡上的計算機、控制面板程序、回收站等等對象的知識點,Windows Shell為了識別具體的每一個對象,就使用了ITEMID來唯一識別和區分,而ITEMIDLIST就是一個完整的對象路徑。顯然這個函數可以用來瀏覽非文件對象,比如局域網內的電腦等等,在這里這個LPITEMIDLIST返回的對象路徑是一個文件夾的路徑,Windows提供了一個函數BOOL SHGetPathFromIDList(LPCITEMIDLIST pidl, LPSTR pszPath)來實現從對象路徑轉化為文件夾路徑。

弄清楚每個參數的意義,然后才能按需求設定初值。先太盲目了,只知道套別人的,根本就沒有理解。

                LPCITEMIDLIST pidl = NULL;
                BROWSEINFO bi;
                bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
                bi.pidlRoot = NULL;
                bi.pszDisplayName = folderName;
                bi.lpszTitle = _T("請選擇用於保存的文件夾");
                bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;;
                bi.lpfn = BrowseCallbackProc;    //回調函數  
                bi.iImage = 0;
                bi.lParam = long(&szPath);  //設置默認路徑,傳給回掉函數的參數

                pidl = SHBrowseForFolder(&bi);
                if (pidl)
                {        
                    SHGetPathFromIDList(pidl, szPath);
                 }

3.回掉函數

     先看別人說設置全局的靜態變量,然后設置靜態變量和靜態函數,開始編譯通不過,要搞清楚類里面怎么寫這種特殊的靜態變量和函數。

      靜態變量初始化,在cpp中,回掉函數的定義.h中static,cpp不需要了。

     感覺回掉函數只是發送了一些消息,根本就沒有什么其他的用處,然后有人用lpData設置初始化路徑,每次將選中的路徑賦值給IpData也可以完成功能。

 

4.記住路徑

     在軟件開啟的時候,設置全局變量,每個更新默認的路徑即可,但是重新開啟軟件的時候,采用先寫入注冊表中,然后再讀注冊表的路徑,這樣就解決了問題。也可以寫到ini文件中。

 

 

5.CString與TCHAR數組 相互轉換

 TCHAR數組轉到CString很簡單:使用CString的Format就行。

    TCHAR m_buf[100] = _T("Hello");

    CString str;

    str.Format(L"%s",m_buf);

     現在就來CString轉為TCHAR數組,這個就有點麻煩了。因為網上有很多的解決方案,但是都不怎么理想。我們使用_tcscpy()宏。

CString str = L"sssssss";

TCHAR m_buf[20];

_tcscpy(m_buf, str);  //類型之間的轉換真麻煩,知道定義這個宏的好處了。

自己找了半天,這個方法很有效!用memcpy,strcpy都不行。。。

TCHAR szDefaultDir[MAX_PATH];
                CString strDef(_T("E:\\"));
                memcpy(szDefaultDir, strDef.GetBuffer(strDef.GetLength() * 2), strDef.GetLength() * 2);
                strDef.ReleaseBuffer();
                szDefaultDir[strDef.GetLength()] = 0;

這樣也是一種方法吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM