* caching of searched start menu entries

* launch by double click

svn path=/trunk/; revision=6355
This commit is contained in:
Martin Fuchs 2003-10-18 13:35:40 +00:00
parent d8255ef3ba
commit e9c87d778a
10 changed files with 284 additions and 92 deletions

View file

@ -49,38 +49,49 @@ int CollectProgramsThread::Run()
} catch(COMException&) {
}
if (_alive)
_cache_valid = true;
return 0;
}
void CollectProgramsThread::collect_programs(const ShellPath& path)
{
ShellDirectory dir(Desktop(), path, 0);
ShellDirectory* dir = new ShellDirectory(Desktop(), path, 0);
_dirs.push(dir);
dir.smart_scan();
dir->smart_scan();
for(const Entry*entry=dir._down; entry; entry=entry->_next) {
for(Entry*entry=dir->_down; entry; entry=entry->_next) {
if (!_alive)
break;
if (entry->_shell_attribs & SFGAO_HIDDEN)
continue;
const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry);
ShellEntry* shell_entry = static_cast<ShellEntry*>(entry);
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
collect_programs(shell_entry->create_absolute_pidl());
else if (entry->_shell_attribs & SFGAO_LINK)
if (_alive)
_callback(dir._folder, shell_entry, _para);
_callback(dir->_folder, shell_entry, _para);
}
}
dir.free_subentries();
void CollectProgramsThread::free_dirs()
{
while(!_dirs.empty()) {
ShellDirectory* dir = _dirs.top();
dir->free_subentries();
_dirs.pop();
}
}
#pragma warning(disable: 4355)
FindProgramTopicDlg::FindProgramTopicDlg(HWND hwnd)
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)),
@ -103,22 +114,36 @@ FindProgramTopicDlg::FindProgramTopicDlg(HWND hwnd)
column.pszText = _T("Name");
ListView_InsertColumn(_list_ctrl, 0, &column);
column.cx = 400;
column.cx = 300;
column.pszText = _T("Path");
ListView_InsertColumn(_list_ctrl, 1, &column);
column.cx = 400;
column.pszText = _T("Menu Path");
ListView_InsertColumn(_list_ctrl, 2, &column);
ListView_SetExtendedListViewStyleEx(_list_ctrl, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
_common_programs = SpecialFolderFSPath(CSIDL_COMMON_PROGRAMS, hwnd);
if (!_common_programs.empty())
_common_programs.append(_T("\\"));
_user_programs = SpecialFolderFSPath(CSIDL_PROGRAMS, hwnd);
if (!_user_programs.empty())
_user_programs.append(_T("\\"));
CenterWindow(hwnd);
Refresh();
}
FindProgramTopicDlg::~FindProgramTopicDlg()
FindProgramDlg::~FindProgramDlg()
{
ImageList_Destroy(_himl);
}
void FindProgramTopicDlg::Refresh()
void FindProgramDlg::Refresh(bool delete_cache)
{
WaitCursor wait;
@ -126,82 +151,112 @@ void FindProgramTopicDlg::Refresh()
TCHAR buffer[1024];
GetWindowText(GetDlgItem(_hwnd, IDC_TOPIC), buffer, 1024);
_filter = buffer;
#ifndef __WINE__ //TODO
_tcslwr(buffer);
#endif
_lwr_filter = buffer;
ListView_DeleteAllItems(_list_ctrl);
_thread.Start();
if (delete_cache || !_thread._cache_valid) {
_thread.free_dirs();
_thread.Start();
} else {
for(FPDCache::const_iterator it=_cache.begin(); it!=_cache.end(); ++it)
add_entry(*it);
}
}
void FindProgramTopicDlg::collect_programs_callback(ShellFolder& folder, const ShellEntry* entry, void* param)
void FindProgramDlg::collect_programs_callback(ShellFolder& folder, ShellEntry* shell_entry, void* param)
{
LPCITEMIDLIST pidl = entry->_pidl;
FindProgramDlg* pThis = (FindProgramDlg*) param;
LPCITEMIDLIST pidl = shell_entry->_pidl;
IShellLink* pShellLink;
HRESULT hr = folder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
if (SUCCEEDED(hr)) {
WIN32_FIND_DATA wfd;
ShellLinkPtr shell_link(pShellLink);
/*hr = pShellLink->Resolve(_hwnd, SLR_NO_UI);
if (SUCCEEDED(NOERROR))*/ {
/*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI);
if (SUCCEEDED(hr))*/ {
WIN32_FIND_DATA wfd;
TCHAR path[MAX_PATH];
hr = pShellLink->GetPath(path, MAX_PATH-1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY);
if (SUCCEEDED(hr)) {
FindProgramTopicDlg* pThis = (FindProgramTopicDlg*) param;
FileSysShellPath entry_path(shell_entry->create_absolute_pidl());
String menu_path;
String lwr_path = path;
String lwr_name = entry->_display_name;
String filter = pThis->_filter;
int len = pThis->_common_programs.size();
if (len && !_tcsnicmp(entry_path, pThis->_common_programs, len))
menu_path = ResString(IDS_ALL_USERS) + (String(entry_path)+len);
else if ((len=pThis->_user_programs.size()) && !_tcsnicmp(entry_path, pThis->_user_programs, len))
menu_path = String(entry_path)+len;
#ifndef __WINE__ //TODO
_tcslwr((LPTSTR)lwr_path.c_str());
_tcslwr((LPTSTR)lwr_name.c_str());
_tcslwr((LPTSTR)filter.c_str());
#endif
// store info in cache
FPDEntry new_entry;
//if (_tcsstr(lwr_path, _T(".exe"))) //@@ filter on ".exe" suffix
//if (!_tcsstr(lwr_name, _T("uninstal")) && !_tcsstr(lwr_name, _T("deinstal"))) //@@ filter out deinstallation links
if (_tcsstr(lwr_path, filter) || _tcsstr(lwr_name, filter)) {
LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX};
new_entry._shell_entry = shell_entry;
new_entry._menu_path = menu_path;
new_entry._path = path;
item.pszText = entry->_display_name;
if (shell_entry->_hIcon != (HICON)-1)
new_entry._idxIcon = ImageList_AddIcon(pThis->_himl, shell_entry->_hIcon);
else
new_entry._idxIcon = pThis->_idxNoIcon;
if (entry->_hIcon != (HICON)-1)
item.iImage = ImageList_AddIcon(pThis->_himl, entry->_hIcon);
else
item.iImage = pThis->_idxNoIcon;
pThis->_cache.push_front(new_entry);
FPDEntry& cache_entry = pThis->_cache.front();
item.lParam = 0; //@@
Lock lock(pThis->_thread._crit_sect);
//TODO: store info in ShellPathWithFolder
// resolve deadlocks while executing Thread::Stop()
if (!pThis->_thread.is_alive())
return;
Lock lock(pThis->_thread._crit_sect);
// resolve deadlocks while executing Thread::Stop()
if (!pThis->_thread.is_alive())
return;
item.iItem = ListView_InsertItem(pThis->_list_ctrl, &item);
item.mask = LVIF_TEXT;
item.iSubItem = 1;
item.pszText = path;
if (!pThis->_thread.is_alive())
return;
ListView_SetItem(pThis->_list_ctrl, &item);
}
pThis->add_entry(cache_entry);
}
}
}
pShellLink->Release();
}
LRESULT FindProgramTopicDlg::WndProc(UINT message, WPARAM wparam, LPARAM lparam)
void FindProgramDlg::add_entry(const FPDEntry& cache_entry)
{
String lwr_path = cache_entry._path;
String lwr_name = cache_entry._shell_entry->_display_name;
#ifndef __WINE__ //TODO
_tcslwr((LPTSTR)lwr_path.c_str());
_tcslwr((LPTSTR)lwr_name.c_str());
#endif
if (_lwr_filter.empty())
if (_tcsstr(lwr_name, _T("uninstal")) || _tcsstr(lwr_name, _T("deinstal"))) // filter out deinstallation links
return;
if (!_tcsstr(lwr_path, _lwr_filter) && !_tcsstr(lwr_name, _lwr_filter))
return;
LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX};
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.mask = LVIF_TEXT;
item.iSubItem = 1;
item.pszText = (LPTSTR)(LPCTSTR)cache_entry._path;
ListView_SetItem(_list_ctrl, &item);
item.iSubItem = 2;
item.pszText = (LPTSTR)(LPCTSTR)cache_entry._menu_path;
ListView_SetItem(_list_ctrl, &item);
}
LRESULT FindProgramDlg::WndProc(UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message) {
default:
@ -211,12 +266,12 @@ LRESULT FindProgramTopicDlg::WndProc(UINT message, WPARAM wparam, LPARAM lparam)
return FALSE;
}
int FindProgramTopicDlg::Command(int id, int code)
int FindProgramDlg::Command(int id, int code)
{
if (code == BN_CLICKED)
switch(id) {
case ID_REFRESH:
Refresh();
Refresh(true);
break;
default:
@ -231,14 +286,13 @@ int FindProgramTopicDlg::Command(int id, int code)
return TRUE;
}
int FindProgramTopicDlg::Notify(int id, NMHDR* pnmh)
int FindProgramDlg::Notify(int id, NMHDR* pnmh)
{
switch(pnmh->code) {
case LVN_GETDISPINFO: {
case LVN_GETDISPINFO: {/*
LV_DISPINFO* pDispInfo = (LV_DISPINFO*) pnmh;
if (pnmh->hwndFrom == _list_ctrl) {
/*
if (pDispInfo->item.mask & LVIF_IMAGE) {
int icon;
HRESULT hr = pShellLink->GetIconLocation(path, MAX_PATH-1, &icon);
@ -250,9 +304,18 @@ int FindProgramTopicDlg::Notify(int id, NMHDR* pnmh)
return 1;
}
*/
}*/}
break;
case NM_DBLCLK: {
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;}
break;}
}
return 0;

View file

@ -27,61 +27,79 @@
// Martin Fuchs, 02.10.2003
//
struct ShellPathWithFolder
{
ShellPathWithFolder(const ShellFolder& folder, const ShellPath& path)
: _folder(folder), _path(path) {}
ShellFolder _folder;
ShellPath _path;
};
#include <stack>
typedef void (*COLLECT_CALLBACK)(ShellFolder& folder, const ShellEntry* entry, void* param);
typedef void (*COLLECT_CALLBACK)(ShellFolder& folder, ShellEntry* shell_entry, void* param);
typedef stack<ShellDirectory*> ShellDirectoryStack;
struct CollectProgramsThread : public Thread
{
CollectProgramsThread(COLLECT_CALLBACK callback, HWND hwnd, void* para)
: _callback(callback),
: _cache_valid(false),
_callback(callback),
_hwnd(hwnd),
_para(para)
{
}
int Run();
~CollectProgramsThread()
{
free_dirs();
}
int Run();
void free_dirs();
bool _cache_valid;
protected:
COLLECT_CALLBACK _callback;
HWND _hwnd;
void* _para;
ShellDirectoryStack _dirs;
void CollectProgramsThread::collect_programs(const ShellPath& path);
void collect_programs(const ShellPath& path);
};
struct FindProgramTopicDlg : public ResizeController<Dialog>
struct FPDEntry
{
ShellEntry* _shell_entry;
int _idxIcon;
String _menu_path;
String _path;
};
typedef list<FPDEntry> FPDCache;
struct FindProgramDlg : public ResizeController<Dialog>
{
typedef ResizeController<Dialog> super;
FindProgramTopicDlg(HWND hwnd);
~FindProgramTopicDlg();
FindProgramDlg(HWND hwnd);
~FindProgramDlg();
protected:
CommonControlInit _usingCmnCtrl;
HWND _list_ctrl;
HACCEL _haccel;
HIMAGELIST _himl;
int _idxNoIcon; // Ersatzicon für Links ohne Symbole
String _filter;
int _idxNoIcon; // replacement icon
String _lwr_filter;
CollectProgramsThread _thread;
FPDCache _cache;
String _common_programs, _user_programs;
virtual LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam);
virtual int Command(int id, int code);
virtual int Command(int id, int code);
virtual int Notify(int id, NMHDR* pnmh);
void Refresh();
void Refresh(bool delete_cache=false);
void add_entry(const FPDEntry& cache_entry);
static void collect_programs_callback(ShellFolder& folder, const ShellEntry* entry, void* param);
static void collect_programs_callback(ShellFolder& folder, ShellEntry* entry, void* param);
};

