Shell.cpp (8696B)
1 // Windows/Shell.cpp 2 3 #include "StdAfx.h" 4 5 #include "../Common/MyCom.h" 6 #ifndef _UNICODE 7 #include "../Common/StringConvert.h" 8 #endif 9 10 #include "COM.h" 11 #include "Shell.h" 12 13 #ifndef _UNICODE 14 extern bool g_IsNT; 15 #endif 16 17 namespace NWindows { 18 namespace NShell { 19 20 #ifndef UNDER_CE 21 22 // SHGetMalloc is unsupported in Windows Mobile? 23 24 void CItemIDList::Free() 25 { 26 if (m_Object == NULL) 27 return; 28 CMyComPtr<IMalloc> shellMalloc; 29 if (::SHGetMalloc(&shellMalloc) != NOERROR) 30 throw 41099; 31 shellMalloc->Free(m_Object); 32 m_Object = NULL; 33 } 34 35 /* 36 CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) 37 { *this = itemIDList; } 38 CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) 39 { *this = itemIDList; } 40 41 CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) 42 { 43 Free(); 44 if (object != 0) 45 { 46 UINT32 size = GetSize(object); 47 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 48 if (m_Object != NULL) 49 MoveMemory(m_Object, object, size); 50 } 51 return *this; 52 } 53 54 CItemIDList& CItemIDList::operator=(const CItemIDList &object) 55 { 56 Free(); 57 if (object.m_Object != NULL) 58 { 59 UINT32 size = GetSize(object.m_Object); 60 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 61 if (m_Object != NULL) 62 MoveMemory(m_Object, object.m_Object, size); 63 } 64 return *this; 65 } 66 */ 67 68 ///////////////////////////// 69 // CDrop 70 71 void CDrop::Attach(HDROP object) 72 { 73 Free(); 74 m_Object = object; 75 m_Assigned = true; 76 } 77 78 void CDrop::Free() 79 { 80 if (m_MustBeFinished && m_Assigned) 81 Finish(); 82 m_Assigned = false; 83 } 84 85 UINT CDrop::QueryCountOfFiles() 86 { 87 return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); 88 } 89 90 UString CDrop::QueryFileName(UINT fileIndex) 91 { 92 UString fileName; 93 #ifndef _UNICODE 94 if (!g_IsNT) 95 { 96 AString fileNameA; 97 UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0); 98 const unsigned len = bufferSize + 2; 99 QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1); 100 fileNameA.ReleaseBuf_CalcLen(len); 101 fileName = GetUnicodeString(fileNameA); 102 } 103 else 104 #endif 105 { 106 UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); 107 const unsigned len = bufferSize + 2; 108 QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1); 109 fileName.ReleaseBuf_CalcLen(len); 110 } 111 return fileName; 112 } 113 114 void CDrop::QueryFileNames(UStringVector &fileNames) 115 { 116 UINT numFiles = QueryCountOfFiles(); 117 fileNames.ClearAndReserve(numFiles); 118 for (UINT i = 0; i < numFiles; i++) 119 fileNames.AddInReserved(QueryFileName(i)); 120 } 121 122 123 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) 124 { 125 const unsigned len = MAX_PATH * 2; 126 bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); 127 path.ReleaseBuf_CalcLen(len); 128 return result; 129 } 130 131 #endif 132 133 #ifdef UNDER_CE 134 135 bool BrowseForFolder(LPBROWSEINFO, CSysString) 136 { 137 return false; 138 } 139 140 bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) 141 { 142 return false; 143 } 144 145 bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, 146 LPCTSTR /* initialFolder */, CSysString & /* resultPath */) 147 { 148 /* 149 // SHBrowseForFolder doesn't work before CE 6.0 ? 150 if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) 151 MessageBoxW(0, L"no", L"", 0); 152 else 153 MessageBoxW(0, L"yes", L"", 0); 154 */ 155 /* 156 UString s = "all files"; 157 s += " (*.*)"; 158 return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); 159 */ 160 return false; 161 } 162 163 #else 164 165 bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) 166 { 167 NWindows::NCOM::CComInitializer comInitializer; 168 LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); 169 if (itemIDList == NULL) 170 return false; 171 CItemIDList itemIDListHolder; 172 itemIDListHolder.Attach(itemIDList); 173 return GetPathFromIDList(itemIDList, resultPath); 174 } 175 176 177 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 178 { 179 #ifndef UNDER_CE 180 switch (uMsg) 181 { 182 case BFFM_INITIALIZED: 183 { 184 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); 185 break; 186 } 187 /* 188 case BFFM_SELCHANGED: 189 { 190 TCHAR dir[MAX_PATH]; 191 if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) 192 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); 193 else 194 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); 195 break; 196 } 197 */ 198 default: 199 break; 200 } 201 #endif 202 return 0; 203 } 204 205 206 bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, 207 LPCTSTR initialFolder, CSysString &resultPath) 208 { 209 CSysString displayName; 210 BROWSEINFO browseInfo; 211 browseInfo.hwndOwner = owner; 212 browseInfo.pidlRoot = NULL; 213 214 // there are Unicode/Astring problems in some WinCE SDK ? 215 /* 216 #ifdef UNDER_CE 217 browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); 218 browseInfo.lpszTitle = (LPCSTR)title; 219 #else 220 */ 221 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); 222 browseInfo.lpszTitle = title; 223 // #endif 224 browseInfo.ulFlags = ulFlags; 225 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL; 226 browseInfo.lParam = (LPARAM)initialFolder; 227 return BrowseForFolder(&browseInfo, resultPath); 228 } 229 230 bool BrowseForFolder(HWND owner, LPCTSTR title, 231 LPCTSTR initialFolder, CSysString &resultPath) 232 { 233 return BrowseForFolder(owner, title, 234 #ifndef UNDER_CE 235 BIF_NEWDIALOGSTYLE | 236 #endif 237 BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); 238 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 239 } 240 241 #ifndef _UNICODE 242 243 typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); 244 245 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) 246 { 247 path.Empty(); 248 SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) 249 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); 250 if (shGetPathFromIDListW == 0) 251 return false; 252 const unsigned len = MAX_PATH * 2; 253 bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); 254 path.ReleaseBuf_CalcLen(len); 255 return result; 256 } 257 258 typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); 259 260 bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) 261 { 262 NWindows::NCOM::CComInitializer comInitializer; 263 SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) 264 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); 265 if (shBrowseForFolderW == 0) 266 return false; 267 LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); 268 if (itemIDList == NULL) 269 return false; 270 CItemIDList itemIDListHolder; 271 itemIDListHolder.Attach(itemIDList); 272 return GetPathFromIDList(itemIDList, resultPath); 273 } 274 275 276 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 277 { 278 switch (uMsg) 279 { 280 case BFFM_INITIALIZED: 281 { 282 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); 283 break; 284 } 285 /* 286 case BFFM_SELCHANGED: 287 { 288 wchar_t dir[MAX_PATH * 2]; 289 290 if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) 291 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); 292 else 293 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); 294 break; 295 } 296 */ 297 default: 298 break; 299 } 300 return 0; 301 } 302 303 304 static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, 305 LPCWSTR initialFolder, UString &resultPath) 306 { 307 UString displayName; 308 BROWSEINFOW browseInfo; 309 browseInfo.hwndOwner = owner; 310 browseInfo.pidlRoot = NULL; 311 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); 312 browseInfo.lpszTitle = title; 313 browseInfo.ulFlags = ulFlags; 314 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL; 315 browseInfo.lParam = (LPARAM)initialFolder; 316 return BrowseForFolder(&browseInfo, resultPath); 317 } 318 319 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) 320 { 321 if (g_IsNT) 322 return BrowseForFolder(owner, title, 323 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 324 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 325 , initialFolder, resultPath); 326 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 327 CSysString s; 328 bool res = BrowseForFolder(owner, GetSystemString(title), 329 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 330 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 331 , GetSystemString(initialFolder), s); 332 resultPath = GetUnicodeString(s); 333 return res; 334 } 335 336 #endif 337 338 #endif 339 340 }}