* 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&) { } catch(COMException&) {
} }
if (_alive)
_cache_valid = true;
return 0; return 0;
} }
void CollectProgramsThread::collect_programs(const ShellPath& path) 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) if (!_alive)
break; break;
if (entry->_shell_attribs & SFGAO_HIDDEN) if (entry->_shell_attribs & SFGAO_HIDDEN)
continue; continue;
const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry); ShellEntry* shell_entry = static_cast<ShellEntry*>(entry);
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
collect_programs(shell_entry->create_absolute_pidl()); collect_programs(shell_entry->create_absolute_pidl());
else if (entry->_shell_attribs & SFGAO_LINK) else if (entry->_shell_attribs & SFGAO_LINK)
if (_alive) 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) #pragma warning(disable: 4355)
FindProgramTopicDlg::FindProgramTopicDlg(HWND hwnd) FindProgramDlg::FindProgramDlg(HWND hwnd)
: super(hwnd), : super(hwnd),
_list_ctrl(GetDlgItem(hwnd, IDC_MAILS_FOUND)), _list_ctrl(GetDlgItem(hwnd, IDC_MAILS_FOUND)),
_himl(ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 0, 0)), _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"); column.pszText = _T("Name");
ListView_InsertColumn(_list_ctrl, 0, &column); ListView_InsertColumn(_list_ctrl, 0, &column);
column.cx = 400; column.cx = 300;
column.pszText = _T("Path"); column.pszText = _T("Path");
ListView_InsertColumn(_list_ctrl, 1, &column); 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); 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(); Refresh();
} }
FindProgramTopicDlg::~FindProgramTopicDlg() FindProgramDlg::~FindProgramDlg()
{ {
ImageList_Destroy(_himl); ImageList_Destroy(_himl);
} }
void FindProgramTopicDlg::Refresh() void FindProgramDlg::Refresh(bool delete_cache)
{ {
WaitCursor wait; WaitCursor wait;
@ -126,82 +151,112 @@ void FindProgramTopicDlg::Refresh()
TCHAR buffer[1024]; TCHAR buffer[1024];
GetWindowText(GetDlgItem(_hwnd, IDC_TOPIC), buffer, 1024); GetWindowText(GetDlgItem(_hwnd, IDC_TOPIC), buffer, 1024);
_filter = buffer; #ifndef __WINE__ //TODO
_tcslwr(buffer);
#endif
_lwr_filter = buffer;
ListView_DeleteAllItems(_list_ctrl); 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; IShellLink* pShellLink;
HRESULT hr = folder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink); HRESULT hr = folder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
WIN32_FIND_DATA wfd; ShellLinkPtr shell_link(pShellLink);
/*hr = pShellLink->Resolve(_hwnd, SLR_NO_UI); /*hr = pShellLink->Resolve(pThis->_hwnd, SLR_NO_UI);
if (SUCCEEDED(NOERROR))*/ { if (SUCCEEDED(hr))*/ {
WIN32_FIND_DATA wfd;
TCHAR path[MAX_PATH]; TCHAR path[MAX_PATH];
hr = pShellLink->GetPath(path, MAX_PATH-1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY); hr = pShellLink->GetPath(path, MAX_PATH-1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
FindProgramTopicDlg* pThis = (FindProgramTopicDlg*) param; FileSysShellPath entry_path(shell_entry->create_absolute_pidl());
String menu_path;
String lwr_path = path; int len = pThis->_common_programs.size();
String lwr_name = entry->_display_name; if (len && !_tcsnicmp(entry_path, pThis->_common_programs, len))
String filter = pThis->_filter; 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 // store info in cache
_tcslwr((LPTSTR)lwr_path.c_str()); FPDEntry new_entry;
_tcslwr((LPTSTR)lwr_name.c_str());
_tcslwr((LPTSTR)filter.c_str());
#endif
//if (_tcsstr(lwr_path, _T(".exe"))) //@@ filter on ".exe" suffix new_entry._shell_entry = shell_entry;
//if (!_tcsstr(lwr_name, _T("uninstal")) && !_tcsstr(lwr_name, _T("deinstal"))) //@@ filter out deinstallation links new_entry._menu_path = menu_path;
if (_tcsstr(lwr_path, filter) || _tcsstr(lwr_name, filter)) { new_entry._path = path;
LV_ITEM item = {LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM, INT_MAX};
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) pThis->_cache.push_front(new_entry);
item.iImage = ImageList_AddIcon(pThis->_himl, entry->_hIcon); FPDEntry& cache_entry = pThis->_cache.front();
else
item.iImage = pThis->_idxNoIcon;
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); pThis->add_entry(cache_entry);
// 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);
}
} }
} }
} }
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) { switch(message) {
default: default:
@ -211,12 +266,12 @@ LRESULT FindProgramTopicDlg::WndProc(UINT message, WPARAM wparam, LPARAM lparam)
return FALSE; return FALSE;
} }
int FindProgramTopicDlg::Command(int id, int code) int FindProgramDlg::Command(int id, int code)
{ {
if (code == BN_CLICKED) if (code == BN_CLICKED)
switch(id) { switch(id) {
case ID_REFRESH: case ID_REFRESH:
Refresh(); Refresh(true);
break; break;
default: default:
@ -231,14 +286,13 @@ int FindProgramTopicDlg::Command(int id, int code)
return TRUE; return TRUE;
} }
int FindProgramTopicDlg::Notify(int id, NMHDR* pnmh) int FindProgramDlg::Notify(int id, NMHDR* pnmh)
{ {
switch(pnmh->code) { switch(pnmh->code) {
case LVN_GETDISPINFO: { case LVN_GETDISPINFO: {/*
LV_DISPINFO* pDispInfo = (LV_DISPINFO*) pnmh; LV_DISPINFO* pDispInfo = (LV_DISPINFO*) pnmh;
if (pnmh->hwndFrom == _list_ctrl) { if (pnmh->hwndFrom == _list_ctrl) {
/*
if (pDispInfo->item.mask & LVIF_IMAGE) { if (pDispInfo->item.mask & LVIF_IMAGE) {
int icon; int icon;
HRESULT hr = pShellLink->GetIconLocation(path, MAX_PATH-1, &icon); HRESULT hr = pShellLink->GetIconLocation(path, MAX_PATH-1, &icon);
@ -250,9 +304,18 @@ int FindProgramTopicDlg::Notify(int id, NMHDR* pnmh)
return 1; 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; return 0;

View file

@ -27,61 +27,79 @@
// Martin Fuchs, 02.10.2003 // Martin Fuchs, 02.10.2003
// //
#include <stack>
struct ShellPathWithFolder
{
ShellPathWithFolder(const ShellFolder& folder, const ShellPath& path)
: _folder(folder), _path(path) {}
ShellFolder _folder;
ShellPath _path;
};
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 struct CollectProgramsThread : public Thread
{ {
CollectProgramsThread(COLLECT_CALLBACK callback, HWND hwnd, void* para) CollectProgramsThread(COLLECT_CALLBACK callback, HWND hwnd, void* para)
: _callback(callback), : _cache_valid(false),
_callback(callback),
_hwnd(hwnd), _hwnd(hwnd),
_para(para) _para(para)
{ {
} }
int Run(); ~CollectProgramsThread()
{
free_dirs();
}
int Run();
void free_dirs();
bool _cache_valid;
protected: protected:
COLLECT_CALLBACK _callback; COLLECT_CALLBACK _callback;
HWND _hwnd; HWND _hwnd;
void* _para; 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; typedef ResizeController<Dialog> super;
FindProgramTopicDlg(HWND hwnd); FindProgramDlg(HWND hwnd);
~FindProgramTopicDlg(); ~FindProgramDlg();
protected: protected:
CommonControlInit _usingCmnCtrl; CommonControlInit _usingCmnCtrl;
HWND _list_ctrl; HWND _list_ctrl;
HACCEL _haccel; HACCEL _haccel;
HIMAGELIST _himl; HIMAGELIST _himl;
int _idxNoIcon; // Ersatzicon für Links ohne Symbole int _idxNoIcon; // replacement icon
String _filter; String _lwr_filter;
CollectProgramsThread _thread; CollectProgramsThread _thread;
FPDCache _cache;
String _common_programs, _user_programs;
virtual LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam); 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); 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_PRINTERS 22
#define IDS_BROWSE 23 #define IDS_BROWSE 23
#define IDS_SEARCH_PRG 24 #define IDS_SEARCH_PRG 24
#define IDS_ALL_USERS 25
#define IDI_REACTOS 100 #define IDI_REACTOS 100
#define IDI_EXPLORER 101 #define IDI_EXPLORER 101
#define IDI_STARTMENU 102 #define IDI_STARTMENU 102
@ -77,6 +78,7 @@
#define ID_FILE_EXIT 0xE141 #define ID_FILE_EXIT 0xE141
#define ID_HELP_USING 0xE144 #define ID_HELP_USING 0xE144
#define ID_HELP 0xE146 #define ID_HELP 0xE146
#define IDC_STATIC -1
// Next default values for new objects // Next default values for new objects
// //

View file

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

View file

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

View file

@ -162,7 +162,7 @@ ShellFolder::ShellFolder()
} }
ShellFolder::ShellFolder(IShellFolder* p) ShellFolder::ShellFolder(IShellFolder* p)
: IShellFolderPtr(p) : super(p)
{ {
p->AddRef(); p->AddRef();
} }
@ -220,7 +220,7 @@ ShellFolder::ShellFolder()
} }
ShellFolder::ShellFolder(IShellFolder* p) ShellFolder::ShellFolder(IShellFolder* p)
: SIfacePtr<IShellFolder>(p) : super(p)
{ {
_p->AddRef(); _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() 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 #else // _com_ptr not available -> use SIfacePtr
struct ShellFolder : public SIfacePtr<IShellFolder> struct ShellFolder : public SIfacePtr<IShellFolder>
@ -407,6 +426,18 @@ struct ShellFolder : public SIfacePtr<IShellFolder>
String get_name(LPCITEMIDLIST pidl, SHGDNF flags=SHGDN_NORMAL) const; 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 #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) void display_error(HWND hwnd, DWORD error)
{ {
PTSTR msg; PTSTR msg;

View file

@ -449,9 +449,12 @@ struct String
String() {} String() {}
String(LPCTSTR s) : super(s) {} String(LPCTSTR s) : super(s) {}
String(const super& other) : super(other) {}
String(const String& other) : super(other) {} String(const String& other) : super(other) {}
String& operator=(LPCTSTR s) {assign(s); return *this;} String& operator=(LPCTSTR s) {assign(s); return *this;}
String& operator=(const super& s) {assign(s); return *this;}
operator LPCTSTR() const {return c_str();} 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)) #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); extern void display_error(HWND hwnd, DWORD error);
// convert time_t to WIN32 FILETIME // convert time_t to WIN32 FILETIME

View file

@ -627,3 +627,17 @@ struct ToolTip : public WindowHandle
SendMessage(_hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti); 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;
}