View file

@ -26,6 +26,7 @@
#define IDS_PRINTERS 22
#define IDS_BROWSE 23
#define IDS_SEARCH_PRG 24
#define IDS_ALL_USERS 25
#define IDI_REACTOS 100
#define IDI_EXPLORER 101
#define IDI_STARTMENU 102
@ -77,6 +78,7 @@
#define ID_FILE_EXIT 0xE141
#define ID_HELP_USING 0xE144
#define ID_HELP 0xE146
#define IDC_STATIC -1
// Next default values for new objects
//

View file

@ -112,6 +112,7 @@ BEGIN
IDS_PRINTERS "Printers"
IDS_BROWSE "Browse Files..."
IDS_SEARCH_PRG "Search Programm..."
IDS_ALL_USERS "All Users\\"
END
#endif // Romanian resources
@ -381,6 +382,7 @@ BEGIN
IDS_PRINTERS "Drucker"
IDS_BROWSE "Dateien..."
IDS_SEARCH_PRG "Suche Programm..."
IDS_ALL_USERS "Alle Benutzer\\"
END
#endif // German (Germany) resources
@ -565,11 +567,13 @@ STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Search Program in Startmenu"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_TOPIC,7,7,130,14,ES_AUTOHSCROLL
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 | WS_BORDER | WS_TABSTOP,7,25,130,33
LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER |
WS_TABSTOP,7,25,130,33
END
@ -627,6 +631,7 @@ BEGIN
IDS_PRINTERS "Printers"
IDS_BROWSE "Browse Files..."
IDS_SEARCH_PRG "Search Programm..."
IDS_ALL_USERS "All Users\\"
END
#endif // English (U.S.) resources

