00001 /* 00002 * Copyright 2003, 2004, 2005 Martin Fuchs 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 00020 // 00021 // Explorer clone 00022 // 00023 // dialogs/searchprogram.cpp 00024 // 00025 // Explorer dialogs 00026 // 00027 // Martin Fuchs, 02.10.2003 00028 // 00029 00030 00031 #include <precomp.h> 00032 00033 #include "../resource.h" 00034 00035 #include "searchprogram.h" 00036 00037 00038 int CollectProgramsThread::Run() 00039 { 00040 try { 00041 collect_programs(SpecialFolderPath(CSIDL_COMMON_PROGRAMS, _hwnd)); 00042 } catch(COMException&) { 00043 } 00044 00045 if (_alive) 00046 try { 00047 collect_programs(SpecialFolderPath(CSIDL_PROGRAMS, _hwnd)); 00048 } catch(COMException&) { 00049 } 00050 00051 if (_alive) 00052 _cache_valid = true; 00053 00054 return 0; 00055 } 00056 00057 void CollectProgramsThread::collect_programs(const ShellPath& path) 00058 { 00059 ShellDirectory* dir = new ShellDirectory(GetDesktopFolder(), path, 0); 00060 _dirs.push(dir); 00061 00062 dir->smart_scan(SORT_NONE); 00063 00064 for(Entry*entry=dir->_down; _alive && entry; entry=entry->_next) { 00065 if (entry->_shell_attribs & SFGAO_HIDDEN) 00066 continue; 00067 00068 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00069 collect_programs(entry->create_absolute_pidl()); 00070 else if (entry->_shell_attribs & SFGAO_LINK) 00071 if (_alive) 00072 _callback(entry, _para); 00073 } 00074 } 00075 00076 void CollectProgramsThread::free_dirs() 00077 { 00078 while(!_dirs.empty()) { 00079 ShellDirectory* dir = _dirs.top(); 00080 dir->free_subentries(); 00081 _dirs.pop(); 00082 } 00083 } 00084 00085 00086 #ifdef _MSC_VER 00087 #pragma warning(disable: 4355) 00088 #endif 00089 00090 FindProgramDlg::FindProgramDlg(HWND hwnd) 00091 : super(hwnd), 00092 _list_ctrl(GetDlgItem(hwnd, IDC_PROGRAMS_FOUND)), 00093 _thread(collect_programs_callback, hwnd, this), 00094 _sort(_list_ctrl, CompareFunc/*, (LPARAM)this*/) 00095 { 00096 TCHAR szTemp[256]; 00097 const size_t nChars = sizeof(szTemp)/sizeof(*szTemp); 00098 SetWindowIcon(hwnd, IDI_SEARCH); 00099 00100 _resize_mgr.Add(IDC_FILTER, RESIZE_X); 00101 _resize_mgr.Add(IDC_CHECK_ENTRIES, MOVE_X); 00102 _resize_mgr.Add(IDC_PROGRAMS_FOUND, RESIZE); 00103 00104 _resize_mgr.Resize(+520, +300); 00105 00106 _haccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_SEARCH_PROGRAM)); 00107 00108 (void)ListView_SetImageList(_list_ctrl, g_Globals._icon_cache.get_sys_imagelist(), LVSIL_SMALL); 00109 00110 LV_COLUMN column = {LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 250}; 00111 00112 LoadString(g_Globals._hInstance, IDS_NAMECOLUMN, szTemp, nChars); 00113 column.pszText = szTemp; 00114 ListView_InsertColumn(_list_ctrl, 0, &column); 00115 00116 column.cx = 300; 00117 LoadString(g_Globals._hInstance, IDS_PATHCOLUMN, szTemp, nChars); 00118 column.pszText = szTemp; 00119 ListView_InsertColumn(_list_ctrl, 1, &column); 00120 00121 column.cx = 400; 00122 LoadString(g_Globals._hInstance, IDS_MENUCOLUMN, szTemp, nChars); 00123 column.pszText = szTemp; 00124 ListView_InsertColumn(_list_ctrl, 2, &column); 00125 00126 ListView_SetExtendedListViewStyleEx(_list_ctrl, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); 00127 00128 _common_programs = SpecialFolderFSPath(CSIDL_COMMON_PROGRAMS, hwnd); 00129 if (!_common_programs.empty()) 00130 _common_programs.append(_T("\\")); 00131 00132 _user_programs = SpecialFolderFSPath(CSIDL_PROGRAMS, hwnd); 00133 if (!_user_programs.empty()) 00134 _user_programs.append(_T("\\")); 00135 00136 CenterWindow(hwnd); 00137 00138 Refresh(); 00139 00140 register_pretranslate(hwnd); 00141 } 00142 00143 FindProgramDlg::~FindProgramDlg() 00144 { 00145 _thread.Stop(); 00146 00147 unregister_pretranslate(_hwnd); 00148 } 00149 00150 00151 void FindProgramDlg::Refresh(bool delete_cache) 00152 { 00153 WaitCursor wait; 00154 00155 _thread.Stop(); 00156 00157 TCHAR buffer[1024]; 00158 GetWindowText(GetDlgItem(_hwnd, IDC_FILTER), buffer, COUNTOF(buffer)); 00159 CharLower(buffer); 00160 _lwr_filter = buffer; 00161 00162 HiddenWindow hide_listctrl(_list_ctrl); 00163 00164 ListView_DeleteAllItems(_list_ctrl); 00165 00166 if (delete_cache || !_thread._cache_valid) { 00167 _thread.free_dirs(); 00168 _thread.Start(); 00169 } else { 00170 for(FPDCache::const_iterator it=_cache.begin(); it!=_cache.end(); ++it) 00171 add_entry(*it); 00172 } 00173 } 00174 00175 void FindProgramDlg::collect_programs_callback(Entry* entry, void* param) 00176 { 00177 FindProgramDlg* pThis = (FindProgramDlg*) param; 00178 00179 IShellLink* pShellLink; 00180 HRESULT hr = entry->GetUIObjectOf(pThis->_hwnd, IID_IShellLink, (LPVOID*)&pShellLink); 00181 00182 if (SUCCEEDED(hr)) { 00183 ShellLinkPtr shell_link(pShellLink); 00184 00185 shell_link->Release(); 00186 00187 /*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI); 00188 if (SUCCEEDED(hr))*/ { 00189 WIN32_FIND_DATA wfd; 00190 TCHAR path[MAX_PATH]; 00191 00192 hr = pShellLink->GetPath(path, COUNTOF(path)-1, &wfd, SLGP_UNCPRIORITY); 00193 00194 if (SUCCEEDED(hr)) { 00195 TCHAR entry_path[MAX_PATH]; 00196 00197 entry->get_path(entry_path, COUNTOF(entry_path)); 00198 00199 String menu_path; 00200 00201 int len = pThis->_common_programs.size(); 00202 00203 if (len && !_tcsnicmp(entry_path, pThis->_common_programs, len)) 00204 menu_path = ResString(IDS_ALL_USERS) + (String(entry_path)+len); 00205 else if ((len=pThis->_user_programs.size()) && !_tcsnicmp(entry_path, pThis->_user_programs, len)) 00206 menu_path = String(entry_path)+len; 00207 00208 // store info in cache 00209 FPDEntry new_entry; 00210 00211 new_entry._entry = entry; 00212 new_entry._menu_path = menu_path; 00213 new_entry._path = path; 00214 new_entry._idxIcon = I_IMAGECALLBACK; 00215 00216 pThis->_cache.push_front(new_entry); 00217 FPDEntry& cache_entry = pThis->_cache.front(); 00218 00219 Lock lock(pThis->_thread._crit_sect); 00220 00221 // resolve deadlocks while executing Thread::Stop() 00222 if (!pThis->_thread.is_alive()) 00223 return; 00224 00225 pThis->add_entry(cache_entry); 00226 } 00227 } 00228 } 00229 } 00230 00231 void FindProgramDlg::add_entry(const FPDEntry& cache_entry) 00232 { 00233 String lwr_path = cache_entry._path; 00234 String lwr_name = cache_entry._entry->_display_name; 00235 00236 lwr_path.toLower(); 00237 lwr_name.toLower(); 00238 00239 if (_lwr_filter.empty()) 00240 if (_tcsstr(lwr_name, _T("uninstal")) || _tcsstr(lwr_name, _T("deinstal"))) // filter out deinstallation links 00241 return; 00242 00243 if (!_tcsstr(lwr_path, _lwr_filter) && !_tcsstr(lwr_name, _lwr_filter)) 00244 return; 00245 00246 LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX}; 00247 00248 item.pszText = cache_entry._entry->_display_name; 00249 item.iImage = cache_entry._idxIcon; 00250 item.lParam = (LPARAM) &cache_entry; 00251 item.iItem = ListView_InsertItem(_list_ctrl, &item); // We could use the information in _sort to enable manual sorting while populating the list. 00252 00253 item.mask = LVIF_TEXT; 00254 00255 item.iSubItem = 1; 00256 item.pszText = (LPTSTR)(LPCTSTR)cache_entry._path; 00257 ListView_SetItem(_list_ctrl, &item); 00258 00259 item.iSubItem = 2; 00260 item.pszText = (LPTSTR)(LPCTSTR)cache_entry._menu_path; 00261 ListView_SetItem(_list_ctrl, &item); 00262 } 00263 00264 LRESULT FindProgramDlg::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00265 { 00266 switch(nmsg) { 00267 case WM_CLOSE: 00268 (void)ListView_SetImageList(_list_ctrl, 0, LVSIL_SMALL); // detach system image list 00269 goto def; 00270 00271 case PM_TRANSLATE_MSG: { 00272 MSG* pmsg = (MSG*) lparam; 00273 00274 if (TranslateAccelerator(_hwnd, _haccel, pmsg)) 00275 return TRUE; 00276 00277 return FALSE;} 00278 00279 default: def: 00280 return super::WndProc(nmsg, wparam, lparam); 00281 } 00282 00283 return 0; 00284 } 00285 00286 int FindProgramDlg::Command(int id, int code) 00287 { 00288 if (code == BN_CLICKED) { 00289 switch(id) { 00290 case ID_REFRESH: 00291 Refresh(true); 00292 break; 00293 00294 case IDOK: 00295 LaunchSelected(); 00296 break; 00297 00298 case IDC_CHECK_ENTRIES: 00299 CheckEntries(); 00300 break; 00301 00302 default: 00303 return super::Command(id, code); 00304 } 00305 00306 return 0; 00307 } 00308 else if (code == EN_CHANGE) { 00309 switch(id) { 00310 case IDC_FILTER: 00311 Refresh(); 00312 break; 00313 } 00314 00315 return 0; 00316 } 00317 00318 return 1; 00319 } 00320 00321 void FindProgramDlg::LaunchSelected() 00322 { 00323 Lock lock(_thread._crit_sect); 00324 00325 int count = ListView_GetSelectedCount(_list_ctrl); 00326 00327 if (count > 1) 00328 if (MessageBox(_hwnd, ResString(IDS_LAUNCH_MANY_PROGRAMS), ResString(IDS_TITLE), MB_OKCANCEL) != IDOK) 00329 return; 00330 00331 for(int idx=-1; (idx=ListView_GetNextItem(_list_ctrl, idx, LVNI_SELECTED))!=-1; ) { 00332 LPARAM lparam = ListView_GetItemData(_list_ctrl, idx); 00333 00334 if (lparam) { 00335 FPDEntry& cache_entry = *(FPDEntry*)lparam; 00336 cache_entry._entry->launch_entry(_hwnd); 00337 } 00338 } 00339 } 00340 00341 int FindProgramDlg::Notify(int id, NMHDR* pnmh) 00342 { 00343 switch(pnmh->code) { 00344 case LVN_GETDISPINFO: { 00345 LV_DISPINFO* pDispInfo = (LV_DISPINFO*) pnmh; 00346 00347 if (pnmh->hwndFrom == _list_ctrl) { 00348 if (pDispInfo->item.mask & LVIF_IMAGE) { 00349 FPDEntry& cache_entry = *(FPDEntry*)pDispInfo->item.lParam; 00350 Entry* entry = cache_entry._entry; 00351 00352 if (entry->_icon_id == ICID_UNKNOWN) 00353 entry->_icon_id = entry->extract_icon(ICF_SYSCACHE); 00354 00355 pDispInfo->item.iImage = g_Globals._icon_cache.get_icon(entry->_icon_id).get_sysiml_idx(); 00356 pDispInfo->item.mask |= LVIF_DI_SETITEM; 00357 00358 return 1; 00359 } 00360 }} 00361 break; 00362 00363 case NM_DBLCLK: 00364 if (pnmh->hwndFrom == _list_ctrl) 00365 LaunchSelected(); 00366 /*{ 00367 Lock lock(_thread._crit_sect); 00368 00369 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) pnmh; 00370 LPARAM lparam = ListView_GetItemData(pnmh->hwndFrom, pnmv->iItem); 00371 00372 if (lparam) { 00373 FPDEntry& cache_entry = *(FPDEntry*)lparam; 00374 cache_entry._entry->launch_entry(_hwnd); 00375 } 00376 }*/ 00377 break; 00378 00379 case HDN_ITEMCLICK: { 00380 WaitCursor wait; 00381 NMHEADER* phdr = (NMHEADER*)pnmh; 00382 00383 if (GetParent(pnmh->hwndFrom) == _list_ctrl) { 00384 if (_thread._cache_valid) { // disable manual sorting while populating the list 00385 _sort.toggle_sort(phdr->iItem); 00386 _sort.sort(); 00387 } 00388 } 00389 break;} 00390 } 00391 00392 return 0; 00393 } 00394 00395 int CALLBACK FindProgramDlg::CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort) 00396 { 00397 ListSort* sort = (ListSort*)lparamSort; 00398 00399 FPDEntry& a = *(FPDEntry*)lparam1; 00400 FPDEntry& b = *(FPDEntry*)lparam2; 00401 00402 int cmp = 0; 00403 00404 switch(sort->_sort_crit) { 00405 case 0: 00406 cmp = _tcsicoll(a._entry->_display_name, b._entry->_display_name); 00407 break; 00408 00409 case 1: 00410 cmp = _tcsicoll(a._path, b._path); 00411 break; 00412 00413 case 2: 00414 cmp = _tcsicoll(a._menu_path, b._menu_path); 00415 } 00416 00417 return sort->_direction? -cmp: cmp; 00418 } 00419 00420 void FindProgramDlg::CheckEntries() 00421 { 00422 ///@todo check all entries for existing targets, display a list of not working entries and ask the user for permission to delete them 00423 }
ROS Explorer Source Code Documentation
generated on 02.01.2013 by ![]() |