bool CDeskBand::FindPaths() { m_currentDirectory.clear(); m_selectedItems.clear(); m_bFilesSelected = false; m_bFolderSelected = false; if (m_pSite == NULL) return false; IServiceProvider * pServiceProvider; if (SUCCEEDED(m_pSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServiceProvider))) { IShellBrowser * pShellBrowser; if (SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_IShellBrowser, (LPVOID*)&pShellBrowser))) { IShellView * pShellView; if (SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView))) { IFolderView * pFolderView; if (SUCCEEDED(pShellView->QueryInterface(IID_IFolderView, (LPVOID*)&pFolderView))) { // hooray! we got the IFolderView interface! // that means the explorer is active and well :) // but we also need the IShellFolder interface because // we need its GetCurFolder() method IPersistFolder2 * pPersistFolder; if (SUCCEEDED(pFolderView->GetFolder(IID_IPersistFolder2, (LPVOID*)&pPersistFolder))) { LPITEMIDLIST folderpidl; if (SUCCEEDED(pPersistFolder->GetCurFolder(&folderpidl))) { // we have the current folder TCHAR buf[MAX_PATH] = {0}; // find the path of the folder if (SHGetPathFromIDList(folderpidl, buf)) { m_currentDirectory = buf; } // if m_currentDirectory is empty here, that means // the current directory is a virtual path IShellFolder * pShellFolder; if (SUCCEEDED(pPersistFolder->QueryInterface(IID_IShellFolder, (LPVOID*)&pShellFolder))) { // if there was a new folder created but not found to set into editing mode, // we try here to do that if (!m_newfolderPidls.empty()) { int nCount2 = 0; IShellFolder * pShellFolder; if (SUCCEEDED(pPersistFolder->QueryInterface(IID_IShellFolder, (LPVOID*)&pShellFolder))) { if (SUCCEEDED(pFolderView->ItemCount(SVGIO_ALLVIEW, &nCount2))) { for (int i=0; i<nCount2; ++i) { LPITEMIDLIST pidl; pFolderView->Item(i, &pidl); bool bFound = false; for (std::vector<LPITEMIDLIST>::iterator it = m_newfolderPidls.begin(); it != m_newfolderPidls.end(); ++it) { HRESULT hr = pShellFolder->CompareIDs(0, pidl, *it); if (HRESULT_CODE(hr) == 0) { // this item was there before, so it's not the new folder CoTaskMemFree(*it); m_newfolderPidls.erase(it); bFound = true; break; } } if (!bFound) { pShellView->SelectItem(pidl, SVSI_EDIT); } CoTaskMemFree(pidl); } } if ((nCount2)||(m_newfolderTimeoutCounter-- <= 0)) { m_newfolderTimeoutCounter = 0; for (std::vector<LPITEMIDLIST>::iterator it = m_newfolderPidls.begin(); it != m_newfolderPidls.end(); ++it) { CoTaskMemFree(*it); } m_newfolderPidls.clear(); } pShellFolder->Release(); } } // find all selected items IEnumIDList * pEnum; if (SUCCEEDED(pFolderView->Items(SVGIO_SELECTION, IID_IEnumIDList, (LPVOID*)&pEnum))) { LPITEMIDLIST pidl; WCHAR buf[MAX_PATH] = {0}; ULONG fetched = 0; ULONG attribs = 0; do { pidl = NULL; if (SUCCEEDED(pEnum->Next(1, &pidl, &fetched))) { if (fetched) { // the pidl we get here is relative! attribs = SFGAO_FILESYSTEM|SFGAO_FOLDER; if (SUCCEEDED(pShellFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &attribs))) { if (attribs & SFGAO_FILESYSTEM) { // create an absolute pidl with the pidl we got above LPITEMIDLIST abspidl = CPidl::Append(folderpidl, pidl); if (abspidl) { if (SHGetPathFromIDList(abspidl, buf)) { m_selectedItems[std::wstring(buf)] = attribs; if (m_currentDirectory.empty()) { // remove the last part of the path of the selected item WCHAR * pSlash = _tcsrchr(buf, '\\'); if (pSlash) *pSlash = 0; m_currentDirectory = std::wstring(buf); } } CoTaskMemFree(abspidl); } if (attribs & SFGAO_FOLDER) m_bFolderSelected = true; else m_bFilesSelected = true; } } } CoTaskMemFree(pidl); } } while(fetched); pEnum->Release(); } pShellFolder->Release(); } CoTaskMemFree(folderpidl); } pPersistFolder->Release(); } pFolderView->Release(); } pShellView->Release(); } pShellBrowser->Release(); } pServiceProvider->Release(); } return ((!m_currentDirectory.empty()) || (!m_selectedItems.empty())); }
/* * Class: sun_awt_shell_Win32ShellFolder2 * Method: getAttributes0 * Signature: (JJI)J */ JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getAttributes0 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong jpIDL, jint attrsMask) { IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder; if (pParentIShellFolder == NULL) { return 0; } LPCITEMIDLIST pIDL = (LPCITEMIDLIST)jpIDL; if (pIDL == NULL) { return 0; } ULONG attrs = attrsMask; HRESULT res = pParentIShellFolder->GetAttributesOf(1, &pIDL, &attrs); return attrs; }
/* * Class: sun_awt_shell_Win32ShellFolder * Method: hasAttribute * Signature: (JJI)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_shell_Win32ShellFolder_hasAttribute__JJI (JNIEnv* env, jobject folder, jlong parentIShellFolder, jlong relativePIDL, jint dwAttribute) { IShellFolder* pParent = (IShellFolder*)parentIShellFolder; if (pParent == NULL) { return false; } LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; if (pidl == NULL) { return false; } ULONG attrib = (ULONG)dwAttribute; pParent->GetAttributesOf(1, const_cast<LPCITEMIDLIST*>(&pidl), &attrib); return ((dwAttribute & attrib) != 0); }
HRESULT GetItemAttributes(LPCITEMIDLIST pidl,SFGAOF *pItemAttributes) { if(pidl == NULL || pItemAttributes == NULL) { return E_FAIL; } IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlRelative = NULL; HRESULT hr; hr = SHBindToParent(pidl, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { hr = pShellFolder->GetAttributesOf(1,(LPCITEMIDLIST *)&pidlRelative,pItemAttributes); pShellFolder->Release(); } return hr; }
void CDeskBand::Rename(HWND hwnd, const std::map<std::wstring, ULONG>& items) { // fill the list of selected file/foldernames m_filelist.clear(); if (items.size() > 1) { for (std::map<std::wstring, ULONG>::const_iterator it = items.begin(); it != items.end(); ++it) { size_t pos = it->first.find_last_of('\\'); if (pos != std::wstring::npos) { m_filelist.insert(it->first.substr(pos+1)); } } } else if (items.size() == 1) { for (std::map<std::wstring, ULONG>::const_iterator it = items.begin(); it != items.end(); ++it) { size_t pos = it->first.find_last_of('\\'); if (pos != std::wstring::npos) { m_filelist.insert(it->first.substr(pos+1)); } } } else { // no files or only one file were selected. // use all files and folders in the current folder instead IServiceProvider * pServiceProvider = NULL; if (SUCCEEDED(GetIServiceProvider(hwnd, &pServiceProvider))) { IShellBrowser * pShellBrowser; if (SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_IShellBrowser, (LPVOID*)&pShellBrowser))) { IShellView * pShellView; if (SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView))) { IFolderView * pFolderView; if (SUCCEEDED(pShellView->QueryInterface(IID_IFolderView, (LPVOID*)&pFolderView))) { // hooray! we got the IFolderView interface! // that means the explorer is active and well :) // but we also need the IShellFolder interface because // we need its GetCurFolder() method IPersistFolder2 * pPersistFolder; if (SUCCEEDED(pFolderView->GetFolder(IID_IPersistFolder2, (LPVOID*)&pPersistFolder))) { LPITEMIDLIST folderpidl; if (SUCCEEDED(pPersistFolder->GetCurFolder(&folderpidl))) { // we have the current folder TCHAR buf[MAX_PATH] = {0}; // find the path of the folder if (SHGetPathFromIDList(folderpidl, buf)) { m_currentDirectory = buf; } // if m_currentDirectory is empty here, that means // the current directory is a virtual path IShellFolder * pShellFolder; if (SUCCEEDED(pPersistFolder->QueryInterface(IID_IShellFolder, (LPVOID*)&pShellFolder))) { // find all selected items IEnumIDList * pEnum; if (SUCCEEDED(pFolderView->Items(SVGIO_ALLVIEW, IID_IEnumIDList, (LPVOID*)&pEnum))) { LPITEMIDLIST pidl; WCHAR buf[MAX_PATH] = {0}; ULONG fetched = 0; ULONG attribs = 0; do { pidl = NULL; if (SUCCEEDED(pEnum->Next(1, &pidl, &fetched))) { if (fetched) { // the pidl we get here is relative! attribs = SFGAO_FILESYSTEM|SFGAO_FOLDER; if (SUCCEEDED(pShellFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &attribs))) { if (attribs & SFGAO_FILESYSTEM) { // create an absolute pidl with the pidl we got above LPITEMIDLIST abspidl = CPidl::Append(folderpidl, pidl); if (abspidl) { if (SHGetPathFromIDList(abspidl, buf)) { std::wstring p = buf; size_t pos = p.find_last_of('\\'); if (pos != std::wstring::npos) { m_filelist.insert(p.substr(pos+1)); } } CoTaskMemFree(abspidl); } } } } CoTaskMemFree(pidl); } } while(fetched); pEnum->Release(); } pShellFolder->Release(); } CoTaskMemFree(folderpidl); } pPersistFolder->Release(); } pFolderView->Release(); } pShellView->Release(); } pShellBrowser->Release(); } pServiceProvider->Release(); } } // show the rename dialog m_bDialogShown = TRUE; CRenameDlg dlg(hwnd); dlg.SetFileList(m_filelist); if (dlg.DoModal(g_hInst, IDD_RENAMEDLG, hwnd, NULL) == IDOK) { try { const std::tr1::wregex regCheck(dlg.GetMatchString(), dlg.GetRegexFlags()); NumberReplaceHandler handler(dlg.GetReplaceString()); // start renaming the files IServiceProvider * pServiceProvider = NULL; if (SUCCEEDED(GetIServiceProvider(hwnd, &pServiceProvider))) { IShellBrowser * pShellBrowser; if (SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_IShellBrowser, (LPVOID*)&pShellBrowser))) { IShellView * pShellView; if (SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView))) { IFolderView * pFolderView; if (SUCCEEDED(pShellView->QueryInterface(IID_IFolderView, (LPVOID*)&pFolderView))) { // hooray! we got the IFolderView interface! // that means the explorer is active and well :) // but we also need the IShellFolder interface because // we need its GetDisplayNameOf() method IPersistFolder2 * pPersistFolder; if (SUCCEEDED(pFolderView->GetFolder(IID_IPersistFolder2, (LPVOID*)&pPersistFolder))) { IShellFolder * pShellFolder; if (SUCCEEDED(pPersistFolder->QueryInterface(IID_IShellFolder, (LPVOID*)&pShellFolder))) { // our next task is to enumerate all the // items in the folder view and select those // which match the text in the edit control int nCount = 0; if (SUCCEEDED(pFolderView->ItemCount(SVGIO_ALLVIEW, &nCount))) { for (int i=0; i<nCount; ++i) { LPITEMIDLIST pidl; if (SUCCEEDED(pFolderView->Item(i, &pidl))) { STRRET str; if (SUCCEEDED(pShellFolder->GetDisplayNameOf(pidl, // SHGDN_FORPARSING needed to get the extensions even if they're not shown SHGDN_INFOLDER|SHGDN_FORPARSING, &str))) { TCHAR dispname[MAX_PATH]; StrRetToBuf(&str, pidl, dispname, _countof(dispname)); std::wstring replaced; try { std::wstring sDispName = dispname; // check if the item is in the list of selected items if (m_filelist.find(sDispName) != m_filelist.end()) { replaced = std::tr1::regex_replace(sDispName, regCheck, dlg.GetReplaceString()); replaced = handler.ReplaceCounters(replaced); if (replaced.compare(sDispName)) { ITEMIDLIST * pidlrenamed; pShellFolder->SetNameOf(NULL, pidl, replaced.c_str(), SHGDN_FORPARSING|SHGDN_INFOLDER, &pidlrenamed); // if the rename was successful, select the renamed item if (pidlrenamed) pFolderView->SelectItem(i, SVSI_CHECK|SVSI_SELECT); } } } catch (std::exception) { } } CoTaskMemFree(pidl); } } } pShellFolder->Release(); } pPersistFolder->Release(); } pFolderView->Release(); } pShellView->Release(); } pShellBrowser->Release(); } pServiceProvider->Release(); } } catch (std::exception) { } } m_bDialogShown = FALSE; }
void FileDialog::FilterFiles(HWND hDlg) { HWND parent = ::GetParent(hDlg); IShellFolder *ishell = NULL; LPMALLOC imalloc = NULL; HRESULT hr; // Get pointer to the ListView control HWND lv = ::GetDlgItem(::GetDlgItem(parent, lst2), 1); if (lv == NULL) { wxASSERT(lv != NULL); return; } // Get shell's memory allocation interface (must be Release()'d) hr = SHGetMalloc(&imalloc); if ((hr != NOERROR) || (imalloc == NULL)) { wxASSERT((hr == NOERROR) && (imalloc != NULL)); return; } // Init LVITEM lvi; wxZeroMemory(lvi); // Process all items int fltcnt = m_Filters.GetCount(); int itmcnt = ::SendMessage(lv, LVM_GETITEMCOUNT, 0, 0); for (int itm = 0; itm < itmcnt; itm++) { // Retrieve the file IDL lvi.iItem = itm; lvi.mask = LVIF_PARAM; if (ListView_GetItem(lv, &lvi) != TRUE) { wxASSERT(FALSE); break; } LPCITEMIDLIST fidl = (LPCITEMIDLIST) lvi.lParam; // Retrieve the IShellFolder interface of the parent (must be Release()'d) if (ishell == NULL) { hr = SHBindToParent(fidl, IID_IShellFolder, (void **)&ishell, NULL); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } } // Get the attributes of the object DWORD attr = SFGAO_FOLDER | SFGAO_STREAM; hr = ishell->GetAttributesOf(1, &fidl, &attr); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } // Allow all folders (things like zip files get filtered below) if (attr == SFGAO_FOLDER) { continue; } // Retrieve the parsable name of the object (includes extension) STRRET str; hr = ishell->GetDisplayNameOf(fidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str); if (hr != NOERROR) { // For some objects, we get back an error of 80070057. I'm assuming this // means there is no way to represent the name (like some sort of virtual name) // or I've not used the correct PIDL. But, in either case, it "probably" // represents some sort of folder (at least in all cases I've seen), so we // simply allow it to display. continue; } // Convert result to wxString wxString filename; switch (str.uType) { case STRRET_WSTR: filename = str.pOleStr; imalloc->Free(str.pOleStr); break; case STRRET_OFFSET: filename = wxString(((char *)fidl) + str.uOffset, wxConvISO8859_1); break; case STRRET_CSTR: filename = wxString(str.cStr, wxConvISO8859_1); break; } // Attempt to match it to all of our filters bool match = false; for (int flt = 0; flt < fltcnt; flt++) { if (wxMatchWild(m_Filters[flt], filename, false)) { match = true; break; } } // Remove it from the display if it didn't match any of the filters. if (!match) { ListView_DeleteItem(lv, itm); itm--; itmcnt--; } } done: // Release the interface if (ishell) { ishell->Release(); } // Release the interface if (imalloc) { imalloc->Release(); } }
const FileItemList& FileItem::getChildren() { // Is the file-item a folder? if (IS_FOLDER(this) && // if the children list is empty, or the file-system version // change (it's like to say: the current this->children list // is outdated)... (this->children.empty() || current_file_system_version > this->version)) { FileItemList::iterator it; FileItem* child; // we have to mark current items as deprecated for (it=this->children.begin(); it!=this->children.end(); ++it) { child = static_cast<FileItem*>(*it); child->removed = true; } //PRINTF("FS: Loading files for %p (%s)\n", fileitem, fileitem->displayname); #ifdef USE_PIDLS { IShellFolder* pFolder = NULL; if (this == rootitem) pFolder = shl_idesktop; else shl_idesktop->BindToObject(this->fullpidl, NULL, IID_IShellFolder, (LPVOID *)&pFolder); if (pFolder != NULL) { IEnumIDList *pEnum = NULL; ULONG c, fetched; /* get the interface to enumerate subitems */ pFolder->EnumObjects(win_get_window(), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum); if (pEnum != NULL) { LPITEMIDLIST itempidl[256]; SFGAOF attribs[256]; /* enumerate the items in the folder */ while (pEnum->Next(256, itempidl, &fetched) == S_OK && fetched > 0) { /* request the SFGAO_FOLDER attribute to know what of the item is a folder */ for (c=0; c<fetched; ++c) { attribs[c] = SFGAO_FOLDER; pFolder->GetAttributesOf(1, (LPCITEMIDLIST *)itempidl, attribs+c); } /* generate the FileItems */ for (c=0; c<fetched; ++c) { LPITEMIDLIST fullpidl = concat_pidl(this->fullpidl, itempidl[c]); child = get_fileitem_by_fullpidl(fullpidl, false); if (!child) { child = new FileItem(this); child->pidl = itempidl[c]; child->fullpidl = fullpidl; child->attrib = attribs[c]; update_by_pidl(child); put_fileitem(child); } else { ASSERT(child->parent == this); free_pidl(fullpidl); free_pidl(itempidl[c]); } this->insertChildSorted(child); } } pEnum->Release(); } if (pFolder != shl_idesktop) pFolder->Release(); } } #else { char buf[MAX_PATH], path[MAX_PATH], tmp[32]; ustrcpy(path, this->filename.c_str()); put_backslash(path); replace_filename(buf, path, uconvert_ascii("*.*", tmp), sizeof(buf)); #ifdef WORKAROUND_64BITS_SUPPORT // we cannot use the for_each_file's 'param' to wrap a 64-bits pointer for_each_child_callback_param = this; for_each_file(buf, FA_TO_SHOW, for_each_child_callback, 0); #else for_each_file(buf, FA_TO_SHOW, for_each_child_callback, (int)this); #endif } #endif // check old file-items (maybe removed directories or file-items) for (it=this->children.begin(); it!=this->children.end(); ) { child = static_cast<FileItem*>(*it); if (child->removed) { it = this->children.erase(it); fileitems_map->erase(fileitems_map->find(child->keyname)); delete child; } else ++it; } // now this file-item is updated this->version = current_file_system_version; } return this->children; }
void FileDialog::FilterFiles(HWND hDlg, bool refresh) { HWND parent = ::GetParent(hDlg); IShellFolder *ishell = NULL; IShellBrowser *ishellbrowser = NULL; // Does not have to be released IShellView *ishellview = NULL; IFolderView *ifolderview = NULL; LPMALLOC imalloc = NULL; HRESULT hr; // Get pointer to the ListView control HWND lv = ::GetDlgItem(::GetDlgItem(parent, lst2), 1); if (lv == NULL) { wxASSERT(lv != NULL); return; } // Get shell's memory allocation interface (must be Release()'d) hr = SHGetMalloc(&imalloc); if ((hr != NOERROR) || (imalloc == NULL)) { wxASSERT((hr == NOERROR) && (imalloc != NULL)); return; } // Get IShellBrowser interface for current dialog ishellbrowser = (IShellBrowser*)::SendMessage(parent, WM_GETISHELLBROWSER, 0, 0); if (ishellbrowser) { // Get IShellBrowser interface for returned browser if (ishellbrowser->QueryActiveShellView(&ishellview) == S_OK) { // Get the IFolderView interface...available on XP or greater ishellview->QueryInterface(IID_IFolderView, (void **)&ifolderview); } } // Init LVITEM lvi; wxZeroMemory(lvi); // Process all items int fltcnt = (int) m_Filters.GetCount(); int itmcnt = ::SendMessage(lv, LVM_GETITEMCOUNT, 0, 0); for (int itm = 0; itm < itmcnt; itm++) { // Retrieve the file IDL lvi.iItem = itm; lvi.mask = LVIF_PARAM; if (ListView_GetItem(lv, &lvi) != TRUE) { wxASSERT(FALSE); break; } LPCITEMIDLIST fidl = (LPCITEMIDLIST) lvi.lParam; // On Vista, lParam no longer contains the pidl so retrieve it via the // IFolderView interface. This interface is only available on XP or higher // so if that limitation isn't workable, use IShellView::GetItemObject() to // retrieve items. if (fidl == NULL && ifolderview != NULL) { ifolderview->Item(itm, (LPITEMIDLIST *) &fidl); } if (fidl == NULL) { wxASSERT(fidl != NULL); break; } // Retrieve the IShellFolder interface of the parent (must be Release()'d) if (ishell == NULL) { hr = SHBindToParentLocal(fidl, IID_IShellFolder, (void **)&ishell, NULL); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } } // Get the attributes of the object DWORD attr = SFGAO_FOLDER | SFGAO_BROWSABLE; hr = ishell->GetAttributesOf(1, &fidl, &attr); if (!SUCCEEDED(hr)) { wxASSERT(SUCCEEDED(hr)); break; } // Allow all folders (things like zip files get filtered below) if ((attr & (SFGAO_FOLDER)) && !(attr & SFGAO_BROWSABLE)) { continue; } // Retrieve the parsable name of the object (includes extension) STRRET str; hr = ishell->GetDisplayNameOf(fidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str); if (hr != NOERROR) { // For some objects, we get back an error of 80070057. I'm assuming this // means there is no way to represent the name (like some sort of virtual name) // or I've not used the correct PIDL. But, in either case, it "probably" // represents some sort of folder (at least in all cases I've seen), so we // simply allow it to display. continue; } // Convert result to wxString wxString filename; switch (str.uType) { case STRRET_WSTR: filename = str.pOleStr; imalloc->Free(str.pOleStr); break; case STRRET_OFFSET: filename = wxString(((char *)fidl) + str.uOffset, wxConvISO8859_1); break; case STRRET_CSTR: filename = wxString(str.cStr, wxConvISO8859_1); break; } // Convert the filename to lowercase (and remember to write filters in lowercase!) filename = filename.Lower(); // Attempt to match it to all of our filters bool match = false; for (int flt = 0; flt < fltcnt; flt++) { if (wxMatchWild(m_Filters[flt], filename, false)) { match = true; break; } } // Remove it from the display if it didn't match any of the filters. if (!match) { ListView_DeleteItem(lv, itm); itm--; itmcnt--; } } // On Vista and maybe XP, we seem to need to refresh the view after // changing the filters. But, only refresh for type changes and not // selection changes since it causes additional selection change // events to occur. if (ishellview && refresh) { ishellview->Refresh(); } // Release the interface if (ifolderview) { ifolderview->Release(); } // Release the interface if (ishellview) { ishellview->Release(); } // Release the interface if (ishell) { ishell->Release(); } // Release the interface if (imalloc) { imalloc->Release(); } }
void CShellBrowser::BrowseVirtualFolder(LPITEMIDLIST pidlDirectory) { IShellFolder *pShellFolder = NULL; IEnumIDList *pEnumIDList = NULL; LPITEMIDLIST rgelt = NULL; STRRET str; SHCONTF EnumFlags; TCHAR szFileName[MAX_PATH]; ULONG uFetched; HRESULT hr; DetermineFolderVirtual(pidlDirectory); hr = BindToIdl(pidlDirectory, IID_PPV_ARGS(&pShellFolder)); if(SUCCEEDED(hr)) { m_pidlDirectory = ILClone(pidlDirectory); EnumFlags = SHCONTF_FOLDERS|SHCONTF_NONFOLDERS; if(m_bShowHidden) EnumFlags |= SHCONTF_INCLUDEHIDDEN; hr = pShellFolder->EnumObjects(m_hOwner,EnumFlags,&pEnumIDList); if(SUCCEEDED(hr) && pEnumIDList != NULL) { uFetched = 1; while(pEnumIDList->Next(1,&rgelt,&uFetched) == S_OK && (uFetched == 1)) { ULONG uAttributes = SFGAO_FOLDER; pShellFolder->GetAttributesOf(1,(LPCITEMIDLIST *)&rgelt,&uAttributes); /* If this is a virtual folder, only use SHGDN_INFOLDER. If this is a real folder, combine SHGDN_INFOLDER with SHGDN_FORPARSING. This is so that items in real folders can still be shown with extensions, even if the global, Explorer option is disabled. Also use only SHGDN_INFOLDER if this item is a folder. This is to ensure that specific folders in Windows 7 (those under C:\Users\Username) appear correctly. */ if(m_bVirtualFolder || (uAttributes & SFGAO_FOLDER)) hr = pShellFolder->GetDisplayNameOf(rgelt,SHGDN_INFOLDER,&str); else hr = pShellFolder->GetDisplayNameOf(rgelt,SHGDN_INFOLDER|SHGDN_FORPARSING,&str); if(SUCCEEDED(hr)) { StrRetToBuf(&str,rgelt,szFileName,MAX_PATH); AddItemInternal(pidlDirectory,rgelt,szFileName,-1,FALSE); } CoTaskMemFree((LPVOID)rgelt); } pEnumIDList->Release(); } pShellFolder->Release(); } }
void CMyTreeView::AddItemInternal(HTREEITEM hParent,const TCHAR *szFullFileName) { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlComplete = NULL; LPITEMIDLIST pidlRelative = NULL; HTREEITEM hItem; TVITEMEX tvItem; TVINSERTSTRUCT tvis; SHFILEINFO shfi; SFGAOF Attributes; TCHAR szDisplayName[MAX_PATH]; HRESULT hr; BOOL res; int iItemId; int nChildren = 0; hr = GetIdlFromParsingName(szFullFileName,&pidlComplete); if(!SUCCEEDED(hr)) return; tvItem.mask = TVIF_CHILDREN | TVIF_STATE; tvItem.hItem = hParent; res = TreeView_GetItem(m_hTreeView,&tvItem); if(res) { /* If the parent node is currently collapsed, simply indicate that it has children (i.e. a plus sign will be shown next to the parent node). */ if((tvItem.cChildren == 0) || ((tvItem.state & TVIS_EXPANDED) != TVIS_EXPANDED)) { tvItem.mask = TVIF_CHILDREN; tvItem.hItem = hParent; tvItem.cChildren = 1; TreeView_SetItem(m_hTreeView,&tvItem); } else { SHGetFileInfo(szFullFileName,NULL,&shfi, sizeof(shfi),SHGFI_SYSICONINDEX); hr = SHBindToParent(pidlComplete, IID_PPV_ARGS(&pShellFolder), (LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { Attributes = SFGAO_HASSUBFOLDER; /* Only retrieve the attributes for this item. */ hr = pShellFolder->GetAttributesOf(1, (LPCITEMIDLIST *)&pidlRelative,&Attributes); if(SUCCEEDED(hr)) { if((Attributes & SFGAO_HASSUBFOLDER) != SFGAO_HASSUBFOLDER) nChildren = 0; else nChildren = 1; iItemId = GenerateUniqueItemId(); m_pItemInfo[iItemId].pidl = ILClone(pidlComplete); m_pItemInfo[iItemId].pridl = ILClone(pidlRelative); GetDisplayName(szFullFileName,szDisplayName,SIZEOF_ARRAY(szDisplayName),SHGDN_NORMAL); tvItem.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM|TVIF_CHILDREN; tvItem.pszText = szDisplayName; tvItem.iImage = shfi.iIcon; tvItem.iSelectedImage = shfi.iIcon; tvItem.lParam = (LPARAM)iItemId; tvItem.cChildren = nChildren; if(hParent != NULL) { tvis.hParent = hParent; tvis.hInsertAfter = DetermineItemSortedPosition(hParent,szFullFileName); tvis.itemex = tvItem; hItem = TreeView_InsertItem(m_hTreeView,&tvis); } } pShellFolder->Release(); } } } CoTaskMemFree(pidlComplete); }
//*************************************************************************************** void CBCGPShellList::DoDefault (int iItem) { LVITEM lvItem; ZeroMemory(&lvItem, sizeof(lvItem)); lvItem.mask = LVIF_PARAM; lvItem.iItem = iItem; if (!GetItem (&lvItem)) { return; } LPBCGCBITEMINFO pInfo = (LPBCGCBITEMINFO) lvItem.lParam; if (pInfo == NULL || pInfo->pParentFolder == NULL || pInfo->pidlRel == NULL) { ASSERT (FALSE); return; } IShellFolder *psfFolder = pInfo->pParentFolder; if (psfFolder == NULL) { SHGetDesktopFolder (&psfFolder); } else { psfFolder->AddRef (); } if (psfFolder == NULL) { return; } //----------------------------------------------------- // If specified element is a folder, try to display it: //----------------------------------------------------- ULONG ulAttrs = SFGAO_FOLDER; psfFolder->GetAttributesOf (1, (const struct _ITEMIDLIST **) &pInfo->pidlRel, &ulAttrs); if (ulAttrs & SFGAO_FOLDER) { DisplayFolder (pInfo); } else { //------------------------------- // Invoke a default menu command: //------------------------------- IContextMenu *pcm; HRESULT hr = psfFolder->GetUIObjectOf (GetSafeHwnd (), 1, (LPCITEMIDLIST*)&pInfo->pidlRel, IID_IContextMenu, NULL, (LPVOID*)&pcm); if (SUCCEEDED (hr)) { HMENU hPopup = CreatePopupMenu (); if (hPopup != NULL) { hr = pcm->QueryContextMenu (hPopup, 0, 1, 0x7fff, CMF_DEFAULTONLY | CMF_EXPLORE); if (SUCCEEDED (hr)) { UINT idCmd = ::GetMenuDefaultItem (hPopup, FALSE, 0); if (idCmd != 0 && idCmd != (UINT)-1) { CMINVOKECOMMANDINFO cmi; cmi.cbSize = sizeof (CMINVOKECOMMANDINFO); cmi.fMask = 0; cmi.hwnd = GetParent()->GetSafeHwnd (); cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - 1); cmi.lpParameters = NULL; cmi.lpDirectory = NULL; cmi.nShow = SW_SHOWNORMAL; cmi.dwHotKey = 0; cmi.hIcon = NULL; hr = pcm->InvokeCommand (&cmi); if (SUCCEEDED (hr) && GetParent () != NULL) { GetParent ()->SendMessage (BCGPM_ON_AFTER_SHELL_COMMAND, (WPARAM) idCmd); } } } } pcm->Release (); } } psfFolder->Release (); }