View file

@ -788,7 +788,7 @@ int StartMenuRoot::Command(int id, int code)
case IDC_SEARCH_PROGRAM:
CloseStartMenu(id);
Dialog::DoModal(IDD_SEARCH_PROGRAM, WINDOW_CREATOR(FindProgramTopicDlg));
Dialog::DoModal(IDD_SEARCH_PROGRAM, WINDOW_CREATOR(FindProgramDlg));
break;
case IDC_EXPLORE:

View file

@ -162,7 +162,7 @@ ShellFolder::ShellFolder()
}
ShellFolder::ShellFolder(IShellFolder* p)
: IShellFolderPtr(p)
: super(p)
{
p->AddRef();
}
@ -220,7 +220,7 @@ ShellFolder::ShellFolder()
}
ShellFolder::ShellFolder(IShellFolder* p)
: SIfacePtr<IShellFolder>(p)
: super(p)
{
_p->AddRef();
}

View file

@ -392,6 +392,25 @@ struct ShellFolder : public IShellFolderPtr // IShellFolderPtr uses intrinsic ex
bool empty() const {return !operator bool();} //NOTE: see SIfacePtr::empty()
};
#ifdef UNICODE
#define IShellLinkPtr IShellLinkWPtr
#else
#define IShellLinkPtr IShellLinkAPtr
#endif
struct ShellLinkPtr : public IShellLinkPtr
{
typedef IShellLinkPtr super;
ShellLinkPtr(IShellLink* p)
: super(p)
{
p->AddRef();
}
bool empty() const {return !operator bool();} //NOTE: see SIfacePtr::empty()
};
#else // _com_ptr not available -> use SIfacePtr
struct ShellFolder : public SIfacePtr<IShellFolder>
@ -407,6 +426,18 @@ struct ShellFolder : public SIfacePtr<IShellFolder>
String get_name(LPCITEMIDLIST pidl, SHGDNF flags=SHGDN_NORMAL) const;
};
struct ShellLinkPtr : public SIfacePtr<IShellLink>
{
typedef SIfacePtr<IShellLink> super;
ShellLinkPtr(IShellLink* p)
: super(p)
{
_p->AddRef();
}
};
#endif

