cout << "Hello World!" << endl; // 张鲁夺 :: 个人博客,幸福着你的幸福!


在GetOpenFileName函数多选文件过程中,动态分配文件名缓冲区大小

作者:鲁夺,2015年9月28日,原创文章,转载请注明出处!

原文:http://zhangluduo.com/article/fb6113f2/



0001 void UnicodeToAnsi(/* _IN */WCHAR* text, /* _OUT */CHAR** out)
0002 {
0003     *out = NULL;
0004 
0005     int len = WideCharToMultiByte(CP_ACP, 0, text, -1, NULL, NULL, NULL, NULL);
0006     if (len > 0) 
0007     {
0008         CHAR* buffer = new CHAR[len + 1];
0009         memset(buffer, 0, len + 1);
0010         WideCharToMultiByte(CP_ACP, 0, text, -1, buffer, len, NULL, NULL);
0011 
0012         *out = buffer;
0013     }
0014 }
0015 
0016 void UnicodeToAnsi_Release(/* _IN */CHAR** out)
0017 {
0018     if (*out)
0019     {
0020         delete (*out);
0021         (*out) = NULL;
0022     }
0023 }
0024 
0025 void AnsiToUnicode(/* _IN*/ CHAR* text, /* _OUT */WCHAR** out)
0026 {
0027     *out = NULL;
0028 
0029     int len = MultiByteToWideChar(CP_ACP, 0, text, -1, NULL, NULL);
0030     if (len > 0)
0031     {
0032         WCHAR *buffer = new WCHAR[len + 1];
0033         memset(buffer, 0, (len + 1 )* sizeof(WCHAR));
0034         MultiByteToWideChar(CP_ACP, 0, text, -1, buffer, len);
0035 
0036         (*out) = buffer;
0037     }
0038 }
0039 
0040 void AnsiToUnicode_Release(/* _IN */WCHAR** out)
0041 {
0042     if (*out)
0043     {
0044         delete (*out);
0045         (*out) = NULL;
0046     }
0047 }
0048 
0049 //    Article ID: 131462
0050 //    http://support.microsoft.com/kb/131462/en-us
0051 //
0052 //    Finally, this technique only works for 32-bit applications that are 
0053 //    using the Explorer-type common dialogs. 
0054 //
0055 //    Windows 95/98: For 32-bit applications that do not use the OFN_EXPLORER 
0056 //    flag, it thunks to the 16-bit common dialog and the hook function only 
0057 //    gets a copy of the OPENFILENAME structure.
0058 //
0059 //    Windows NT/2000: Applications should use Unicode version of the Open 
0060 //    file Common dialog. For example, use OPENFILENAMEW structure and call 
0061 //    GetOpenFileNameW API. This workaround will not work for Ansi version 
0062 //    of open file Common dialog. 
0063 
0064 UINT CALLBACK OFNHookProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
0065 {
0066     switch (uMsg)
0067     {
0068     case WM_NOTIFY:
0069         LPOFNOTIFY lpofn = (LPOFNOTIFY) lParam;
0070         
0071         switch (lpofn->hdr.code)
0072         {
0073         case CDN_SELCHANGE:
0074             LPOFNOTIFY lpofnNotify = (LPOFNOTIFY) lParam;        
0075             int cbLength = CommDlg_OpenSave_GetSpec(GetParent(hwnd), NULL, 0);
0076             cbLength += _MAX_PATH;
0077 
0078             if (lpofnNotify->lpOFN->nMaxFile < cbLength)
0079             {
0080                 if (lpofnNotify->lpOFN->lpstrFile)
0081                     delete[] lpofnNotify->lpOFN->lpstrFile;
0082 
0083                 WCHAR* Buffer = new WCHAR[cbLength];
0084                 lpofnNotify->lpOFN->lpstrFile = (LPTSTR)Buffer;
0085                 lpofnNotify->lpOFN->nMaxFile = cbLength;
0086             }
0087         }
0088     }
0089     return 0;
0090 } 
0091 
0092 // Implement by Zhang Luduo
0093 BOOL GetOpenMultiFile(vector<CString>* Result, HWND hOwner = NULL, TCHAR* Filter = _T("All Files(*.*)\0*.*\0\0"), TCHAR* InitDir = NULL)
0094 {
0095     HWND hwndOwner = hOwner;
0096 
0097 #if defined UNICODE || defined _UNICODE
0098     if (!Filter)
0099         Filter = L"All Files(*.*)\0*.*\0\0";
0100     WCHAR* lpstrFilter = Filter;
0101 #else
0102     if (!Filter)
0103         Filter = "All Files(*.*)\0*.*\0\0";
0104 
0105     //
0106     // Calc length of 'Filter'
0107     //
0108     CHAR* p = Filter;
0109     int CharLen = 0;
0110     for (;;)
0111     {
0112         CharLen++;
0113         if (*p == '\0')
0114         {
0115             if (*(p + 1) == '\0')
0116             {
0117                 CharLen++;
0118                 break;
0119             }
0120         }
0121         p++;
0122     }
0123 
0124     //
0125     // Copy 'Filter' to new buffer and replace '\0' to '|'
0126     //
0127 
0128     CHAR* Buffer = new CHAR[CharLen];
0129     memcpy(Buffer, Filter, CharLen);
0130 
0131     for (int i = 0; i < CharLen; i++)
0132     {
0133         if (Buffer[i] == '\0')
0134         {
0135             Buffer[i] = '|';
0136             if (Buffer[i + 1] == '\0')
0137                 break;
0138         }
0139     }
0140 
0141     WCHAR* FilterW = NULL;
0142     AnsiToUnicode(Buffer, &FilterW);
0143     WCHAR* lpstrFilter = FilterW;
0144 
0145     delete Buffer;
0146 
0147     //
0148     // Now we need replace '|' to '\0'
0149     //
0150 
0151     WCHAR* p2 = FilterW;
0152     while (*p2)
0153     {
0154         if (*p2 == '|')
0155             *p2 = '\0';
0156         p2++;
0157     }
0158 
0159 #endif    
0160 
0161     DWORD NameBufferLen = 1024;
0162     WCHAR* lpstrFile = new WCHAR[NameBufferLen];
0163     memset(lpstrFile, 0, NameBufferLen * sizeof(WCHAR));
0164     //_tcscpy(lpstrFile, _T("InitName"));
0165 
0166     OPENFILENAMEW ofn;
0167     memset(&ofn, 0, sizeof(OPENFILENAME));
0168 
0169     ofn.lStructSize       = 88;//sizeof(OPENFILENAME); 
0170     ofn.hwndOwner         = hwndOwner;
0171     ofn.hInstance         = NULL;
0172     ofn.lpstrFilter       = lpstrFilter;
0173     ofn.lpstrCustomFilter = NULL;
0174     ofn.nMaxCustFilter    = NULL;
0175     ofn.nFilterIndex      = 0;
0176     ofn.lpstrFile         = lpstrFile; // 在Hook函数中可能会重新分配内存, 调用GetOpenFileName完毕手工释放该内存
0177     ofn.nMaxFile          = NameBufferLen;
0178     ofn.lpstrFileTitle    = NULL;
0179     ofn.nMaxFileTitle     = NULL;
0180     ofn.lpstrInitialDir   = NULL;
0181 
0182     WCHAR* InitDirW = NULL;
0183     if (InitDir)
0184     {
0185         #if defined UNICODE || defined _UNICODE
0186             ofn.lpstrInitialDir = InitDir;
0187         #else            
0188             AnsiToUnicode(InitDir, &InitDirW);
0189             ofn.lpstrInitialDir = InitDirW;
0190         #endif
0191     }
0192 
0193     ofn.lpstrTitle        = NULL;
0194     ofn.Flags             = OFN_ENABLESIZING | OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_ENABLEHOOK;
0195     ofn.nFileOffset       = 0;
0196     ofn.nFileExtension    = 0;
0197     ofn.lpstrDefExt       = NULL;
0198     ofn.lCustData         = NULL;
0199     ofn.lpfnHook          = OFNHookProc;
0200     ofn.lpTemplateName    = NULL;
0201 
0202     if (GetOpenFileNameW(&ofn))
0203     {
0204         WCHAR* p = (WCHAR*)(ofn.lpstrFile);
0205         WCHAR FirstName[MAX_PATH] = { 0 };
0206         int index = 0;
0207 
0208         while (*p)
0209         {
0210             if (index++ == 0)
0211             {
0212                 #if _MSC_VER == 1200 // VC6
0213                     wcscpy(FirstName, p);
0214                 #else
0215                     wcscpy_s(FirstName, MAX_PATH, p);
0216                 #endif    
0217                 
0218                 while (*p++);
0219 
0220                 if (!(*p))
0221                 {
0222                     #if defined UNICODE || defined _UNICODE
0223                         Result->push_back(FirstName);
0224                     #else
0225                         CHAR* FirstNameA = NULL;
0226                         UnicodeToAnsi(FirstName, &FirstNameA);
0227                         Result->push_back(FirstNameA);
0228                         UnicodeToAnsi_Release(&FirstNameA);
0229                     #endif
0230 
0231                     break;
0232                 }
0233                 else
0234                 {
0235                     while (*p--);
0236                     if (FirstName[wcslen(FirstName) - 1] != '\\')
0237 
0238                     #if _MSC_VER == 1200 // VC6
0239                         wcscat(FirstName, L"\\");
0240                     #else
0241                         wcscat_s(FirstName, MAX_PATH, L"\\");
0242                     #endif                    
0243                 }
0244             }
0245             else
0246             {
0247                 #if defined UNICODE || defined _UNICODE
0248                     CString File;
0249                     File.Format(_T("%s%s"), FirstName, p);
0250                     Result->push_back(File);
0251                     //AfxMessageBox(File);
0252                 #else
0253                     WCHAR File[MAX_PATH] = { 0 };
0254 
0255                     #if _MSC_VER == 1200 // VC6
0256                         wcscpy(File, FirstName);
0257                         wcscat(File, p);
0258                     #else
0259                         wcscpy_s(File, MAX_PATH, FirstName);
0260                         wcscat_s(File, MAX_PATH, p);
0261                     #endif    
0262 
0263                     Result->push_back(File);                    
0264                 #endif
0265 
0266             }
0267 
0268             while (*p++);
0269         }
0270 
0271         if (ofn.lpstrFile != lpstrFile)
0272         {
0273             delete[] ofn.lpstrFile;
0274             ofn.lpstrFile = NULL;
0275         }
0276         else if (ofn.lpstrFile == lpstrFile)
0277         {
0278             delete[] lpstrFile;
0279             lpstrFile = NULL;
0280         }
0281 
0282         if (InitDir)
0283         {
0284             #if defined UNICODE || defined _UNICODE
0285             #else
0286                 AnsiToUnicode_Release(&InitDirW);
0287             #endif
0288         }
0289 
0290         #if defined UNICODE || defined _UNICODE
0291         #else
0292             AnsiToUnicode_Release(&FilterW);
0293         #endif
0294 
0295         //AfxMessageBox(_T("OK"));
0296         return TRUE;
0297     }
0298     else
0299     {
0300         delete[] lpstrFile;
0301         lpstrFile = NULL;
0302 
0303         if (InitDir)
0304         {
0305             #if defined UNICODE || defined _UNICODE
0306             #else
0307                 AnsiToUnicode_Release(&InitDirW);
0308             #endif
0309         }
0310 
0311         #if defined UNICODE || defined _UNICODE
0312         #else
0313             AnsiToUnicode_Release(&FilterW);
0314         #endif
0315 
0316         //AfxMessageBox(_T("Failed"));
0317         return FALSE;
0318     }
0319 }
0320 
0321 void CTestDlg::OnButton1() 
0322 {
0323     vector<CString> Result;
0324     GetOpenMultiFile(&Result, m_hWnd, _T("MP4 Files(*.mp4)\0*.mp4\0All Files(*.*)\0*.*\0\0"), _T("D:\\My Document\\GetOpenFileName\\UnicodeRelease"));
0325 
0326     CString Temp;
0327     for (int i = 0; i < Result.size(); i++)
0328         Temp += Result[i] + _T("\r\n");
0329     AfxMessageBox(Temp);
0330 
0331 }


Copyright © 2015 Zhang Luduo.

All rights reserved.