Home | History | Annotate | Download | only in Windows
      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     QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);
     99     fileNameA.ReleaseBuffer();
    100     fileName = GetUnicodeString(fileNameA);
    101   }
    102   else
    103   #endif
    104   {
    105     UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
    106     QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);
    107     fileName.ReleaseBuffer();
    108   }
    109   return fileName;
    110 }
    111 
    112 void CDrop::QueryFileNames(UStringVector &fileNames)
    113 {
    114   UINT numFiles = QueryCountOfFiles();
    115   fileNames.ClearAndReserve(numFiles);
    116   for (UINT i = 0; i < numFiles; i++)
    117     fileNames.AddInReserved(QueryFileName(i));
    118 }
    119 
    120 
    121 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
    122 {
    123   bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));
    124   path.ReleaseBuffer();
    125   return result;
    126 }
    127 
    128 #endif
    129 
    130 #ifdef UNDER_CE
    131 
    132 bool BrowseForFolder(LPBROWSEINFO, CSysString)
    133 {
    134   return false;
    135 }
    136 
    137 bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
    138 {
    139   return false;
    140 }
    141 
    142 bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
    143     LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
    144 {
    145   /*
    146   // SHBrowseForFolder doesn't work before CE 6.0 ?
    147   if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
    148     MessageBoxW(0, L"no", L"", 0);
    149   else
    150     MessageBoxW(0, L"yes", L"", 0);
    151   */
    152   /*
    153   UString s = L"all files";
    154   s += L" (*.*)";
    155   return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
    156   */
    157   return false;
    158 }
    159 
    160 #else
    161 
    162 bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
    163 {
    164   NWindows::NCOM::CComInitializer comInitializer;
    165   LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
    166   if (itemIDList == NULL)
    167     return false;
    168   CItemIDList itemIDListHolder;
    169   itemIDListHolder.Attach(itemIDList);
    170   return GetPathFromIDList(itemIDList, resultPath);
    171 }
    172 
    173 
    174 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
    175 {
    176   #ifndef UNDER_CE
    177   switch(uMsg)
    178   {
    179     case BFFM_INITIALIZED:
    180     {
    181       SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
    182       break;
    183     }
    184     /*
    185     case BFFM_SELCHANGED:
    186     {
    187       TCHAR dir[MAX_PATH];
    188       if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
    189         SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
    190       else
    191         SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
    192       break;
    193     }
    194     */
    195     default:
    196       break;
    197   }
    198   #endif
    199   return 0;
    200 }
    201 
    202 
    203 bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
    204     LPCTSTR initialFolder, CSysString &resultPath)
    205 {
    206   CSysString displayName;
    207   BROWSEINFO browseInfo;
    208   browseInfo.hwndOwner = owner;
    209   browseInfo.pidlRoot = NULL;
    210 
    211   // there are Unicode/astring problems in WinCE SDK!!!
    212   #ifdef UNDER_CE
    213   browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);
    214   browseInfo.lpszTitle = (LPCSTR)title;
    215   #else
    216   browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
    217   browseInfo.lpszTitle = title;
    218   #endif
    219   browseInfo.ulFlags = ulFlags;
    220   browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
    221   browseInfo.lParam = (LPARAM)initialFolder;
    222   return BrowseForFolder(&browseInfo, resultPath);
    223 }
    224 
    225 bool BrowseForFolder(HWND owner, LPCTSTR title,
    226     LPCTSTR initialFolder, CSysString &resultPath)
    227 {
    228   return BrowseForFolder(owner, title,
    229       #ifndef UNDER_CE
    230       BIF_NEWDIALOGSTYLE |
    231       #endif
    232       BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
    233   // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)
    234 }
    235 
    236 #ifndef _UNICODE
    237 
    238 typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
    239 
    240 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
    241 {
    242   path.Empty();
    243   SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
    244     ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
    245   if (shGetPathFromIDListW == 0)
    246     return false;
    247   bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));
    248   path.ReleaseBuffer();
    249   return result;
    250 }
    251 
    252 typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
    253 
    254 bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
    255 {
    256   NWindows::NCOM::CComInitializer comInitializer;
    257   SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
    258     ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
    259   if (shBrowseForFolderW == 0)
    260     return false;
    261   LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
    262   if (itemIDList == NULL)
    263     return false;
    264   CItemIDList itemIDListHolder;
    265   itemIDListHolder.Attach(itemIDList);
    266   return GetPathFromIDList(itemIDList, resultPath);
    267 }
    268 
    269 
    270 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
    271 {
    272   switch(uMsg)
    273   {
    274     case BFFM_INITIALIZED:
    275     {
    276       SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
    277       break;
    278     }
    279     /*
    280     case BFFM_SELCHANGED:
    281     {
    282       wchar_t dir[MAX_PATH * 2];
    283 
    284       if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
    285         SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
    286       else
    287         SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
    288       break;
    289     }
    290     */
    291     default:
    292       break;
    293   }
    294   return 0;
    295 }
    296 
    297 
    298 static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
    299     LPCWSTR initialFolder, UString &resultPath)
    300 {
    301   UString displayName;
    302   BROWSEINFOW browseInfo;
    303   browseInfo.hwndOwner = owner;
    304   browseInfo.pidlRoot = NULL;
    305   browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
    306   browseInfo.lpszTitle = title;
    307   browseInfo.ulFlags = ulFlags;
    308   browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
    309   browseInfo.lParam = (LPARAM)initialFolder;
    310   return BrowseForFolder(&browseInfo, resultPath);
    311 }
    312 
    313 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
    314 {
    315   if (g_IsNT)
    316     return BrowseForFolder(owner, title,
    317       BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
    318       //  | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
    319       , initialFolder, resultPath);
    320   // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)
    321   CSysString s;
    322   bool res = BrowseForFolder(owner, GetSystemString(title),
    323       BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
    324       // | BIF_STATUSTEXT  // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
    325       , GetSystemString(initialFolder), s);
    326   resultPath = GetUnicodeString(s);
    327   return res;
    328 }
    329 
    330 #endif
    331 
    332 #endif
    333 
    334 }}
    335