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())); }
void GetExplorerWindows(std::vector<PairHwndPath>& windows, BOOL needPaths) { IShellWindows *psw; if(SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) { VARIANT v; V_VT(&v) = VT_I4; IDispatch* pdisp; for(V_I4(&v) = 0; psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) { IWebBrowserApp *pwba; if(SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) { PairHwndPath pair; if(SUCCEEDED(pwba->get_HWND((LONG_PTR*)&pair.hwnd))) { IServiceProvider *psp; if(needPaths && SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) { IShellBrowser *psb; if(SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&psb))) { IShellView *psv; if(SUCCEEDED(psb->QueryActiveShellView(&psv))) { IFolderView *pfv; if(SUCCEEDED(psv->QueryInterface(IID_IFolderView, (void**)&pfv))) { IPersistFolder2 *ppf2; if(SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2, (void**)&ppf2))) { LPITEMIDLIST pidlFolder; if(SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) { if(!SHGetPathFromIDList(pidlFolder, pair.path)) { IShellFolder* psf; LPCITEMIDLIST pidlLast; if(SUCCEEDED(SHBindToParent(pidlFolder, IID_IShellFolder, (void**)&psf, &pidlLast))) { STRRET strret; if(SUCCEEDED(psf->GetDisplayNameOf(pidlLast, 0x8000, &strret))) { StrRetToBuf(&strret, pidlLast, pair.path, MAX_PATH); } else { pair.path[0] = 0; } psf->Release(); } } CoTaskMemFree(pidlFolder); } ppf2->Release(); } pfv->Release(); } psv->Release(); } psb->Release(); } psp->Release(); } windows.push_back(pair); } pwba->Release(); } pdisp->Release(); } psw->Release(); } }
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; }
bool CDeskBand::Filter(LPTSTR filter) { bool bReturn = 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 :) IShellFolderView * pShellFolderView; if (SUCCEEDED(pShellView->QueryInterface(IID_IShellFolderView, (LPVOID*)&pShellFolderView))) { // the first thing we do is to deselect all already selected entries pFolderView->SelectItem(NULL, SVSI_DESELECTOTHERS); // but we also need the IShellFolder interface because // we need its GetDisplayNameOf() method IPersistFolder2 * pPersistFolder; if (SUCCEEDED(pFolderView->GetFolder(IID_IPersistFolder2, (LPVOID*)&pPersistFolder))) { LPITEMIDLIST curFolder; pPersistFolder->GetCurFolder(&curFolder); if (ILIsEqual(m_currentFolder, curFolder)) { CoTaskMemFree(curFolder); } else { CoTaskMemFree(m_currentFolder); m_currentFolder = curFolder; for (size_t i=0; i<m_noShows.size(); ++i) { CoTaskMemFree(m_noShows[i]); } m_noShows.clear(); } 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 bool bUseRegex = (filter[0] == '\\'); try { const std::tr1::wregex regCheck(&filter[1], std::tr1::regex_constants::icase | std::tr1::regex_constants::ECMAScript); } catch (std::exception) { bUseRegex = false; } if (!bUseRegex) { // force the filter to lowercase TCHAR * pString = filter; while (*pString) { *pString = _totlower(*pString); pString++; } } int nCount = 0; if (SUCCEEDED(pFolderView->ItemCount(SVGIO_ALLVIEW, &nCount))) { pShellFolderView->SetRedraw(FALSE); HWND listView = GetListView32(pShellView); LRESULT viewType = 0; if (listView) { // inserting items in the list view if the list view is set to // e.g., LV_VIEW_LIST is painfully slow. So save the current view // and set it to LV_VIEW_DETAILS (which is much faster for inserting) // and restore the view after we're done. viewType = SendMessage(listView, LVM_GETVIEW, 0, 0); SendMessage(listView, LVM_SETVIEW, LV_VIEW_DETAILS, 0); } std::vector<LPITEMIDLIST> noShows; for (int i=0; i<nCount; ++i) { LPITEMIDLIST pidl; if (SUCCEEDED(pFolderView->Item(i, &pidl))) { if (CheckDisplayName(pShellFolder, pidl, filter, bUseRegex)) { // remove now shown items which are in the no-show list // this is necessary since we don't get a notification // if the shell refreshes its view for (std::vector<LPITEMIDLIST>::iterator it = m_noShows.begin(); it != m_noShows.end(); ++it ) { if (HRESULT_CODE(pShellFolder->CompareIDs(SHCIDS_CANONICALONLY, *it, pidl))==0) { m_noShows.erase(it); break; } } CoTaskMemFree(pidl); } else { UINT puItem = 0; if (pShellFolderView->RemoveObject(pidl, &puItem) == S_OK) { i--; nCount--; noShows.push_back(pidl); } } } } // now add all those items again which were removed by a previous filter string // but don't match this new one //pShellFolderView->SetObjectCount(5000, SFVSOC_INVALIDATE_ALL|SFVSOC_NOSCROLL); for (size_t i=0; i<m_noShows.size(); ++i) { LPITEMIDLIST pidlNoShow = m_noShows[i]; if (CheckDisplayName(pShellFolder, pidlNoShow, filter, bUseRegex)) { m_noShows.erase(m_noShows.begin() + i); i--; UINT puItem = (UINT)i; pShellFolderView->AddObject(pidlNoShow, &puItem); CoTaskMemFree(pidlNoShow); } } for (size_t i=0; i<noShows.size(); ++i) { m_noShows.push_back(noShows[i]); } if (listView) { SendMessage(listView, LVM_SETVIEW, viewType, 0); } pShellFolderView->SetRedraw(TRUE); } pShellFolder->Release(); } pPersistFolder->Release(); } pShellFolderView->Release(); } pFolderView->Release(); } pShellView->Release(); } pShellBrowser->Release(); } pServiceProvider->Release(); } return bReturn; }