使用VC++2013写出短小精悍的函数

以选择文件夹对话框为例,研究C++11新特性。

使用VC++2013写出短小精悍的函数

调用Windows API SHBrowseForFolder 可以打开该对话框,进行浏览和选择对话框。调用该接口之前,需要构造一个结构体BROWSEINFO 。参考下面的函数:

  1. // hParent,父窗口; strFolder,返回选择的文件夹路径。  
  2. BOOL WINAPI SelectFolder(HWND hParent, CString &strFolder)  
  3. {  
  4.     BOOL bRet = FALSE;  
  5.     LPMALLOC lpMalloc;  
  6.     if (::SHGetMalloc(&lpMalloc) != NOERROR)  
  7.     {  
  8.         return FALSE;  
  9.     }  
  10.   
  11.     TCHAR szDisplayName[_MAX_PATH];  
  12.     TCHAR szBuffer[_MAX_PATH];  
  13.     BROWSEINFO browseInfo;  
  14.     browseInfo.hwndOwner = hParent;  
  15.     browseInfo.pidlRoot = NULL;  
  16.     browseInfo.pszDisplayName = szDisplayName;  
  17.     browseInfo.lpszTitle = _T("请选择一个文件夹:\nPlease select a folder:");  
  18.     browseInfo.ulFlags = BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS;  
  19.     browseInfo.lpfn = NULL;  
  20.     browseInfo.lParam = NULL;  
  21.   
  22.     LPITEMIDLIST lpItemIDList;  
  23.     if ((lpItemIDList = ::SHBrowseForFolder(&browseInfo)) != NULL)  
  24.     {  
  25.         if (::SHGetPathFromIDList(lpItemIDList, szBuffer))  
  26.         {  
  27.             if (szBuffer[0] != ‘\0‘)  
  28.             {  
  29.                 strFolder = szBuffer;  
  30.                 bRet = TRUE;  
  31.             }  
  32.         }  
  33.         lpMalloc->Free(lpItemIDList);  
  34.         lpMalloc->Release();  
  35.     }  
  36.     return bRet;  
  37. }   

但是,这样没有“新建文件夹”的按钮,也没有选择文件夹的编辑框显示,如下图。

使用VC++2013写出短小精悍的函数


如果需要新建文件夹的按钮,需要给BROWSEINFO的表示位ulFlags添加一个标志BIF_USENEWUI 。这个标志在VC6.0没有给出,可以自己定义:

#ifndef BIF_USENEWUI
#define BIF_NEWDIALOGSTYLE      0x00000040  // Use the new dialog layout with the ability to resize
#define BIF_USENEWUI            (BIF_NEWDIALOGSTYLE | BIF_EDITBOX)  // Caller needs to call OleInitialize() before using this API
#endif

然后把上面函数稍加修改,    browseInfo.ulFlags = BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS|BIF_USENEWUI;  这样就有了“新建文件夹”按钮了。

但是,这样仍不完美。因为每次打开该对话框时,都是默认选择同样的目录,想要找到自己想要的目的文件夹就要多次点击鼠标才行。如果能够指定一个默认选择的文件夹就好了。而幸运的是,Windows提供了这样的接口。但需要通过回调的方式实现,如下:

  1. int CALLBACK BrowserCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)    
  2. {    
  3.     switch(uMsg)    
  4.     {    
  5.     case BFFM_INITIALIZED: //设置默认选择的文件夹    
  6.         ::SendMessage(hWnd, BFFM_SETSELECTION, 1, lpData);    
  7.         break;    
  8.     default:    
  9.         break;    
  10.     }    
  11.     return 0;    
  12. }    
  13. // hParent,父窗口; strFolder,输入默认选择的文件夹路径,返回新选择的文件夹路径。   
  14. BOOL WINAPI SelFolder(HWND hParent, CString &strFolder)  
  15. {  
  16.     BOOL bRet = FALSE;  
  17.     LPMALLOC lpMalloc;  
  18.     if (::SHGetMalloc(&lpMalloc) != NOERROR)  
  19.     {  
  20.         return FALSE;  
  21.     }  
  22.   
  23.     TCHAR szDisplayName[_MAX_PATH];  
  24.     TCHAR szBuffer[_MAX_PATH];  
  25.     BROWSEINFO browseInfo;  
  26.     browseInfo.hwndOwner = hParent;  
  27.     browseInfo.pidlRoot = NULL;  
  28.     browseInfo.pszDisplayName = szDisplayName;  
  29.     browseInfo.lpszTitle = _T("请选择一个文件夹:\n\nPlease select a folder:");  
  30.     browseInfo.ulFlags = BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS|BIF_USENEWUI;  
  31.     browseInfo.lpfn = BrowserCallbackProc;  
  32.     browseInfo.lParam = (LPARAM)(const char*)strFolder;  
  33.   
  34.     LPITEMIDLIST lpItemIDList;  
  35.     if ((lpItemIDList = ::SHBrowseForFolder(&browseInfo)) != NULL)  
  36.     {  
  37.         if (::SHGetPathFromIDList(lpItemIDList, szBuffer))  
  38.         {  
  39.             if (szBuffer[0] != ‘\0‘)  
  40.             {  
  41.                 strFolder = szBuffer;  
  42.                 bRet = TRUE;  
  43.             }  
  44.         }  
  45.         lpMalloc->Free(lpItemIDList);  
  46.         lpMalloc->Release();  
  47.     }  
  48.     return bRet;  
  49. }   

这样就能达到想要的效果。

但是仍不完美,一个功能本来应该一个函数就实现的,却写了两个函数,看起来真是膈应。复制的时候,仅复制下面的函数是用不了的,程序的可读性、可移植性都大打折扣。如果能写在同一个函数中,再精简一下就完美了。VC6.0是不行了,VS2010也力不从心。

而VS2013用几个C++11的新特性就能轻松是实现:

使用VC++2013写出短小精悍的函数


使用VC++2013写出短小精悍的函数,布布扣,bubuko.com

使用VC++2013写出短小精悍的函数

上一篇:初识spring boot maven管理--属性文件配置


下一篇:paip.输入法编程---词库多意义条目分割 python实现.