View file

@ -44,6 +44,55 @@ DWORD WINAPI Thread::ThreadProc(void* para)
}
void CenterWindow(HWND hwnd)
{
RECT rt, prt;
GetWindowRect(hwnd, &rt);
DWORD style;
HWND owner = 0;
for(HWND wh=hwnd; (wh=GetWindow(wh,GW_OWNER))!=0; )
if (((style=GetWindowStyle(wh))&WS_VISIBLE) && !(style&WS_MINIMIZE))
{owner=wh; break;}
if (owner)
GetWindowRect(owner, &prt);
else
SystemParametersInfo(SPI_GETWORKAREA, 0, &prt, 0); //@@ GetDesktopWindow() wäre auch hilfreich.
SetWindowPos(hwnd, 0, (prt.left+prt.right+rt.left-rt.right)/2,
(prt.top+prt.bottom+rt.top-rt.bottom)/2, 0,0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
MoveVisible(hwnd);
}
void MoveVisible(HWND hwnd)
{
RECT rc;
GetWindowRect(hwnd, &rc);
int left=rc.left, top=rc.top;
int xmax = GetSystemMetrics(SM_CXSCREEN);
int ymax = GetSystemMetrics(SM_CYSCREEN);
if (rc.left < 0)
rc.left = 0;
else if (rc.right > xmax)
if ((rc.left-=rc.right-xmax) < 0)
rc.left = 0;
if (rc.top < 0)
rc.top = 0;
else if (rc.bottom > ymax)
if ((rc.top-=rc.bottom-ymax) < 0)
rc.top = 0;
if (rc.left!=left || rc.top!=top)
SetWindowPos(hwnd, 0, rc.left,rc.top, 0,0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
}
void display_error(HWND hwnd, DWORD error)
{
PTSTR msg;

View file

@ -449,9 +449,12 @@ struct String
String() {}
String(LPCTSTR s) : super(s) {}
String(const super& other) : super(other) {}
String(const String& other) : super(other) {}
String& operator=(LPCTSTR s) {assign(s); return *this;}
String& operator=(const super& s) {assign(s); return *this;}
operator LPCTSTR() const {return c_str();}
};
@ -551,7 +554,14 @@ extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR*
#define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
// display
// center window in respect to its parent window
extern void CenterWindow(HWND hwnd);
// move window into visibility
extern void MoveVisible(HWND hwnd);
// display error message
extern void display_error(HWND hwnd, DWORD error);
// convert time_t to WIN32 FILETIME

View file

@ -627,3 +627,17 @@ struct ToolTip : public WindowHandle
SendMessage(_hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
}
};
inline int ListView_GetItemData(HWND list_ctrl, int idx)
{
LV_ITEM item;
item.mask = LVIF_PARAM;
item.iItem = idx;
if (!ListView_GetItem(list_ctrl, &item))
return 0;
return item.lParam;
}