diff --git a/reactos/subsys/system/explorer/dialogs/searchprogram.cpp b/reactos/subsys/system/explorer/dialogs/searchprogram.cpp index ff43aec495c..ae089ea3bbe 100644 --- a/reactos/subsys/system/explorer/dialogs/searchprogram.cpp +++ b/reactos/subsys/system/explorer/dialogs/searchprogram.cpp @@ -95,7 +95,8 @@ FindProgramDlg::FindProgramDlg(HWND hwnd) : super(hwnd), _list_ctrl(GetDlgItem(hwnd, IDC_MAILS_FOUND)), _himl(ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 0, 0)), - _thread(collect_programs_callback, hwnd, this) + _thread(collect_programs_callback, hwnd, this), + _sort(_list_ctrl, CompareFunc/*, (LPARAM)this*/) { SetWindowIcon(hwnd, IDI_REACTOS/*IDI_SEARCH*/); @@ -156,6 +157,8 @@ void FindProgramDlg::Refresh(bool delete_cache) #endif _lwr_filter = buffer; + HiddenWindow hide_listctrl(_list_ctrl); + ListView_DeleteAllItems(_list_ctrl); if (delete_cache || !_thread._cache_valid) { @@ -243,8 +246,7 @@ void FindProgramDlg::add_entry(const FPDEntry& cache_entry) item.pszText = cache_entry._shell_entry->_display_name; item.iImage = cache_entry._idxIcon; item.lParam = (LPARAM) &cache_entry; - - item.iItem = ListView_InsertItem(_list_ctrl, &item); + item.iItem = ListView_InsertItem(_list_ctrl, &item); // We could use the information in _sort to enable manual sorting while populating the list. item.mask = LVIF_TEXT; item.iSubItem = 1; @@ -274,6 +276,10 @@ int FindProgramDlg::Command(int id, int code) Refresh(true); break; + case IDOK: + LaunchSelected(); + break; + default: return super::Command(id, code); } @@ -286,6 +292,23 @@ int FindProgramDlg::Command(int id, int code) return TRUE; } +void FindProgramDlg::LaunchSelected() +{ + Lock lock(_thread._crit_sect); + + int count = ListView_GetSelectedCount(_list_ctrl); + //TODO: ask user if there are many selected items + + for(int idx=-1; (idx=ListView_GetNextItem(_list_ctrl, idx, LVNI_SELECTED))!=-1; ) { + LPARAM lparam = ListView_GetItemData(_list_ctrl, idx); + + if (lparam) { + FPDEntry& cache_entry = *(FPDEntry*)lparam; + cache_entry._shell_entry->launch_entry(_hwnd); + } + } +} + int FindProgramDlg::Notify(int id, NMHDR* pnmh) { switch(pnmh->code) { @@ -307,16 +330,59 @@ int FindProgramDlg::Notify(int id, NMHDR* pnmh) }*/} break; - case NM_DBLCLK: { - LPNMLISTVIEW pnmv = (LPNMLISTVIEW) pnmh; - LPARAM lparam = ListView_GetItemData(pnmh->hwndFrom, pnmv->iItem); + case NM_DBLCLK: + if (pnmh->hwndFrom == _list_ctrl) + LaunchSelected(); + /*{ + Lock lock(_thread._crit_sect); - if (lparam) { - FPDEntry& cache_entry = *(FPDEntry*)lparam; - cache_entry._shell_entry->launch_entry(_hwnd); + LPNMLISTVIEW pnmv = (LPNMLISTVIEW) pnmh; + LPARAM lparam = ListView_GetItemData(pnmh->hwndFrom, pnmv->iItem); + + if (lparam) { + FPDEntry& cache_entry = *(FPDEntry*)lparam; + cache_entry._shell_entry->launch_entry(_hwnd); + } + }*/ + break; + + case HDN_ITEMCLICK: { + WaitCursor wait; + NMHEADER* phdr = (NMHEADER*)pnmh; + + if (GetParent(pnmh->hwndFrom) == _list_ctrl) { + if (_thread._cache_valid) { // disable manual sorting while populating the list + _sort.toggle_sort(phdr->iItem); + _sort.sort(); + } } break;} } return 0; } + +int CALLBACK FindProgramDlg::CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort) +{ + ListSort* sort = (ListSort*)lparamSort; + + FPDEntry& a = *(FPDEntry*)lparam1; + FPDEntry& b = *(FPDEntry*)lparam2; + + int cmp = 0; + + switch(sort->_sort_crit) { + case 0: + cmp = _tcsicoll(a._shell_entry->_display_name, b._shell_entry->_display_name); + break; + + case 1: + cmp = _tcsicoll(a._path, b._path); + break; + + case 2: + cmp = _tcsicoll(a._menu_path, b._menu_path); + } + + return sort->_direction? -cmp: cmp; +} diff --git a/reactos/subsys/system/explorer/dialogs/searchprogram.h b/reactos/subsys/system/explorer/dialogs/searchprogram.h index b1ca21673a8..33c15ef4f0d 100644 --- a/reactos/subsys/system/explorer/dialogs/searchprogram.h +++ b/reactos/subsys/system/explorer/dialogs/searchprogram.h @@ -94,12 +94,16 @@ protected: String _common_programs, _user_programs; + ListSort _sort; + virtual LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam); virtual int Command(int id, int code); virtual int Notify(int id, NMHDR* pnmh); void Refresh(bool delete_cache=false); void add_entry(const FPDEntry& cache_entry); + void LaunchSelected(); static void collect_programs_callback(ShellFolder& folder, ShellEntry* entry, void* param); + static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort); }; diff --git a/reactos/subsys/system/explorer/explorer_intres.rc b/reactos/subsys/system/explorer/explorer_intres.rc index eae407b40b3..f40df1349c7 100644 --- a/reactos/subsys/system/explorer/explorer_intres.rc +++ b/reactos/subsys/system/explorer/explorer_intres.rc @@ -569,7 +569,7 @@ EXSTYLE WS_EX_APPWINDOW CAPTION "Search Program in Startmenu" FONT 8, "MS Sans Serif" BEGIN - LTEXT "Filter:",IDC_STATIC,7,9,18,8 + LTEXT "&Filter:",IDC_STATIC,7,9,18,8 EDITTEXT IDC_TOPIC,34,7,103,14,ES_AUTOHSCROLL CONTROL "List1",IDC_MAILS_FOUND,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index be22968daa1..a3e8afecf16 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -128,6 +128,21 @@ protected: }; +struct HiddenWindow : public WindowHandle +{ + HiddenWindow(HWND hwnd) + : WindowHandle(hwnd) + { + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER); + } + + ~HiddenWindow() + { + SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER); + } +}; + + /// critical section wrapper struct CritSect : public CRITICAL_SECTION diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index 659309d5df8..4c2ff12c6f3 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -897,3 +897,35 @@ ToolTip::ToolTip(HWND owner) { activate(); } + + +ListSort::ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct) + : WindowHandle(hwndListview), + _compare_fct(compare_fct) +{ + _sort_crit = 0; + _direction = false; +} + +void ListSort::toggle_sort(int idx) +{ + if (_sort_crit == idx) + _direction = !_direction; + else { + _sort_crit = idx; + _direction = false; + } +} + +void ListSort::sort() +{ + int idx = ListView_GetSelectionMark(_hwnd); + LPARAM param = ListView_GetItemData(_hwnd, idx); + + ListView_SortItems(_hwnd, _compare_fct, (LPARAM)this); + + if (idx >= 0) { + idx = ListView_FindItemPara(_hwnd, param); + ListView_EnsureVisible(_hwnd, idx, FALSE); + } +} diff --git a/reactos/subsys/system/explorer/utility/window.h b/reactos/subsys/system/explorer/utility/window.h index 89d82a3ac54..e53d00bdf75 100644 --- a/reactos/subsys/system/explorer/utility/window.h +++ b/reactos/subsys/system/explorer/utility/window.h @@ -641,3 +641,41 @@ inline int ListView_GetItemData(HWND list_ctrl, int idx) return item.lParam; } + +inline int ListView_FindItemPara(HWND list_ctrl, LPARAM param) +{ + LVFINDINFO fi; + + fi.flags = LVFI_PARAM; + fi.lParam = param; + + return ListView_FindItem(list_ctrl, -1, &fi); +} + +inline int ListView_GetFocusedItem(HWND list_ctrl) +{ + int idx = ListView_GetItemCount(list_ctrl); + + while(--idx >= 0) + if (ListView_GetItemState(list_ctrl, idx, LVIS_FOCUSED)) + break; + + return idx; +} + + +struct ListSort : public WindowHandle +{ + ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct); + + void toggle_sort(int idx); + void sort(); + + int _sort_crit; + bool _direction; + +protected: + PFNLVCOMPARE _compare_fct; + + static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort); +};