mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
direct file system access for start menu
svn path=/trunk/; revision=7424
This commit is contained in:
parent
33f1db80ee
commit
398b10102e
16 changed files with 615 additions and 310 deletions
|
@ -60,7 +60,7 @@ void CollectProgramsThread::collect_programs(const ShellPath& path)
|
|||
ShellDirectory* dir = new ShellDirectory(Desktop(), path, 0);
|
||||
_dirs.push(dir);
|
||||
|
||||
dir->smart_scan();
|
||||
dir->smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
|
||||
|
||||
for(Entry*entry=dir->_down; entry; entry=entry->_next) {
|
||||
if (!_alive)
|
||||
|
@ -69,13 +69,14 @@ void CollectProgramsThread::collect_programs(const ShellPath& path)
|
|||
if (entry->_shell_attribs & SFGAO_HIDDEN)
|
||||
continue;
|
||||
|
||||
ShellEntry* shell_entry = static_cast<ShellEntry*>(entry);
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
ShellPath shell_path;
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
collect_programs(shell_entry->create_absolute_pidl());
|
||||
else if (entry->_shell_attribs & SFGAO_LINK)
|
||||
if (get_entry_pidl(entry, shell_path))
|
||||
collect_programs(shell_path);
|
||||
} else if (entry->_shell_attribs & SFGAO_LINK)
|
||||
if (_alive)
|
||||
_callback(dir->_folder, shell_entry, _para);
|
||||
_callback(entry, _para);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,56 +173,70 @@ void FindProgramDlg::Refresh(bool delete_cache)
|
|||
}
|
||||
}
|
||||
|
||||
void FindProgramDlg::collect_programs_callback(ShellFolder& folder, ShellEntry* shell_entry, void* param)
|
||||
void FindProgramDlg::collect_programs_callback(Entry* entry, void* param)
|
||||
{
|
||||
FindProgramDlg* pThis = (FindProgramDlg*) param;
|
||||
LPCITEMIDLIST pidl = shell_entry->_pidl;
|
||||
ShellPath shell_path;
|
||||
|
||||
if (!get_entry_pidl(entry, shell_path))
|
||||
return;
|
||||
|
||||
IShellLink* pShellLink;
|
||||
HRESULT hr = folder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
|
||||
LPCITEMIDLIST pidl_last = NULL;
|
||||
IShellFolder* pFolder;
|
||||
|
||||
HRESULT hr = SHBindToParent(shell_path, IID_IShellFolder, (LPVOID*)&pFolder, &pidl_last);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
ShellLinkPtr shell_link(pShellLink);
|
||||
hr = pFolder->GetUIObjectOf(pThis->_hwnd, 1, &pidl_last, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
|
||||
|
||||
/*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI);
|
||||
if (SUCCEEDED(hr))*/ {
|
||||
WIN32_FIND_DATA wfd;
|
||||
TCHAR path[MAX_PATH];
|
||||
if (SUCCEEDED(hr)) {
|
||||
ShellLinkPtr shell_link(pShellLink);
|
||||
|
||||
hr = pShellLink->GetPath(path, MAX_PATH-1, &wfd, SLGP_UNCPRIORITY);
|
||||
/*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI);
|
||||
if (SUCCEEDED(hr))*/ {
|
||||
WIN32_FIND_DATA wfd;
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
FileSysShellPath entry_path(shell_entry->create_absolute_pidl());
|
||||
String menu_path;
|
||||
hr = pShellLink->GetPath(path, MAX_PATH-1, &wfd, SLGP_UNCPRIORITY);
|
||||
|
||||
int len = pThis->_common_programs.size();
|
||||
if (SUCCEEDED(hr)) {
|
||||
TCHAR entry_path[MAX_PATH];
|
||||
|
||||
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;
|
||||
entry->get_path(entry_path);
|
||||
|
||||
// store info in cache
|
||||
FPDEntry new_entry;
|
||||
String menu_path;
|
||||
|
||||
new_entry._shell_entry = shell_entry;
|
||||
new_entry._menu_path = menu_path;
|
||||
new_entry._path = path;
|
||||
int len = pThis->_common_programs.size();
|
||||
|
||||
if (shell_entry->_hIcon != (HICON)-1)
|
||||
new_entry._idxIcon = ImageList_AddIcon(pThis->_himl, shell_entry->_hIcon);
|
||||
else
|
||||
new_entry._idxIcon = pThis->_idxNoIcon;
|
||||
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;
|
||||
|
||||
pThis->_cache.push_front(new_entry);
|
||||
FPDEntry& cache_entry = pThis->_cache.front();
|
||||
// store info in cache
|
||||
FPDEntry new_entry;
|
||||
|
||||
Lock lock(pThis->_thread._crit_sect);
|
||||
new_entry._entry = entry;
|
||||
new_entry._menu_path = menu_path;
|
||||
new_entry._path = path;
|
||||
|
||||
// resolve deadlocks while executing Thread::Stop()
|
||||
if (!pThis->_thread.is_alive())
|
||||
return;
|
||||
if (entry->_hIcon != (HICON)-1)
|
||||
new_entry._idxIcon = ImageList_AddIcon(pThis->_himl, entry->_hIcon);
|
||||
else
|
||||
new_entry._idxIcon = pThis->_idxNoIcon;
|
||||
|
||||
pThis->add_entry(cache_entry);
|
||||
pThis->_cache.push_front(new_entry);
|
||||
FPDEntry& cache_entry = pThis->_cache.front();
|
||||
|
||||
Lock lock(pThis->_thread._crit_sect);
|
||||
|
||||
// resolve deadlocks while executing Thread::Stop()
|
||||
if (!pThis->_thread.is_alive())
|
||||
return;
|
||||
|
||||
pThis->add_entry(cache_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +245,7 @@ void FindProgramDlg::collect_programs_callback(ShellFolder& folder, ShellEntry*
|
|||
void FindProgramDlg::add_entry(const FPDEntry& cache_entry)
|
||||
{
|
||||
String lwr_path = cache_entry._path;
|
||||
String lwr_name = cache_entry._shell_entry->_display_name;
|
||||
String lwr_name = cache_entry._entry->_display_name;
|
||||
|
||||
#ifndef __WINE__ ///@todo
|
||||
_tcslwr((LPTSTR)lwr_path.c_str());
|
||||
|
@ -246,7 +261,7 @@ void FindProgramDlg::add_entry(const FPDEntry& cache_entry)
|
|||
|
||||
LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX};
|
||||
|
||||
item.pszText = cache_entry._shell_entry->_display_name;
|
||||
item.pszText = cache_entry._entry->_display_name;
|
||||
item.iImage = cache_entry._idxIcon;
|
||||
item.lParam = (LPARAM) &cache_entry;
|
||||
item.iItem = ListView_InsertItem(_list_ctrl, &item); // We could use the information in _sort to enable manual sorting while populating the list.
|
||||
|
@ -297,7 +312,7 @@ void FindProgramDlg::LaunchSelected()
|
|||
|
||||
if (lparam) {
|
||||
FPDEntry& cache_entry = *(FPDEntry*)lparam;
|
||||
cache_entry._shell_entry->launch_entry(_hwnd);
|
||||
cache_entry._entry->launch_entry(_hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +349,7 @@ int FindProgramDlg::Notify(int id, NMHDR* pnmh)
|
|||
|
||||
if (lparam) {
|
||||
FPDEntry& cache_entry = *(FPDEntry*)lparam;
|
||||
cache_entry._shell_entry->launch_entry(_hwnd);
|
||||
cache_entry._entry->launch_entry(_hwnd);
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
|
@ -366,7 +381,7 @@ int CALLBACK FindProgramDlg::CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM
|
|||
|
||||
switch(sort->_sort_crit) {
|
||||
case 0:
|
||||
cmp = _tcsicoll(a._shell_entry->_display_name, b._shell_entry->_display_name);
|
||||
cmp = _tcsicoll(a._entry->_display_name, b._entry->_display_name);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <stack>
|
||||
|
||||
|
||||
typedef void (*COLLECT_CALLBACK)(ShellFolder& folder, ShellEntry* shell_entry, void* param);
|
||||
typedef void (*COLLECT_CALLBACK)(Entry* entry, void* param);
|
||||
typedef stack<ShellDirectory*> ShellDirectoryStack;
|
||||
|
||||
/// Thread for collecting start menu entries
|
||||
|
@ -67,7 +67,7 @@ protected:
|
|||
/// entry for the list in "find program" dialogs
|
||||
struct FPDEntry
|
||||
{
|
||||
ShellEntry* _shell_entry;
|
||||
Entry* _entry;
|
||||
int _idxIcon;
|
||||
String _menu_path;
|
||||
String _path;
|
||||
|
@ -106,6 +106,6 @@ protected:
|
|||
void add_entry(const FPDEntry& cache_entry);
|
||||
void LaunchSelected();
|
||||
|
||||
static void collect_programs_callback(ShellFolder& folder, ShellEntry* entry, void* param);
|
||||
static void collect_programs_callback(Entry* entry, void* param);
|
||||
static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort);
|
||||
};
|
||||
|
|
|
@ -52,3 +52,4 @@ If you search for more information, look into the CVS repository.
|
|||
01.01.2004 m. fuchs integrated icons of Everaldo (http://www.everaldo.com) into the start menu.
|
||||
02.01.2004 m. fuchs reimplemented start menu as light weight version
|
||||
03.01.2004 m. fuchs lazy icon extraction for start menu
|
||||
direct file system access for start menu
|
||||
|
|
|
@ -57,7 +57,7 @@ BSC32=bscmake.exe
|
|||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /machine:I386
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32 Debug"
|
||||
|
@ -82,7 +82,7 @@ BSC32=bscmake.exe
|
|||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32 Debug Release"
|
||||
|
@ -108,7 +108,7 @@ BSC32=bscmake.exe
|
|||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Release"
|
||||
|
@ -134,7 +134,7 @@ BSC32=bscmake.exe
|
|||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /machine:I386
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Debug"
|
||||
|
@ -160,7 +160,7 @@ BSC32=bscmake.exe
|
|||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL"
|
||||
|
@ -187,7 +187,7 @@ BSC32=bscmake.exe
|
|||
LINK32=link.exe
|
||||
# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib shell32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none /force
|
||||
|
||||
!ELSEIF "$(CFG)" == "explorer - Win32"
|
||||
|
|
|
@ -48,9 +48,9 @@ Entry::Entry(ENTRY_TYPE etype)
|
|||
_display_name = _data.cFileName;
|
||||
}
|
||||
|
||||
Entry::Entry(Entry* parent)
|
||||
Entry::Entry(Entry* parent, ENTRY_TYPE etype)
|
||||
: _up(parent),
|
||||
_etype(parent->_etype)
|
||||
_etype(etype)
|
||||
{
|
||||
_next = NULL;
|
||||
_down = NULL;
|
||||
|
@ -126,17 +126,17 @@ Entry* Entry::read_tree(const void* path, SORT_ORDER sortOrder)
|
|||
}
|
||||
|
||||
|
||||
void Entry::read_directory(SORT_ORDER sortOrder, bool read_icons)
|
||||
void Entry::read_directory(SORT_ORDER sortOrder, int scan_flags)
|
||||
{
|
||||
CONTEXT("Entry::read_directory(SORT_ORDER)");
|
||||
|
||||
// call into subclass
|
||||
read_directory(read_icons);
|
||||
read_directory(scan_flags);
|
||||
|
||||
if (g_Globals._prescan_nodes) { //@todo _prescan_nodes should not be used for filling the start menu.
|
||||
if (g_Globals._prescan_nodes) { //@todo _prescan_nodes should not be used for reading the start menu.
|
||||
for(Entry*entry=_down; entry; entry=entry->_next)
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
entry->read_directory(read_icons);
|
||||
entry->read_directory(scan_flags);
|
||||
entry->sort_directory(sortOrder);
|
||||
}
|
||||
}
|
||||
|
@ -284,13 +284,13 @@ void Entry::sort_directory(SORT_ORDER sortOrder)
|
|||
}
|
||||
|
||||
|
||||
void Entry::smart_scan(bool read_icons)
|
||||
void Entry::smart_scan(int scan_flags)
|
||||
{
|
||||
CONTEXT("Entry::smart_scan()");
|
||||
|
||||
if (!_scanned) {
|
||||
free_subentries();
|
||||
read_directory(SORT_NAME, read_icons); // we could use IShellFolder2::GetDefaultColumn to determine sort order
|
||||
read_directory(SORT_NAME, scan_flags); // we could use IShellFolder2::GetDefaultColumn to determine sort order
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,8 @@ BOOL Entry::launch_entry(HWND hwnd, UINT nCmdShow)
|
|||
{
|
||||
TCHAR cmd[MAX_PATH];
|
||||
|
||||
get_path(cmd);
|
||||
if (!get_path(cmd))
|
||||
return FALSE;
|
||||
|
||||
// start program, open document...
|
||||
return launch_file(hwnd, cmd, nCmdShow);
|
||||
|
|
|
@ -41,12 +41,21 @@ enum SORT_ORDER {
|
|||
SORT_DATE
|
||||
};
|
||||
|
||||
enum SCAN_FLAGS {
|
||||
SCAN_EXTRACT_ICONS = 1,
|
||||
SCAN_DO_ACCESS = 2,
|
||||
|
||||
SCAN_ALL = 3,
|
||||
|
||||
SCAN_FILESYSTEM = 4
|
||||
};
|
||||
|
||||
/// base of all file and directory entries
|
||||
struct Entry
|
||||
{
|
||||
protected:
|
||||
Entry(ENTRY_TYPE etype);
|
||||
Entry(Entry* parent);
|
||||
Entry(Entry* parent, ENTRY_TYPE etype);
|
||||
Entry(const Entry&);
|
||||
|
||||
public:
|
||||
|
@ -73,15 +82,15 @@ public:
|
|||
|
||||
void free_subentries();
|
||||
|
||||
void read_directory(SORT_ORDER sortOrder, bool read_icons=true);
|
||||
void read_directory(SORT_ORDER sortOrder, int scan_flags=SCAN_ALL);
|
||||
Entry* read_tree(const void* path, SORT_ORDER sortOrder);
|
||||
void sort_directory(SORT_ORDER sortOrder);
|
||||
void smart_scan(bool read_icons=true);
|
||||
void smart_scan(int scan_flags=SCAN_ALL);
|
||||
|
||||
virtual void read_directory(bool read_icons=true) {}
|
||||
virtual void read_directory(int scan_flags=SCAN_ALL) {}
|
||||
virtual const void* get_next_path_component(const void*) {return NULL;}
|
||||
virtual Entry* find_entry(const void*) {return NULL;}
|
||||
virtual void get_path(PTSTR path) const = 0;
|
||||
virtual bool get_path(PTSTR path) const = 0;
|
||||
virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL);
|
||||
};
|
||||
|
||||
|
|
|
@ -501,14 +501,12 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
|
|||
if (cx > IMAGE_WIDTH)
|
||||
cx = IMAGE_WIDTH;
|
||||
|
||||
if (entry->_hIcon != (HICON)-1) {
|
||||
if (entry->_hIcon)
|
||||
DrawIconEx(dis->hDC, img_pos, dis->rcItem.top, entry->_hIcon, cx, GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
|
||||
else
|
||||
ImageList_DrawEx(_himl, img, dis->hDC,
|
||||
img_pos, dis->rcItem.top, cx,
|
||||
IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
|
||||
}
|
||||
if (entry->_hIcon && entry->_hIcon!=(HICON)-1)
|
||||
DrawIconEx(dis->hDC, img_pos, dis->rcItem.top, entry->_hIcon, cx, GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
|
||||
else
|
||||
ImageList_DrawEx(_himl, img, dis->hDC,
|
||||
img_pos, dis->rcItem.top, cx,
|
||||
IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,11 +211,13 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO
|
|||
if (itemData) {
|
||||
Entry* entry = (Entry*)itemData;
|
||||
|
||||
ShellDirectory* dir = static_cast<ShellDirectory*>(entry->_up);
|
||||
ShellFolder folder = dir? dir->_folder: Desktop();
|
||||
LPCITEMIDLIST pidl = static_cast<ShellEntry*>(entry)->_pidl;
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
ShellDirectory* dir = static_cast<ShellDirectory*>(entry->_up);
|
||||
ShellFolder folder = dir? dir->_folder: Desktop();
|
||||
LPCITEMIDLIST pidl = static_cast<ShellEntry*>(entry)->_pidl;
|
||||
|
||||
CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y));
|
||||
CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,19 +343,21 @@ void ShellBrowserChild::OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv)
|
|||
|
||||
_last_sel = pnmtv->itemNew.hItem;
|
||||
|
||||
IShellFolder* folder;
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
IShellFolder* folder;
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
folder = static_cast<ShellDirectory*>(entry)->_folder;
|
||||
else
|
||||
folder = entry->get_parent_folder();
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
folder = static_cast<ShellDirectory*>(entry)->_folder;
|
||||
else
|
||||
folder = entry->get_parent_folder();
|
||||
|
||||
if (!folder) {
|
||||
assert(folder);
|
||||
return;
|
||||
if (!folder) {
|
||||
assert(folder);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateFolderView(folder);
|
||||
}
|
||||
|
||||
UpdateFolderView(folder);
|
||||
}
|
||||
|
||||
void ShellBrowserChild::UpdateFolderView(IShellFolder* folder)
|
||||
|
@ -456,8 +460,9 @@ HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pida)
|
|||
Entry* entry = parent->find_entry(pidl);
|
||||
|
||||
if (entry && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
|
||||
if (expand_folder(static_cast<ShellDirectory*>(entry)))
|
||||
return S_OK;
|
||||
if (entry->_etype == ET_SHELL)
|
||||
if (expand_folder(static_cast<ShellDirectory*>(entry)))
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
} else { // no tree control
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
|
||||
#include "entries.h"
|
||||
#include "shellfs.h"
|
||||
#include "winfs.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
bool ShellDirectory::fill_w32fdata_shell(LPCITEMIDLIST pidl, SFGAOF attribs, WIN32_FIND_DATA* pw32fdata, BY_HANDLE_FILE_INFORMATION* pbhfi, bool do_access)
|
||||
|
@ -60,7 +63,7 @@ bool ShellDirectory::fill_w32fdata_shell(LPCITEMIDLIST pidl, SFGAOF attribs, WIN
|
|||
LPCTSTR path = (LPCTSTR)GlobalLock(medium.UNION_MEMBER(hGlobal));
|
||||
UINT sem_org = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
// fill out drive names "C:", ...
|
||||
// fill with drive names "C:", ...
|
||||
_tcscpy(pw32fdata->cFileName, path);
|
||||
|
||||
if (GetFileAttributesEx(path, GetFileExInfoStandard, &fad)) {
|
||||
|
@ -111,41 +114,63 @@ ShellPath ShellEntry::create_absolute_pidl() const
|
|||
{
|
||||
CONTEXT("ShellEntry::create_absolute_pidl()");
|
||||
|
||||
if (_up/* && _up->_etype==ET_SHELL*/) {
|
||||
ShellDirectory* dir = static_cast<ShellDirectory*>(_up);
|
||||
if (_up)
|
||||
if (_up->_etype==ET_SHELL) {
|
||||
ShellDirectory* dir = static_cast<ShellDirectory*>(_up);
|
||||
|
||||
if (dir->_pidl->mkid.cb) // Caching of absolute PIDLs could enhance performance.
|
||||
return _pidl.create_absolute_pidl(dir->create_absolute_pidl());
|
||||
}
|
||||
if (dir->_pidl->mkid.cb) // Caching of absolute PIDLs could enhance performance.
|
||||
return _pidl.create_absolute_pidl(dir->create_absolute_pidl());
|
||||
} else {
|
||||
ShellPath shell_path;
|
||||
|
||||
if (get_entry_pidl(_up, shell_path))
|
||||
return _pidl.create_absolute_pidl(shell_path);
|
||||
}
|
||||
|
||||
return _pidl;
|
||||
}
|
||||
|
||||
|
||||
// get full path of a shell entry
|
||||
void ShellEntry::get_path(PTSTR path) const
|
||||
bool ShellEntry::get_path(PTSTR path) const
|
||||
{
|
||||
/*
|
||||
path[0] = TEXT('\0');
|
||||
|
||||
/*HRESULT hr = */path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH);
|
||||
if (FAILED(path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH)))
|
||||
return false;
|
||||
*/
|
||||
FileSysShellPath fs_path(create_absolute_pidl());
|
||||
|
||||
if (!(LPCTSTR)fs_path)
|
||||
return false;
|
||||
|
||||
_tcscpy(path, fs_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// get full path of a shell folder
|
||||
void ShellDirectory::get_path(PTSTR path) const
|
||||
bool ShellDirectory::get_path(PTSTR path) const
|
||||
{
|
||||
CONTEXT("ShellDirectory::get_path()");
|
||||
|
||||
path[0] = TEXT('\0');
|
||||
|
||||
SFGAOF attribs = 0;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!_folder.empty())
|
||||
hr = const_cast<ShellFolder&>(_folder)->GetAttributesOf(1, (LPCITEMIDLIST*)&_pidl, &attribs);
|
||||
if (FAILED(const_cast<ShellFolder&>(_folder)->GetAttributesOf(1, (LPCITEMIDLIST*)&_pidl, &attribs)))
|
||||
return false;
|
||||
|
||||
if (SUCCEEDED(hr) && (attribs&SFGAO_FILESYSTEM))
|
||||
hr = path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH);
|
||||
if (!(attribs & SFGAO_FILESYSTEM))
|
||||
return false;
|
||||
|
||||
if (FAILED(path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,12 +210,12 @@ static HICON extract_icon(IShellFolder* folder, LPCITEMIDLIST pidl)
|
|||
IExtractIcon* pExtract;
|
||||
|
||||
if (SUCCEEDED(folder->GetUIObjectOf(0, 1, (LPCITEMIDLIST*)&pidl, IID_IExtractIcon, 0, (LPVOID*)&pExtract))) {
|
||||
TCHAR path[_MAX_PATH];
|
||||
TCHAR path[MAX_PATH];
|
||||
unsigned flags;
|
||||
HICON hIcon;
|
||||
int idx;
|
||||
|
||||
if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, _MAX_PATH, &idx, &flags))) {
|
||||
if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, MAX_PATH, &idx, &flags))) {
|
||||
if (!(flags & GIL_NOTFILENAME)) {
|
||||
if (idx == -1)
|
||||
idx = 0; // special case for some control panel applications
|
||||
|
@ -234,25 +259,48 @@ static HICON extract_icon(IShellFolder* folder, LPCITEMIDLIST pidl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static HICON extract_icon(IShellFolder* folder, LPCITEMIDLIST pidl, ShellEntry* entry)
|
||||
static HICON extract_icon(IShellFolder* folder, const ShellEntry* entry)
|
||||
{
|
||||
HICON hIcon = extract_icon(folder, pidl);
|
||||
HICON hIcon = extract_icon(folder, entry->_pidl);
|
||||
|
||||
if (!hIcon) {
|
||||
ShellPath pidl_abs = static_cast<ShellEntry*>(entry)->create_absolute_pidl();
|
||||
LPCITEMIDLIST pidl = pidl_abs;
|
||||
|
||||
SHFILEINFO sfi;
|
||||
|
||||
ShellPath pidl_abs = entry->create_absolute_pidl();
|
||||
LPCITEMIDLIST pidl = pidl_abs;
|
||||
|
||||
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON))
|
||||
entry->_hIcon = sfi.hIcon;
|
||||
hIcon = sfi.hIcon;
|
||||
}
|
||||
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
HICON extract_icon(const Entry* entry)
|
||||
{
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry);
|
||||
|
||||
void ShellDirectory::read_directory(bool read_icons)
|
||||
return extract_icon(shell_entry->get_parent_folder(), shell_entry);
|
||||
} else {
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
if (entry->get_path(path)) {
|
||||
SHFILEINFO sfi;
|
||||
|
||||
ShellPath shell_path(path);
|
||||
LPCITEMIDLIST pidl = shell_path;
|
||||
|
||||
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON))
|
||||
return sfi.hIcon;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ShellDirectory::read_directory(int scan_flags)
|
||||
{
|
||||
CONTEXT("ShellDirectory::read_directory()");
|
||||
|
||||
|
@ -264,65 +312,37 @@ void ShellDirectory::read_directory(bool read_icons)
|
|||
/*if (_folder.empty())
|
||||
return;*/
|
||||
|
||||
ShellItemEnumerator enumerator(_folder, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN|SHCONTF_SHAREABLE|SHCONTF_STORAGE);
|
||||
TCHAR buffer[MAX_PATH];
|
||||
|
||||
TCHAR name[MAX_PATH];
|
||||
HRESULT hr_next = S_OK;
|
||||
if ((scan_flags&SCAN_FILESYSTEM) && get_path(buffer)) {
|
||||
Entry* entry;
|
||||
|
||||
do {
|
||||
#define FETCH_ITEM_COUNT 32
|
||||
LPITEMIDLIST pidls[FETCH_ITEM_COUNT];
|
||||
ULONG cnt = 0;
|
||||
ULONG n;
|
||||
LPTSTR p = buffer + _tcslen(buffer);
|
||||
|
||||
memset(pidls, 0, sizeof(pidls));
|
||||
lstrcpy(p, TEXT("\\*"));
|
||||
|
||||
hr_next = enumerator->Next(FETCH_ITEM_COUNT, pidls, &cnt);
|
||||
WIN32_FIND_DATA w32fd;
|
||||
HANDLE hFind = FindFirstFile(buffer, &w32fd);
|
||||
|
||||
/* don't break yet now: Registry Explorer Plugin returns E_FAIL!
|
||||
if (!SUCCEEDED(hr_next))
|
||||
break; */
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
// ignore hidden files (usefull in the start menu)
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
continue;
|
||||
|
||||
if (hr_next == S_FALSE)
|
||||
break;
|
||||
// ignore directory entries "." and ".."
|
||||
if ((w32fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
w32fd.cFileName[0]==TEXT('.') &&
|
||||
(w32fd.cFileName[1]==TEXT('\0') ||
|
||||
(w32fd.cFileName[1]==TEXT('.') && w32fd.cFileName[2]==TEXT('\0'))))
|
||||
continue;
|
||||
|
||||
for(n=0; n<cnt; ++n) {
|
||||
WIN32_FIND_DATA w32fd;
|
||||
BY_HANDLE_FILE_INFORMATION bhfi;
|
||||
bool bhfi_valid = false;
|
||||
|
||||
memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
|
||||
|
||||
SFGAOF attribs_before = ~SFGAO_READONLY & ~SFGAO_VALIDATE;
|
||||
SFGAOF attribs = attribs_before;
|
||||
HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs);
|
||||
bool removeable = false;
|
||||
|
||||
if (SUCCEEDED(hr) && attribs!=attribs_before) {
|
||||
// avoid accessing floppy drives when browsing "My Computer"
|
||||
if (attribs & SFGAO_REMOVABLE) {
|
||||
attribs |= SFGAO_HASSUBFOLDER;
|
||||
removeable = true;
|
||||
} else {
|
||||
DWORD attribs2 = SFGAO_READONLY;
|
||||
|
||||
HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs2);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
attribs |= attribs2;
|
||||
}
|
||||
} else
|
||||
attribs = 0;
|
||||
|
||||
bhfi_valid = fill_w32fdata_shell(pidls[n], attribs, &w32fd, &bhfi, !removeable);
|
||||
|
||||
try {
|
||||
Entry* entry;
|
||||
lstrcpy(p+1, w32fd.cFileName);
|
||||
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
entry = new ShellDirectory(this, pidls[n], _hwnd);
|
||||
entry = new WinDirectory(this, buffer);
|
||||
else
|
||||
entry = new ShellEntry(this, pidls[n]);
|
||||
entry = new WinEntry(this);
|
||||
|
||||
if (!first_entry)
|
||||
first_entry = entry;
|
||||
|
@ -332,21 +352,9 @@ void ShellDirectory::read_directory(bool read_icons)
|
|||
|
||||
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
|
||||
|
||||
if (bhfi_valid)
|
||||
memcpy(&entry->_bhfi, &bhfi, sizeof(BY_HANDLE_FILE_INFORMATION));
|
||||
|
||||
if (SUCCEEDED(name_from_pidl(_folder, pidls[n], name, MAX_PATH, SHGDN_INFOLDER|0x2000/*0x2000=SHGDN_INCLUDE_NONFILESYS*/))) {
|
||||
if (!entry->_data.cFileName[0])
|
||||
_tcscpy(entry->_data.cFileName, name);
|
||||
else if (_tcscmp(entry->_display_name, name))
|
||||
entry->_display_name = _tcsdup(name); // store display name separate from file name; sort display by file name
|
||||
}
|
||||
|
||||
// get display icons for files and virtual objects
|
||||
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
||||
!(attribs & SFGAO_FILESYSTEM)) {
|
||||
if (read_icons) {
|
||||
entry->_hIcon = extract_icon(_folder, pidls[n], static_cast<ShellEntry*>(entry));
|
||||
if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (scan_flags & SCAN_EXTRACT_ICONS) {
|
||||
entry->_hIcon = extract_icon(entry);
|
||||
|
||||
if (!entry->_hIcon)
|
||||
entry->_hIcon = (HICON)-1; // don't try again later
|
||||
|
@ -359,15 +367,166 @@ void ShellDirectory::read_directory(bool read_icons)
|
|||
entry->_expanded = false;
|
||||
entry->_scanned = false;
|
||||
entry->_level = level;
|
||||
entry->_bhfi_valid = false;
|
||||
|
||||
if (scan_flags & SCAN_DO_ACCESS) {
|
||||
HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
if (GetFileInformationByHandle(hFile, &entry->_bhfi))
|
||||
entry->_bhfi_valid = true;
|
||||
|
||||
if (ScanNTFSStreams(entry, hFile))
|
||||
entry->_scanned = true; // There exist named NTFS sub-streams in this file.
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
LPCTSTR ext = _tcsrchr(entry->_data.cFileName, TEXT('.'));
|
||||
|
||||
if (ext) {//@@
|
||||
int len = ext - entry->_data.cFileName;
|
||||
|
||||
entry->_display_name = (LPTSTR) malloc((len+1)*sizeof(TCHAR));
|
||||
_tcsncpy(entry->_display_name, entry->_data.cFileName, len);
|
||||
entry->_display_name[len] = TEXT('\0');
|
||||
}
|
||||
|
||||
DWORD attribs = SFGAO_FILESYSTEM;
|
||||
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
attribs |= SFGAO_FOLDER;
|
||||
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
attribs |= SFGAO_READONLY;
|
||||
|
||||
//if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
// attribs |= SFGAO_HIDDEN;
|
||||
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
||||
attribs |= SFGAO_COMPRESSED;
|
||||
|
||||
if (ext && !_tcsicmp(ext, _T(".lnk")))
|
||||
attribs |= SFGAO_LINK;
|
||||
|
||||
entry->_shell_attribs = attribs;
|
||||
entry->_bhfi_valid = bhfi_valid;
|
||||
|
||||
last = entry;
|
||||
} catch(COMException& e) {
|
||||
HandleException(e, _hwnd);
|
||||
}
|
||||
} while(FindNextFile(hFind, &w32fd));
|
||||
|
||||
FindClose(hFind);
|
||||
}
|
||||
} while(SUCCEEDED(hr_next));
|
||||
|
||||
} else { // !SCAN_FILESYSTEM
|
||||
|
||||
ShellItemEnumerator enumerator(_folder, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN|SHCONTF_SHAREABLE|SHCONTF_STORAGE);
|
||||
|
||||
TCHAR name[MAX_PATH];
|
||||
HRESULT hr_next = S_OK;
|
||||
|
||||
do {
|
||||
#define FETCH_ITEM_COUNT 32
|
||||
LPITEMIDLIST pidls[FETCH_ITEM_COUNT];
|
||||
ULONG cnt = 0;
|
||||
ULONG n;
|
||||
|
||||
memset(pidls, 0, sizeof(pidls));
|
||||
|
||||
hr_next = enumerator->Next(FETCH_ITEM_COUNT, pidls, &cnt);
|
||||
|
||||
/* don't break yet now: Registry Explorer Plugin returns E_FAIL!
|
||||
if (!SUCCEEDED(hr_next))
|
||||
break; */
|
||||
|
||||
if (hr_next == S_FALSE)
|
||||
break;
|
||||
|
||||
for(n=0; n<cnt; ++n) {
|
||||
WIN32_FIND_DATA w32fd;
|
||||
BY_HANDLE_FILE_INFORMATION bhfi;
|
||||
bool bhfi_valid = false;
|
||||
|
||||
memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
|
||||
|
||||
SFGAOF attribs_before = ~SFGAO_READONLY & ~SFGAO_VALIDATE;
|
||||
SFGAOF attribs = attribs_before;
|
||||
HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs);
|
||||
bool removeable = false;
|
||||
|
||||
if (SUCCEEDED(hr) && attribs!=attribs_before) {
|
||||
// avoid accessing floppy drives when browsing "My Computer"
|
||||
if (attribs & SFGAO_REMOVABLE) {
|
||||
attribs |= SFGAO_HASSUBFOLDER;
|
||||
removeable = true;
|
||||
} else if (scan_flags & SCAN_DO_ACCESS) {
|
||||
DWORD attribs2 = SFGAO_READONLY;
|
||||
|
||||
HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs2);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
attribs |= attribs2;
|
||||
}
|
||||
} else
|
||||
attribs = 0;
|
||||
|
||||
bhfi_valid = fill_w32fdata_shell(pidls[n], attribs, &w32fd, &bhfi,
|
||||
(scan_flags&SCAN_DO_ACCESS) && !removeable);
|
||||
|
||||
try {
|
||||
Entry* entry;
|
||||
|
||||
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
entry = new ShellDirectory(this, pidls[n], _hwnd);
|
||||
else
|
||||
entry = new ShellEntry(this, pidls[n]);
|
||||
|
||||
if (!first_entry)
|
||||
first_entry = entry;
|
||||
|
||||
if (last)
|
||||
last->_next = entry;
|
||||
|
||||
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
|
||||
|
||||
if (bhfi_valid)
|
||||
memcpy(&entry->_bhfi, &bhfi, sizeof(BY_HANDLE_FILE_INFORMATION));
|
||||
|
||||
if (SUCCEEDED(name_from_pidl(_folder, pidls[n], name, MAX_PATH, SHGDN_INFOLDER|0x2000/*0x2000=SHGDN_INCLUDE_NONFILESYS*/))) {
|
||||
if (!entry->_data.cFileName[0])
|
||||
_tcscpy(entry->_data.cFileName, name);
|
||||
else if (_tcscmp(entry->_display_name, name))
|
||||
entry->_display_name = _tcsdup(name); // store display name separate from file name; sort display by file name
|
||||
}
|
||||
|
||||
// get icons for files and virtual objects
|
||||
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
||||
!(attribs & SFGAO_FILESYSTEM)) {
|
||||
if (scan_flags & SCAN_EXTRACT_ICONS) {
|
||||
entry->_hIcon = extract_icon(_folder, static_cast<ShellEntry*>(entry));
|
||||
|
||||
if (!entry->_hIcon)
|
||||
entry->_hIcon = (HICON)-1; // don't try again later
|
||||
} else
|
||||
entry->_hIcon = 0;
|
||||
} else
|
||||
entry->_hIcon = (HICON)-1; // don't try again later
|
||||
|
||||
entry->_down = NULL;
|
||||
entry->_expanded = false;
|
||||
entry->_scanned = false;
|
||||
entry->_level = level;
|
||||
entry->_shell_attribs = attribs;
|
||||
entry->_bhfi_valid = bhfi_valid;
|
||||
|
||||
last = entry;
|
||||
} catch(COMException& e) {
|
||||
HandleException(e, _hwnd);
|
||||
}
|
||||
}
|
||||
} while(SUCCEEDED(hr_next));
|
||||
}
|
||||
|
||||
if (last)
|
||||
last->_next = NULL;
|
||||
|
@ -393,12 +552,13 @@ Entry* ShellDirectory::find_entry(const void* p)
|
|||
{
|
||||
LPITEMIDLIST pidl = (LPITEMIDLIST) p;
|
||||
|
||||
for(Entry*entry=_down; entry; entry=entry->_next) {
|
||||
ShellEntry* se = static_cast<ShellEntry*>(entry);
|
||||
for(Entry*entry=_down; entry; entry=entry->_next)
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
ShellEntry* se = static_cast<ShellEntry*>(entry);
|
||||
|
||||
if (se->_pidl && se->_pidl->mkid.cb==pidl->mkid.cb && !memcmp(se->_pidl, pidl, se->_pidl->mkid.cb))
|
||||
return entry;
|
||||
}
|
||||
if (se->_pidl && se->_pidl->mkid.cb==pidl->mkid.cb && !memcmp(se->_pidl, pidl, se->_pidl->mkid.cb))
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -407,18 +567,18 @@ int ShellDirectory::extract_icons()
|
|||
{
|
||||
int cnt = 0;
|
||||
|
||||
for(Entry*entry=_down; entry; entry=entry->_next) {
|
||||
ShellEntry* se = static_cast<ShellEntry*>(entry);
|
||||
|
||||
if (!se->_hIcon) {
|
||||
se->_hIcon = extract_icon(_folder, se->_pidl, static_cast<ShellEntry*>(se));
|
||||
for(Entry*entry=_down; entry; entry=entry->_next)
|
||||
if (!entry->_hIcon) {
|
||||
if (entry->_etype == ET_SHELL)
|
||||
entry->_hIcon = extract_icon(_folder, static_cast<ShellEntry*>(entry));
|
||||
else // !ET_SHELL
|
||||
entry->_hIcon = extract_icon(entry);
|
||||
|
||||
if (entry->_hIcon)
|
||||
++cnt;
|
||||
else
|
||||
entry->_hIcon = (HICON)-1; // don't try again later
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
/// shell file/directory entry
|
||||
struct ShellEntry : public Entry
|
||||
{
|
||||
ShellEntry(Entry* parent, LPITEMIDLIST shell_path) : Entry(parent), _pidl(shell_path) {}
|
||||
ShellEntry(Entry* parent, const ShellPath& shell_path) : Entry(parent), _pidl(shell_path) {}
|
||||
ShellEntry(Entry* parent, LPITEMIDLIST shell_path) : Entry(parent, ET_SHELL), _pidl(shell_path) {}
|
||||
ShellEntry(Entry* parent, const ShellPath& shell_path) : Entry(parent, ET_SHELL), _pidl(shell_path) {}
|
||||
|
||||
virtual void get_path(PTSTR path) const;
|
||||
virtual bool get_path(PTSTR path) const;
|
||||
virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL);
|
||||
|
||||
IShellFolder* get_parent_folder() const;
|
||||
|
@ -45,6 +45,23 @@ protected:
|
|||
ShellEntry(const ShellPath& shell_path) : Entry(ET_SHELL), _pidl(shell_path) {}
|
||||
};
|
||||
|
||||
bool inline get_entry_pidl(Entry* entry, ShellPath& shell_path)
|
||||
{
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
shell_path = static_cast<ShellEntry*>(entry)->create_absolute_pidl();
|
||||
return true;
|
||||
} else {
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
if (!entry->get_path(path))
|
||||
return false;
|
||||
|
||||
shell_path = path;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// shell folder entry
|
||||
struct ShellDirectory : public ShellEntry, public Directory
|
||||
|
@ -97,11 +114,11 @@ struct ShellDirectory : public ShellEntry, public Directory
|
|||
pFolder->Release();
|
||||
}
|
||||
|
||||
virtual void read_directory(bool read_icons=true);
|
||||
virtual void read_directory(int scan_flags=SCAN_ALL);
|
||||
virtual const void* get_next_path_component(const void*);
|
||||
virtual Entry* find_entry(const void* p);
|
||||
|
||||
virtual void get_path(PTSTR path) const;
|
||||
virtual bool get_path(PTSTR path) const;
|
||||
|
||||
int extract_icons();
|
||||
|
||||
|
@ -120,3 +137,5 @@ inline IShellFolder* ShellEntry::get_parent_folder() const
|
|||
else
|
||||
return Desktop();
|
||||
}
|
||||
|
||||
extern HICON extract_icon(const Entry* entry);
|
||||
|
|
|
@ -119,14 +119,16 @@ int ScanNTFSStreams(Entry* entry, HANDLE hFile)
|
|||
}
|
||||
|
||||
|
||||
void WinDirectory::read_directory(bool read_icons)
|
||||
void WinDirectory::read_directory(int scan_flags)
|
||||
{
|
||||
CONTEXT("WinDirectory::read_directory()");
|
||||
|
||||
int level = _level + 1;
|
||||
|
||||
Entry* first_entry = NULL;
|
||||
Entry* last = NULL;
|
||||
Entry* entry;
|
||||
|
||||
int level = _level + 1;
|
||||
|
||||
LPCTSTR path = (LPCTSTR)_path;
|
||||
TCHAR buffer[MAX_PATH], *p;
|
||||
for(p=buffer; *path; )
|
||||
|
@ -159,20 +161,22 @@ void WinDirectory::read_directory(bool read_icons)
|
|||
entry->_level = level;
|
||||
entry->_bhfi_valid = false;
|
||||
|
||||
HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (scan_flags & SCAN_DO_ACCESS) {
|
||||
HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
if (GetFileInformationByHandle(hFile, &entry->_bhfi))
|
||||
entry->_bhfi_valid = true;
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
if (GetFileInformationByHandle(hFile, &entry->_bhfi))
|
||||
entry->_bhfi_valid = true;
|
||||
|
||||
if (ScanNTFSStreams(entry, hFile))
|
||||
entry->_scanned = true; // There exist named NTFS sub-streams in this file.
|
||||
if (ScanNTFSStreams(entry, hFile))
|
||||
entry->_scanned = true; // There exist named NTFS sub-streams in this file.
|
||||
|
||||
CloseHandle(hFile);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
last = entry;
|
||||
last = entry; // There is always at least one entry, because FindFirstFile() succeeded and we don't filter the file entries.
|
||||
} while(FindNextFile(hFind, &w32fd));
|
||||
|
||||
last->_next = NULL;
|
||||
|
@ -229,41 +233,68 @@ Entry* WinDirectory::find_entry(const void* p)
|
|||
|
||||
|
||||
// get full path of specified directory entry
|
||||
void WinEntry::get_path(PTSTR path) const
|
||||
bool WinEntry::get_path(PTSTR path) const
|
||||
{
|
||||
int level = 0;
|
||||
int len = 0;
|
||||
int l = 0;
|
||||
LPCTSTR name = NULL;
|
||||
TCHAR buffer[MAX_PATH];
|
||||
|
||||
for(const Entry* entry=this; entry; level++) {
|
||||
LPCTSTR name = entry->_data.cFileName;
|
||||
int l = 0;
|
||||
const Entry* entry;
|
||||
for(entry=this; entry; level++) {
|
||||
l = 0;
|
||||
|
||||
for(LPCTSTR s=name; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++)
|
||||
++l;
|
||||
if (entry->_etype == ET_WINDOWS) {
|
||||
name = entry->_data.cFileName;
|
||||
|
||||
if (entry->_up) {
|
||||
if (l > 0) {
|
||||
memmove(path+l+1, path, len*sizeof(TCHAR));
|
||||
memcpy(path+1, name, l*sizeof(TCHAR));
|
||||
len += l+1;
|
||||
for(LPCTSTR s=name; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++)
|
||||
++l;
|
||||
|
||||
if (entry->_up && !(entry->_up->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // a NTFS stream?
|
||||
path[0] = TEXT(':');
|
||||
else
|
||||
path[0] = TEXT('\\');
|
||||
if (!entry->_up)
|
||||
break;
|
||||
} else {
|
||||
if (entry->get_path(buffer)) {
|
||||
l = _tcslen(buffer);
|
||||
name = buffer;
|
||||
|
||||
/* special handling of drive names */
|
||||
if (l>0 && buffer[l-1]=='\\' && path[0]=='\\')
|
||||
--l;
|
||||
|
||||
memmove(path+l, path, len*sizeof(TCHAR));
|
||||
memcpy(path, name, l*sizeof(TCHAR));
|
||||
len += l;
|
||||
}
|
||||
|
||||
entry = entry->_up;
|
||||
} else {
|
||||
memmove(path+l, path, len*sizeof(TCHAR));
|
||||
memcpy(path, name, l*sizeof(TCHAR));
|
||||
len += l;
|
||||
entry = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (l > 0) {
|
||||
memmove(path+l+1, path, len*sizeof(TCHAR));
|
||||
memcpy(path+1, name, l*sizeof(TCHAR));
|
||||
len += l+1;
|
||||
|
||||
if (entry->_up && !(entry->_up->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // a NTFS stream?
|
||||
path[0] = TEXT(':');
|
||||
else
|
||||
path[0] = TEXT('\\');
|
||||
}
|
||||
|
||||
entry = entry->_up;
|
||||
}
|
||||
|
||||
if (entry) {
|
||||
memmove(path+l, path, len*sizeof(TCHAR));
|
||||
memcpy(path, name, l*sizeof(TCHAR));
|
||||
len += l;
|
||||
}
|
||||
|
||||
if (!level)
|
||||
path[len++] = TEXT('\\');
|
||||
|
||||
path[len] = TEXT('\0');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,19 +26,19 @@
|
|||
//
|
||||
|
||||
|
||||
/// Windows File System file-entry
|
||||
/// Windows file system file-entry
|
||||
struct WinEntry : public Entry
|
||||
{
|
||||
WinEntry(Entry* parent) : Entry(parent) {}
|
||||
WinEntry(Entry* parent) : Entry(parent, ET_WINDOWS) {}
|
||||
|
||||
protected:
|
||||
WinEntry() : Entry(ET_WINDOWS) {}
|
||||
|
||||
virtual void get_path(PTSTR path) const;
|
||||
virtual bool get_path(PTSTR path) const;
|
||||
};
|
||||
|
||||
|
||||
/// Windows File System directory-entry
|
||||
/// Windows file system directory-entry
|
||||
struct WinDirectory : public WinEntry, public Directory
|
||||
{
|
||||
WinDirectory(LPCTSTR root_path)
|
||||
|
@ -47,7 +47,7 @@ struct WinDirectory : public WinEntry, public Directory
|
|||
_path = _tcsdup(root_path);
|
||||
}
|
||||
|
||||
WinDirectory(WinDirectory* parent, LPCTSTR path)
|
||||
WinDirectory(Entry* parent, LPCTSTR path)
|
||||
: WinEntry(parent)
|
||||
{
|
||||
_path = _tcsdup(path);
|
||||
|
@ -59,7 +59,9 @@ struct WinDirectory : public WinEntry, public Directory
|
|||
_path = NULL;
|
||||
}
|
||||
|
||||
virtual void read_directory(bool read_icons=true);
|
||||
virtual void read_directory(int scan_flags=SCAN_ALL);
|
||||
virtual const void* get_next_path_component(const void*);
|
||||
virtual Entry* find_entry(const void*);
|
||||
};
|
||||
|
||||
extern int ScanNTFSStreams(Entry* entry, HANDLE hFile);
|
||||
|
|
|
@ -94,7 +94,7 @@ void QuickLaunchBar::AddShortcuts()
|
|||
WaitCursor wait;
|
||||
|
||||
try {
|
||||
TCHAR path[_MAX_PATH];
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
SpecialFolderFSPath app_data(CSIDL_APPDATA, _hwnd); // perhaps also look into CSIDL_COMMON_APPDATA ?
|
||||
|
||||
|
@ -102,7 +102,7 @@ void QuickLaunchBar::AddShortcuts()
|
|||
|
||||
_dir = new ShellDirectory(Desktop(), path, _hwnd);
|
||||
|
||||
_dir->smart_scan();
|
||||
_dir->smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
|
||||
} catch(COMException&) {
|
||||
return;
|
||||
}
|
||||
|
@ -120,10 +120,7 @@ void QuickLaunchBar::AddShortcuts()
|
|||
|
||||
// hide subfolders
|
||||
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
ShellEntry* shell_entry = static_cast<ShellEntry*>(entry);
|
||||
|
||||
const String& entry_name = desktop_folder.get_name(shell_entry->_pidl);
|
||||
HBITMAP hbmp = create_bitmap_from_icon(shell_entry->_hIcon, GetSysColorBrush(COLOR_BTNFACE), canvas);
|
||||
HBITMAP hbmp = create_bitmap_from_icon(entry->_hIcon, GetSysColorBrush(COLOR_BTNFACE), canvas);
|
||||
|
||||
TBADDBITMAP ab = {0, (UINT_PTR)hbmp};
|
||||
int bmp_idx = SendMessage(_hwnd, TB_ADDBITMAP, 1, (LPARAM)&ab);
|
||||
|
@ -133,8 +130,8 @@ void QuickLaunchBar::AddShortcuts()
|
|||
int id = ++_next_id;
|
||||
|
||||
qle._hbmp = hbmp;
|
||||
qle._title = entry_name;
|
||||
qle._entry = shell_entry;
|
||||
qle._title = entry->_display_name; //entry->_etype==ET_SHELL? desktop_folder.get_name(static_cast<ShellEntry*>(entry)->_pidl): entry->_display_name
|
||||
qle._entry = entry;
|
||||
|
||||
_entries[id] = qle;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct QuickLaunchEntry
|
|||
|
||||
HBITMAP _hbmp;
|
||||
String _title;
|
||||
ShellEntry* _entry;
|
||||
Entry* _entry;
|
||||
};
|
||||
|
||||
/// map for managing the task bar buttons
|
||||
|
|
|
@ -188,9 +188,9 @@ void StartMenu::AddEntries()
|
|||
WaitCursor wait;
|
||||
|
||||
#ifdef _LAZY_ICONEXTRACT
|
||||
dir.smart_scan(false); // lazy icon extraction
|
||||
dir.smart_scan(SCAN_FILESYSTEM); // lazy icon extraction, try to read directly from filesystem
|
||||
#else
|
||||
dir.smart_scan(true);
|
||||
dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -218,9 +218,10 @@ void StartMenu::AddShellEntries(const ShellDirectory& dir, int max, bool subfold
|
|||
if (++cnt == max)
|
||||
break;
|
||||
|
||||
const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry);
|
||||
|
||||
AddEntry(dir._folder, shell_entry);
|
||||
if (entry->_etype == ET_SHELL)
|
||||
AddEntry(dir._folder, static_cast<const ShellEntry*>(entry));
|
||||
else
|
||||
AddEntry(dir._folder, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +269,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
|
|||
RECT rect;
|
||||
|
||||
// check mouse cursor for coordinates of floating button
|
||||
GetFloatingButonRect(&rect);
|
||||
GetFloatingButtonRect(&rect);
|
||||
|
||||
if (PtInRect(&rect, Point(lparam))) {
|
||||
// create a floating copy of the current start menu
|
||||
|
@ -334,7 +335,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
|
|||
|
||||
#ifdef _LAZY_ICONEXTRACT
|
||||
case PM_UPDATE_ICONS:
|
||||
UpdateIcons();
|
||||
UpdateIcons(wparam);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -441,7 +442,7 @@ void StartMenu::SelectButton(int id)
|
|||
#endif
|
||||
|
||||
|
||||
bool StartMenu::GetButtonRect(int id, PRECT prect)
|
||||
bool StartMenu::GetButtonRect(int id, PRECT prect) const
|
||||
{
|
||||
#ifdef _LIGHT_STARTMENU
|
||||
ClientRect clnt(_hwnd);
|
||||
|
@ -452,7 +453,7 @@ bool StartMenu::GetButtonRect(int id, PRECT prect)
|
|||
|
||||
rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT);
|
||||
|
||||
if (info._id == _selected_id) {
|
||||
if (info._id == id) {
|
||||
*prect = rect;
|
||||
return true;
|
||||
}
|
||||
|
@ -484,7 +485,7 @@ void StartMenu::DrawFloatingButton(HDC hdc)
|
|||
DrawIconEx(hdc, clnt.right-12, 0, floatingIcon, 8, 4, 0, 0, DI_NORMAL);
|
||||
}
|
||||
|
||||
void StartMenu::GetFloatingButonRect(LPRECT prect)
|
||||
void StartMenu::GetFloatingButtonRect(LPRECT prect)
|
||||
{
|
||||
GetClientRect(_hwnd, prect);
|
||||
|
||||
|
@ -509,12 +510,12 @@ void StartMenu::Paint(PaintCanvas& canvas)
|
|||
BkMode bk_mode(canvas, TRANSPARENT);
|
||||
|
||||
for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) {
|
||||
const SMBtnInfo& info = *it;
|
||||
const SMBtnInfo& btn = *it;
|
||||
|
||||
if (rect.top > canvas.rcPaint.bottom)
|
||||
break;
|
||||
|
||||
if (info._id == -1) { // a separator?
|
||||
if (btn._id == -1) { // a separator?
|
||||
rect.bottom = rect.top + STARTMENU_SEP_HEIGHT;
|
||||
|
||||
BrushSelection brush_sel(canvas, GetSysColorBrush(COLOR_BTNSHADOW));
|
||||
|
@ -526,8 +527,8 @@ void StartMenu::Paint(PaintCanvas& canvas)
|
|||
rect.bottom = rect.top + STARTMENU_LINE_HEIGHT;
|
||||
|
||||
if (rect.top >= canvas.rcPaint.top)
|
||||
DrawStartMenuButton(canvas, rect, info._title, info._hIcon,
|
||||
info._hasSubmenu, info._enabled, info._id==_selected_id, false);
|
||||
DrawStartMenuButton(canvas, rect, btn._title, btn._hIcon,
|
||||
btn._hasSubmenu, btn._enabled, btn._id==_selected_id, false);
|
||||
}
|
||||
|
||||
rect.top = rect.bottom;
|
||||
|
@ -536,12 +537,52 @@ void StartMenu::Paint(PaintCanvas& canvas)
|
|||
}
|
||||
|
||||
#ifdef _LAZY_ICONEXTRACT
|
||||
void StartMenu::UpdateIcons()
|
||||
void StartMenu::UpdateIcons(int idx)
|
||||
{
|
||||
UpdateWindow(_hwnd);
|
||||
|
||||
#ifdef _SINGLE_ICONEXTRACT
|
||||
// extract only one icon per call to allow leaving the folder while the lazy extraction is running
|
||||
if (idx >= 0) {
|
||||
for(; idx<(int)_buttons.size(); ++idx) {
|
||||
SMBtnInfo& btn = _buttons[idx];
|
||||
|
||||
if (!btn._hIcon && btn._id>0) {
|
||||
StartMenuEntry& sme = _entries[btn._id];
|
||||
|
||||
btn._hIcon = (HICON)-1;
|
||||
|
||||
for(ShellEntrySet::const_iterator it=sme._entries.begin(); it!=sme._entries.end(); ++it) {
|
||||
const Entry* entry = *it;
|
||||
|
||||
HICON hIcon = extract_icon(entry);
|
||||
|
||||
if (hIcon) {
|
||||
btn._hIcon = hIcon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (btn._hIcon != (HICON)-1) {
|
||||
RECT rect;
|
||||
GetButtonRect(btn._id, &rect);
|
||||
WindowCanvas canvas(_hwnd);
|
||||
DrawStartMenuButton(canvas, rect, NULL, btn._hIcon, btn._hasSubmenu, btn._enabled, btn._id==_selected_id, false);
|
||||
//InvalidateRect(_hwnd, &rect, FALSE);
|
||||
//UpdateWindow(_hwnd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (++idx < (int)_buttons.size())
|
||||
PostMessage(_hwnd, PM_UPDATE_ICONS, idx, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
int icons_extracted = 0;
|
||||
int icons_refreshed = 0;
|
||||
int icons_updated = 0;
|
||||
|
||||
for(StartMenuShellDirs::iterator it=_dirs.begin(); it!=_dirs.end(); ++it) {
|
||||
ShellDirectory& dir = it->_dir;
|
||||
|
@ -557,7 +598,7 @@ void StartMenu::UpdateIcons()
|
|||
sme._hIcon = (HICON)-1;
|
||||
|
||||
for(ShellEntrySet::const_iterator it2=sme._entries.begin(); it2!=sme._entries.end(); ++it2) {
|
||||
const ShellEntry* sm_entry = *it2;
|
||||
const Entry* sm_entry = *it2;
|
||||
|
||||
if (sm_entry->_hIcon) {
|
||||
sme._hIcon = sm_entry->_hIcon;
|
||||
|
@ -572,15 +613,16 @@ void StartMenu::UpdateIcons()
|
|||
|
||||
if (info._id>0 && !info._hIcon) {
|
||||
info._hIcon = _entries[info._id]._hIcon;
|
||||
++icons_refreshed;
|
||||
++icons_updated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icons_refreshed) {
|
||||
InvalidateRect(_hwnd, NULL, TRUE);
|
||||
if (icons_updated) {
|
||||
InvalidateRect(_hwnd, NULL, FALSE);
|
||||
UpdateWindow(_hwnd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -630,7 +672,31 @@ int StartMenu::Command(int id, int code)
|
|||
}
|
||||
|
||||
|
||||
StartMenuEntry& StartMenu::AddEntry(LPCTSTR title, HICON hIcon, int id)
|
||||
StartMenuEntry& StartMenu::AddEntry(const String& title, HICON hIcon, const Entry* entry)
|
||||
{
|
||||
// search for an already existing subdirectory entry with the same name
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
for(ShellEntryMap::iterator it=_entries.begin(); it!=_entries.end(); ++it) {
|
||||
StartMenuEntry& sme = it->second;
|
||||
|
||||
if (sme._title == title) ///@todo speed up by using a map indexed by name
|
||||
for(ShellEntrySet::iterator it2=sme._entries.begin(); it2!=sme._entries.end(); ++it2) {
|
||||
if ((*it2)->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// merge the new shell entry with the existing of the same name
|
||||
sme._entries.insert(entry);
|
||||
return sme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StartMenuEntry& sme = AddEntry(title, hIcon);
|
||||
|
||||
sme._entries.insert(entry);
|
||||
|
||||
return sme;
|
||||
}
|
||||
|
||||
StartMenuEntry& StartMenu::AddEntry(const String& title, HICON hIcon, int id)
|
||||
{
|
||||
if (id == -1)
|
||||
id = ++_next_id;
|
||||
|
@ -648,32 +714,20 @@ StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, const ShellEntry*
|
|||
HICON hIcon = entry->_hIcon;
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
hIcon = SmallIcon(IDI_EXPLORER);
|
||||
hIcon = SmallIcon(IDI_FOLDER);
|
||||
|
||||
const String& entry_name = folder.get_name(entry->_pidl);
|
||||
|
||||
// search for an already existing subdirectory entry with the same name
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
for(ShellEntryMap::iterator it=_entries.begin(); it!=_entries.end(); ++it) {
|
||||
StartMenuEntry& sme = it->second;
|
||||
|
||||
if (sme._title == entry_name) ///@todo speed up by using a map indexed by name
|
||||
for(ShellEntrySet::iterator it2=sme._entries.begin(); it2!=sme._entries.end(); ++it2) {
|
||||
if ((*it2)->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// merge the new shell entry with the existing of the same name
|
||||
sme._entries.insert(entry);
|
||||
return sme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StartMenuEntry& sme = AddEntry(entry_name, hIcon);
|
||||
|
||||
sme._entries.insert(entry);
|
||||
|
||||
return sme;
|
||||
return AddEntry(folder.get_name(entry->_pidl), hIcon, entry);
|
||||
}
|
||||
|
||||
StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, const Entry* entry)
|
||||
{
|
||||
HICON hIcon = entry->_hIcon;
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
hIcon = SmallIcon(IDI_FOLDER);
|
||||
|
||||
return AddEntry(entry->_display_name, hIcon, entry);
|
||||
}
|
||||
|
||||
|
||||
void StartMenu::AddButton(LPCTSTR title, HICON hIcon, bool hasSubmenu, int id, bool enabled)
|
||||
|
@ -743,8 +797,8 @@ bool StartMenu::CloseOtherSubmenus(int id)
|
|||
if (_submenu_id == id)
|
||||
return false;
|
||||
else {
|
||||
DestroyWindow(_submenu);
|
||||
_submenu_id = 0;
|
||||
DestroyWindow(_submenu);
|
||||
// _submenu should be reset automatically by PM_STARTMENU_CLOSED, but safety first...
|
||||
}
|
||||
}
|
||||
|
@ -825,10 +879,20 @@ void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries)
|
|||
String title;
|
||||
|
||||
for(ShellEntrySet::const_iterator it=entries.begin(); it!=entries.end(); ++it) {
|
||||
ShellEntry* entry = const_cast<ShellEntry*>(*it);
|
||||
Entry* entry = const_cast<Entry*>(*it);
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
new_folders.push_back(entry->create_absolute_pidl());
|
||||
|
||||
///@todo If the user explicitely clicked on a submenu, display this folder as floating start menu.
|
||||
|
||||
if (entry->_etype == ET_SHELL)
|
||||
new_folders.push_back(static_cast<const ShellEntry*>(entry)->create_absolute_pidl());
|
||||
else {
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
if (entry->get_path(path))
|
||||
new_folders.push_back(path);
|
||||
}
|
||||
|
||||
if (title.empty())
|
||||
title = entry->_display_name;
|
||||
|
@ -903,7 +967,9 @@ void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
|
|||
|
||||
HBRUSH bk_brush = GetSysColorBrush(bk_color);
|
||||
|
||||
FillRect(hdc, &rect, bk_brush);
|
||||
if (title)
|
||||
FillRect(hdc, &rect, bk_brush);
|
||||
|
||||
DrawIconEx(hdc, iconPos.x, iconPos.y, hIcon, 16, 16, 0, bk_brush, DI_NORMAL);
|
||||
|
||||
// draw submenu arrow at the right
|
||||
|
@ -916,13 +982,15 @@ void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
|
|||
16, 16, 0, bk_brush, DI_NORMAL);
|
||||
}
|
||||
|
||||
BkMode bk_mode(hdc, TRANSPARENT);
|
||||
if (title) {
|
||||
BkMode bk_mode(hdc, TRANSPARENT);
|
||||
|
||||
if (!enabled) // dis->itemState & (ODS_DISABLED|ODS_GRAYED)
|
||||
DrawGrayText(hdc, &textRect, title, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
|
||||
else {
|
||||
TextColor lcColor(hdc, GetSysColor(text_color));
|
||||
DrawText(hdc, title, -1, &textRect, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
|
||||
if (!enabled) // dis->itemState & (ODS_DISABLED|ODS_GRAYED)
|
||||
DrawGrayText(hdc, &textRect, title, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
|
||||
else {
|
||||
TextColor lcColor(hdc, GetSysColor(text_color));
|
||||
DrawText(hdc, title, -1, &textRect, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1505,10 +1573,6 @@ void SearchMenu::AddEntries()
|
|||
|
||||
void RecentStartMenu::AddEntries()
|
||||
{
|
||||
|
||||
///@todo A cache would really speed up processing of long recent doc lists.
|
||||
///@todo Alternativelly we could also use direct file system access instead of iterating in shell namespace.
|
||||
|
||||
for(StartMenuShellDirs::iterator it=_dirs.begin(); it!=_dirs.end(); ++it) {
|
||||
StartMenuDirectory& smd = *it;
|
||||
ShellDirectory& dir = smd._dir;
|
||||
|
@ -1517,9 +1581,9 @@ void RecentStartMenu::AddEntries()
|
|||
WaitCursor wait;
|
||||
|
||||
#ifdef _LAZY_ICONEXTRACT
|
||||
dir.smart_scan(false); // lazy icon extraction
|
||||
dir.smart_scan(SCAN_FILESYSTEM);
|
||||
#else
|
||||
dir.smart_scan(true);
|
||||
dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#define _LIGHT_STARTMENU
|
||||
#define _LAZY_ICONEXTRACT
|
||||
#define _SINGLE_ICONEXTRACT
|
||||
|
||||
|
||||
#define CLASSNAME_STARTMENU TEXT("ReactosStartmenuClass")
|
||||
|
@ -69,7 +70,7 @@ struct StartMenuDirectory
|
|||
};
|
||||
|
||||
typedef list<StartMenuDirectory> StartMenuShellDirs;
|
||||
typedef set<const ShellEntry*> ShellEntrySet;
|
||||
typedef set<const Entry*> ShellEntrySet;
|
||||
|
||||
/// structure holding information about one start menu entry
|
||||
struct StartMenuEntry
|
||||
|
@ -253,8 +254,10 @@ protected:
|
|||
|
||||
virtual void AddEntries();
|
||||
|
||||
StartMenuEntry& AddEntry(LPCTSTR title, HICON hIcon=0, int id=-1);
|
||||
StartMenuEntry& AddEntry(const String& title, HICON hIcon, const Entry* entry);
|
||||
StartMenuEntry& AddEntry(const String& title, HICON hIcon=0, int id=-1);
|
||||
StartMenuEntry& AddEntry(const ShellFolder folder, const ShellEntry* entry);
|
||||
StartMenuEntry& AddEntry(const ShellFolder folder, const Entry* entry);
|
||||
|
||||
void AddShellEntries(const ShellDirectory& dir, int max=-1, bool subfolders=true);
|
||||
|
||||
|
@ -270,13 +273,13 @@ protected:
|
|||
void ActivateEntry(int id, const ShellEntrySet& entries);
|
||||
void CloseStartMenu(int id=0);
|
||||
|
||||
bool GetButtonRect(int id, PRECT prect);
|
||||
bool GetButtonRect(int id, PRECT prect) const;
|
||||
|
||||
void DrawFloatingButton(HDC hdc);
|
||||
void GetFloatingButonRect(LPRECT prect);
|
||||
void GetFloatingButtonRect(LPRECT prect);
|
||||
|
||||
void Paint(PaintCanvas& canvas);
|
||||
void UpdateIcons();
|
||||
void UpdateIcons(int idx);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue