Implementation of standard startmenu folders

svn path=/trunk/; revision=5678
This commit is contained in:
Martin Fuchs 2003-08-19 21:04:37 +00:00
parent cb15da56e1
commit c5ddf7eb05
10 changed files with 333 additions and 101 deletions

View file

@ -14,6 +14,9 @@
#define IDS_PROGRAMS 10 #define IDS_PROGRAMS 10
#define IDS_SETTINGS 11 #define IDS_SETTINGS 11
#define IDS_EXPLORE 12 #define IDS_EXPLORE 12
#define IDS_EMPTY 13
#define IDS_RECENT 14
#define IDS_ADMIN 15
#define IDI_REACTOS 100 #define IDI_REACTOS 100
#define IDI_EXPLORER 101 #define IDI_EXPLORER 101
#define IDI_STARTMENU 102 #define IDI_STARTMENU 102
@ -59,7 +62,7 @@
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 125 #define _APS_NEXT_RESOURCE_VALUE 126
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101

View file

@ -251,6 +251,9 @@ BEGIN
IDS_PROGRAMS "Programs" IDS_PROGRAMS "Programs"
IDS_SETTINGS "Settings" IDS_SETTINGS "Settings"
IDS_EXPLORE "Explore" IDS_EXPLORE "Explore"
IDS_EMPTY "(Empty)"
IDS_RECENT "Recent Documents"
IDS_ADMIN "Administration"
END END
#endif // German (Germany) resources #endif // German (Germany) resources

View file

@ -30,6 +30,7 @@
#include "../utility/shellclasses.h" #include "../utility/shellclasses.h"
#include "../globals.h" #include "../globals.h"
#include "entries.h" #include "entries.h"
#include "shellfs.h" #include "shellfs.h"
@ -243,22 +244,18 @@ void ShellDirectory::read_directory()
HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs); HRESULT hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidls[n], &attribs);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
if (attribs != ~SFGAO_FILESYSTEM) { if (attribs != ~SFGAO_FILESYSTEM)
bhfi_valid = fill_w32fdata_shell(pidls[n], attribs, &w32fd, &bhfi); bhfi_valid = fill_w32fdata_shell(pidls[n], attribs, &w32fd, &bhfi);
} else else
attribs = 0; attribs = 0;
} else } else
attribs = 0; attribs = 0;
Entry* entry; Entry* entry;
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
IShellFolder* child = NULL; entry = new ShellDirectory(this, pidls[n], _hwnd);
else
/*hr = */_folder->BindToObject(pidls[n], 0, IID_IShellFolder, (void**)&child);
entry = new ShellDirectory(this, child, pidls[n], _hwnd);
} else
entry = new ShellEntry(this, pidls[n]); entry = new ShellEntry(this, pidls[n]);
if (!first_entry) if (!first_entry)

View file

@ -62,9 +62,9 @@ struct ShellDirectory : public ShellEntry, public Directory
_path = pFolder; _path = pFolder;
} }
explicit ShellDirectory(ShellDirectory* parent, IShellFolder* shell_root, LPITEMIDLIST shell_path, HWND hwnd) explicit ShellDirectory(ShellDirectory* parent, LPITEMIDLIST shell_path, HWND hwnd)
: ShellEntry(parent, shell_path), : ShellEntry(parent, shell_path),
_folder(shell_root), _folder(parent->_folder, shell_path),
_hwnd(hwnd) _hwnd(hwnd)
{ {
/* not neccessary - the caller will fill the info /* not neccessary - the caller will fill the info
@ -72,8 +72,18 @@ struct ShellDirectory : public ShellEntry, public Directory
_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; _data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
_shell_attribs = SFGAO_FOLDER; */ _shell_attribs = SFGAO_FOLDER; */
shell_root->AddRef(); _folder->AddRef();
_path = shell_root; _path = _folder;
}
ShellDirectory(const ShellDirectory& other)
: ShellEntry(other),
Directory(other),
_folder(other._folder),
_hwnd(other._hwnd)
{
IShellFolder* pFolder = (IShellFolder*)_path;
pFolder->AddRef();
} }
~ShellDirectory() ~ShellDirectory()

View file

@ -51,7 +51,8 @@ StartMenu::StartMenu(HWND hwnd, const StartMenuFolders& info)
: super(hwnd) : super(hwnd)
{ {
for(StartMenuFolders::const_iterator it=info.begin(); it!=info.end(); ++it) for(StartMenuFolders::const_iterator it=info.begin(); it!=info.end(); ++it)
_dirs.push_back(ShellDirectory(Desktop(), *it, _hwnd)); if (*it)
_dirs.push_back(ShellDirectory(Desktop(), *it, _hwnd));
_next_id = IDC_FIRST_MENU; _next_id = IDC_FIRST_MENU;
} }
@ -65,33 +66,50 @@ HWND StartMenu::Create(int x, int y, HWND hwndParent)
} }
*/ */
HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent) Window::CREATORFUNC StartMenu::s_def_creator = STARTMENU_CREATOR(StartMenu);
HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent, CREATORFUNC creator)
{ {
return Window::Create(WINDOW_CREATOR_INFO(StartMenu,StartMenuFolders), &folders, 0, s_wcStartMenu, NULL, return Window::Create(creator, &folders, 0, s_wcStartMenu, NULL,
WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, x, y, STARTMENU_WIDTH, 4, hwndParent); WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, x, y, STARTMENU_WIDTH, 4, hwndParent);
} }
LRESULT StartMenu::Init(LPCREATESTRUCT pcs) LRESULT StartMenu::Init(LPCREATESTRUCT pcs)
{ {
WaitCursor wait;
AddEntries();
if (super::Init(pcs)) if (super::Init(pcs))
return 1; return 1;
WaitCursor wait; for(ShellEntryMap::const_iterator it=_entries.begin(); it!=_entries.end(); ++it) {
const StartMenuEntry& sme = it->second;
for(StartMenuShellDirs::iterator it=_dirs.begin(); it!=_dirs.end(); ++it) {
ShellDirectory& dir = *it;
dir.smart_scan(); AddButton(sme._title, sme._hIcon, it->first);
AddShellEntries(dir);
} }
return 0; return 0;
} }
void StartMenu::AddShellEntries(const ShellDirectory& dir, bool subfolders) void StartMenu::AddEntries()
{ {
for(StartMenuShellDirs::iterator it=_dirs.begin(); it!=_dirs.end(); ++it) {
StartMenuDirectory& smd = *it;
ShellDirectory& dir = smd._dir;
dir.smart_scan();
AddShellEntries(dir, -1, smd._subfolders);
}
}
void StartMenu::AddShellEntries(const ShellDirectory& dir, int max, bool subfolders)
{
int cnt = 0;
for(const Entry*entry=dir._down; entry; entry=entry->_next) { for(const Entry*entry=dir._down; entry; entry=entry->_next) {
// hide files like "desktop.ini" // hide files like "desktop.ini"
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
@ -102,14 +120,17 @@ void StartMenu::AddShellEntries(const ShellDirectory& dir, bool subfolders)
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue; continue;
// only 'max' entries shall be added.
if (++cnt == max)
break;
const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry); const ShellEntry* shell_entry = static_cast<const ShellEntry*>(entry);
AddButton(dir._folder, shell_entry); AddEntry(dir._folder, shell_entry);
} }
} }
LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{ {
switch(nmsg) { switch(nmsg) {
@ -141,10 +162,13 @@ int StartMenu::Command(int id, int code)
break; break;
default: { default: {
ShellEntryMap::const_iterator found = _entry_map.find(id); ShellEntryMap::const_iterator found = _entries.find(id);
if (found != _entry_map.end()) { if (found != _entries.end()) {
ActivateEntry(const_cast<ShellEntry*>(found->second)); ShellEntry* entry = const_cast<ShellEntry*>(found->second._entry);
if (entry)
ActivateEntry(id, entry);
break; break;
} }
@ -154,11 +178,39 @@ int StartMenu::Command(int id, int code)
return 0; return 0;
} }
UINT StartMenu::AddButton(LPCTSTR text, HICON hIcon, UINT id)
StartMenuEntry& StartMenu::AddEntry(LPCTSTR title, HICON hIcon, UINT id)
{ {
if (id == (UINT)-1) if (id == (UINT)-1)
id = ++_next_id; id = ++_next_id;
StartMenuEntry& sme = _entries[id];
sme._title = title;
sme._hIcon = hIcon;
return sme;
}
StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, const ShellEntry* entry)
{
HICON hIcon = entry->_hicon;
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
hIcon = SmallIcon(IDI_EXPLORER);
const String& entry_name = folder.get_name(entry->_pidl);
StartMenuEntry& sme = AddEntry(entry_name, hIcon);
sme._entry = entry;
return sme;
}
void StartMenu::AddButton(LPCTSTR title, HICON hIcon, UINT id)
{
WindowRect rect(_hwnd); WindowRect rect(_hwnd);
rect.top -= STARTMENU_LINE_HEIGHT; rect.top -= STARTMENU_LINE_HEIGHT;
@ -170,36 +222,86 @@ UINT StartMenu::AddButton(LPCTSTR text, HICON hIcon, UINT id)
MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
StartMenuButton(_hwnd, rect.bottom-rect.top-STARTMENU_LINE_HEIGHT-4, text, id, hIcon); StartMenuButton(_hwnd, rect.bottom-rect.top-STARTMENU_LINE_HEIGHT-4, title, id, hIcon);
return id;
} }
UINT StartMenu::AddButton(const ShellFolder folder, const ShellEntry* entry) void StartMenu::AddSeparator()
{ {
HICON hIcon = entry->_hicon; WindowRect rect(_hwnd);
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) rect.top -= STARTMENU_SEP_HEIGHT;
hIcon = SmallIcon(IDI_EXPLORER);
const String& entry_name = folder.get_name(entry->_pidl); if (rect.top < 0) {
rect.top += STARTMENU_LINE_HEIGHT;
rect.bottom += STARTMENU_LINE_HEIGHT;
}
UINT id = AddButton(entry_name, hIcon); MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
_entry_map[id] = entry; StartMenuSeparator(_hwnd, rect.bottom-rect.top-STARTMENU_SEP_HEIGHT-4);
return id;
} }
void StartMenu::ActivateEntry(ShellEntry* entry)
void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, CREATORFUNC creator)
{
HWND btn = GetDlgItem(_hwnd, id);
int x, y;
if (btn) {
WindowRect pos(btn);
x = pos.right;
y = pos.top+STARTMENU_HEIGHT-4;
} else {
WindowRect pos(_hwnd);
x = pos.right;
y = pos.top+STARTMENU_HEIGHT-4;
}
StartMenu::Create(x, y, new_folders, _hwnd, creator);
}
void StartMenu::CreateSubmenu(int id, int folder_id, CREATORFUNC creator)
{
StartMenuFolders new_folders;
SpecialFolder folder(folder_id, _hwnd);
if (folder)
new_folders.push_back(folder);
CreateSubmenu(id, new_folders, creator);
}
void StartMenu::CreateSubmenu(int id, int folder_id1, int folder_id2, CREATORFUNC creator)
{
StartMenuFolders new_folders;
SpecialFolder folder1(folder_id1, _hwnd);
if (folder1)
new_folders.push_back(folder1);
if (folder_id2 != -1) {
SpecialFolder folder2(folder_id2, _hwnd);
if (folder2)
new_folders.push_back(folder2);
}
CreateSubmenu(id, new_folders, creator);
}
void StartMenu::ActivateEntry(int id, ShellEntry* entry)
{ {
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
StartMenuFolders new_folders; StartMenuFolders new_folders;
new_folders.push_back(entry->create_absolute_pidl(_hwnd)); new_folders.push_back(entry->create_absolute_pidl(_hwnd));
WindowRect my_pos(_hwnd); CreateSubmenu(id, new_folders);
StartMenu::Create(my_pos.right, my_pos.top+STARTMENU_HEIGHT-4, new_folders, _hwnd);
} else { } else {
entry->launch_entry(_hwnd); entry->launch_entry(_hwnd);
} }
@ -209,6 +311,13 @@ void StartMenu::ActivateEntry(ShellEntry* entry)
StartMenuRoot::StartMenuRoot(HWND hwnd) StartMenuRoot::StartMenuRoot(HWND hwnd)
: super(hwnd) : super(hwnd)
{ {
// insert directory "All Users\Start Menu"
ShellDirectory cmn_startmenu(Desktop(), SpecialFolder(CSIDL_COMMON_STARTMENU, _hwnd), _hwnd);
_dirs.push_back(StartMenuDirectory(cmn_startmenu, false)); // dont't add subfolders
// insert directory "<user name>\Start Menu"
ShellDirectory usr_startmenu(Desktop(), SpecialFolder(CSIDL_STARTMENU, _hwnd), _hwnd);
_dirs.push_back(StartMenuDirectory(usr_startmenu, false)); // dont't add subfolders
} }
HWND StartMenuRoot::Create(int x, int y, HWND hwndParent) HWND StartMenuRoot::Create(int x, int y, HWND hwndParent)
@ -219,29 +328,26 @@ HWND StartMenuRoot::Create(int x, int y, HWND hwndParent)
LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs) LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs)
{ {
// add buttons for entries in _entries
if (super::Init(pcs)) if (super::Init(pcs))
return 1; return 1;
WaitCursor wait; AddSeparator();
// insert start menu entries links from "All Users\Start Menu" and "<user name>\Start Menu"
ShellDirectory cmn_startmenu(Desktop(), SpecialFolder(CSIDL_COMMON_STARTMENU, _hwnd), _hwnd);
cmn_startmenu.read_directory();
AddShellEntries(cmn_startmenu, false);
ShellDirectory usr_startmenu(Desktop(), SpecialFolder(CSIDL_STARTMENU, _hwnd), _hwnd);
usr_startmenu.read_directory();
AddShellEntries(usr_startmenu, false);
// insert hard coded start entries // insert hard coded start entries
AddButton(ResString(IDS_PROGRAMS), 0, IDC_PROGRAMS); AddButton(ResString(IDS_PROGRAMS), 0, IDC_PROGRAMS);
AddButton(ResString(IDS_EXPLORE), SmallIcon(IDI_EXPLORER), IDC_EXPLORE); AddButton(ResString(IDS_EXPLORE), SmallIcon(IDI_EXPLORER), IDC_EXPLORE);
AddButton(ResString(IDS_FAVORITES), 0, IDC_FAVORITES); AddButton(ResString(IDS_FAVORITES), 0, IDC_FAVORITES);
AddButton(ResString(IDS_DOCUMENTS), 0, IDC_DOCUMENTS); AddButton(ResString(IDS_DOCUMENTS), 0, IDC_DOCUMENTS);
AddButton(ResString(IDS_RECENT), 0, IDC_RECENT);
AddButton(ResString(IDS_SETTINGS), 0, IDC_SETTINGS); AddButton(ResString(IDS_SETTINGS), 0, IDC_SETTINGS);
AddButton(ResString(IDS_ADMIN), 0, IDC_ADMIN);
AddButton(ResString(IDS_SEARCH), 0, IDC_SEARCH); AddButton(ResString(IDS_SEARCH), 0, IDC_SEARCH);
AddButton(ResString(IDS_START_HELP),0, IDC_START_HELP); AddButton(ResString(IDS_START_HELP),0, IDC_START_HELP);
AddButton(ResString(IDS_LAUNCH), 0, IDC_LAUNCH); AddButton(ResString(IDS_LAUNCH), 0, IDC_LAUNCH);
AddSeparator();
AddButton(ResString(IDS_SHUTDOWN), SmallIcon(IDI_LOGOFF), IDC_SHUTDOWN); AddButton(ResString(IDS_SHUTDOWN), SmallIcon(IDI_LOGOFF), IDC_SHUTDOWN);
AddButton(ResString(IDS_LOGOFF), SmallIcon(IDI_LOGOFF), IDC_LOGOFF); AddButton(ResString(IDS_LOGOFF), SmallIcon(IDI_LOGOFF), IDC_LOGOFF);
@ -251,20 +357,34 @@ LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs)
int StartMenuRoot::Command(int id, int code) int StartMenuRoot::Command(int id, int code)
{ {
switch(id) { switch(id) {
case IDC_PROGRAMS: { case IDC_PROGRAMS:
StartMenuFolders prg_folders; CreateSubmenu(id, CSIDL_COMMON_PROGRAMS, CSIDL_PROGRAMS);
break;
prg_folders.push_back(SpecialFolder(CSIDL_COMMON_PROGRAMS, _hwnd));
prg_folders.push_back(SpecialFolder(CSIDL_PROGRAMS, _hwnd));
WindowRect my_pos(_hwnd);
StartMenu::Create(my_pos.right, my_pos.top+STARTMENU_HEIGHT-4, prg_folders, _hwnd);
break;}
case IDC_EXPLORE: case IDC_EXPLORE:
explorer_show_frame(_hwnd, SW_SHOWNORMAL); explorer_show_frame(_hwnd, SW_SHOWNORMAL);
break; break;
case IDC_DOCUMENTS:
CreateSubmenu(id, CSIDL_PERSONAL);
break;
case IDC_RECENT:
CreateSubmenu(id, CSIDL_RECENT, STARTMENU_CREATOR(RecentStartMenu));
break;
case IDC_SETTINGS:
CreateSubmenu(id, CSIDL_CONTROLS);
break;
case IDC_FAVORITES:
CreateSubmenu(id, CSIDL_FAVORITES);
break;
case IDC_ADMIN:
CreateSubmenu(id, CSIDL_COMMON_ADMINTOOLS, CSIDL_ADMINTOOLS);
break;
case IDC_LOGOFF: case IDC_LOGOFF:
DestroyWindow(GetParent(_hwnd)); //TODO: show dialog and ask for acknowledge DestroyWindow(GetParent(_hwnd)); //TODO: show dialog and ask for acknowledge
break; break;
@ -279,3 +399,22 @@ int StartMenuRoot::Command(int id, int code)
return 0; return 0;
} }
RecentStartMenu::RecentStartMenu(HWND hwnd, const StartMenuFolders& info)
: super(hwnd, info)
{
}
void RecentStartMenu::AddEntries()
{
for(StartMenuShellDirs::iterator it=_dirs.begin(); it!=_dirs.end(); ++it) {
StartMenuDirectory& smd = *it;
ShellDirectory& dir = smd._dir;
dir.smart_scan();
dir.sort_directory(SORT_DATE);
AddShellEntries(dir, 16, smd._subfolders); //TODO: read max. count of entries from registry
}
}

View file

@ -36,9 +36,9 @@
// Startmenu button // Startmenu button
struct StartMenuButton : public Button struct StartMenuButton : public Button
{ {
StartMenuButton(HWND parent, int y, LPCTSTR text, StartMenuButton(HWND parent, int y, LPCTSTR title,
UINT id, HICON hIcon, DWORD style=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_OWNERDRAW, DWORD exStyle=0) UINT id, HICON hIcon=0, DWORD style=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_OWNERDRAW, DWORD exStyle=0)
: Button(parent, text, 2, y, STARTMENU_WIDTH-4, STARTMENU_LINE_HEIGHT, id, style, exStyle) : Button(parent, title, 2, y, STARTMENU_WIDTH-4, STARTMENU_LINE_HEIGHT, id, style, exStyle)
{ {
*new StartmenuEntry(_hwnd, hIcon); *new StartmenuEntry(_hwnd, hIcon);
@ -47,9 +47,41 @@ struct StartMenuButton : public Button
}; };
struct StartMenuSeparator : public Static
{
StartMenuSeparator(HWND parent, int y, DWORD style=WS_VISIBLE|WS_CHILD|SS_ETCHEDHORZ, DWORD exStyle=0)
: Static(parent, NULL, 2, y+STARTMENU_SEP_HEIGHT/2-1, STARTMENU_WIDTH-4, 2, -1, style, exStyle)
{
}
};
struct StartMenuDirectory
{
StartMenuDirectory(const ShellDirectory& dir, bool subfolders=true)
: _dir(dir), _subfolders(subfolders) {}
ShellDirectory _dir;
bool _subfolders;
};
typedef list<StartMenuDirectory> StartMenuShellDirs;
struct StartMenuEntry
{
StartMenuEntry() : _entry(NULL), _hIcon(0) {}
String _title;
HICON _hIcon;
const ShellEntry* _entry;
};
typedef map<UINT, StartMenuEntry> ShellEntryMap;
typedef list<ShellPath> StartMenuFolders; typedef list<ShellPath> StartMenuFolders;
typedef list<ShellDirectory> StartMenuShellDirs;
typedef map<UINT, const ShellEntry*> ShellEntryMap; #define STARTMENU_CREATOR(WND_CLASS) WINDOW_CREATOR_INFO(WND_CLASS, StartMenuFolders)
// Startmenu window // Startmenu window
@ -61,12 +93,13 @@ struct StartMenu : public OwnerDrawParent<Dialog>
StartMenu(HWND hwnd, const StartMenuFolders& info); StartMenu(HWND hwnd, const StartMenuFolders& info);
static HWND Create(int x, int y, HWND hwndParent=0); static HWND Create(int x, int y, HWND hwndParent=0);
static HWND Create(int x, int y, const StartMenuFolders&, HWND hwndParent=0); static HWND Create(int x, int y, const StartMenuFolders&, HWND hwndParent=0, CREATORFUNC creator=s_def_creator);
static CREATORFUNC s_def_creator;
protected: protected:
int _next_id; int _next_id;
ShellEntryMap _entries;
StartMenuShellDirs _dirs; StartMenuShellDirs _dirs;
ShellEntryMap _entry_map;
static BtnWindowClass s_wcStartMenu; static BtnWindowClass s_wcStartMenu;
@ -74,12 +107,20 @@ protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
int Command(int id, int code); int Command(int id, int code);
UINT AddButton(LPCTSTR text, HICON hIcon=0, UINT id=(UINT)-1); virtual void AddEntries();
UINT AddButton(const ShellFolder folder, const ShellEntry* entry);
void AddShellEntries(const ShellDirectory& dir, bool subfolders=true); StartMenuEntry& AddEntry(LPCTSTR title, HICON hIcon=0, UINT id=(UINT)-1);
StartMenuEntry& AddEntry(const ShellFolder folder, const ShellEntry* entry);
void ActivateEntry(ShellEntry* entry); void AddShellEntries(const ShellDirectory& dir, int max=-1, bool subfolders=true);
void AddButton(LPCTSTR title, HICON hIcon=0, UINT id=(UINT)-1);
void AddSeparator();
void CreateSubmenu(int id, const StartMenuFolders& new_folders, CREATORFUNC creator=s_def_creator);
void CreateSubmenu(int id, int folder1, int folder2, CREATORFUNC creator=s_def_creator);
void CreateSubmenu(int id, int folder, CREATORFUNC creator=s_def_creator);
void ActivateEntry(int id, ShellEntry* entry);
}; };
@ -96,3 +137,14 @@ protected:
LRESULT Init(LPCREATESTRUCT pcs); LRESULT Init(LPCREATESTRUCT pcs);
int Command(int id, int code); int Command(int id, int code);
}; };
struct RecentStartMenu : public StartMenu
{
typedef StartMenu super;
RecentStartMenu(HWND hwnd, const StartMenuFolders& info);
protected:
virtual void AddEntries();
};

View file

@ -37,6 +37,7 @@
#define STARTMENU_WIDTH 150 #define STARTMENU_WIDTH 150
#define STARTMENU_HEIGHT 4 #define STARTMENU_HEIGHT 4
#define STARTMENU_LINE_HEIGHT 22 #define STARTMENU_LINE_HEIGHT 22
#define STARTMENU_SEP_HEIGHT (STARTMENU_LINE_HEIGHT/2)
#define WM_SHELLHOOK_NOTIFY (WM_APP+0x10) #define WM_SHELLHOOK_NOTIFY (WM_APP+0x10)
@ -55,10 +56,12 @@
#define IDC_START_HELP 0x1004 #define IDC_START_HELP 0x1004
#define IDC_SEARCH 0x1005 #define IDC_SEARCH 0x1005
#define IDC_SETTINGS 0x1006 #define IDC_SETTINGS 0x1006
#define IDC_DOCUMENTS 0x1007 #define IDC_ADMIN 0x1007
#define IDC_FAVORITES 0x1008 #define IDC_DOCUMENTS 0x1008
#define IDC_PROGRAMS 0x1009 #define IDC_RECENT 0x1009
#define IDC_EXPLORE 0x100A #define IDC_FAVORITES 0x100A
#define IDC_PROGRAMS 0x100B
#define IDC_EXPLORE 0x100C
#define IDC_FIRST_APP 0x2000 #define IDC_FIRST_APP 0x2000
#define IDC_FIRST_MENU 0x3000 #define IDC_FIRST_MENU 0x3000

View file

@ -139,7 +139,7 @@ ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl)
{ {
IShellFolder* ptr; IShellFolder* ptr;
if (pidl->mkid.cb) if (pidl && pidl->mkid.cb)
CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr)); CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr));
else else
ptr = parent; ptr = parent;
@ -153,7 +153,7 @@ ShellFolder::ShellFolder(LPCITEMIDLIST pidl)
IShellFolder* ptr; IShellFolder* ptr;
IShellFolder* parent = Desktop(); IShellFolder* parent = Desktop();
if (pidl->mkid.cb) if (pidl && pidl->mkid.cb)
CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr)); CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr));
else else
ptr = parent; ptr = parent;
@ -166,7 +166,7 @@ void ShellFolder::attach(IShellFolder* parent, LPCITEMIDLIST pidl)
{ {
IShellFolder* ptr; IShellFolder* ptr;
if (pidl->mkid.cb) if (pidl && pidl->mkid.cb)
CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr)); CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&ptr));
else else
ptr = parent; ptr = parent;
@ -192,7 +192,7 @@ ShellFolder::ShellFolder(IShellFolder* p)
ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl) ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl)
{ {
if (pidl->mkid.cb) if (pidl && pidl->mkid.cb)
CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p));
else else
_p = Desktop(); _p = Desktop();
@ -202,7 +202,7 @@ ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl)
ShellFolder::ShellFolder(LPCITEMIDLIST pidl) ShellFolder::ShellFolder(LPCITEMIDLIST pidl)
{ {
if (pidl->mkid.cb) if (pidl && pidl->mkid.cb)
CheckError(Desktop()->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); CheckError(Desktop()->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p));
else else
_p = Desktop(); _p = Desktop();

View file

@ -58,11 +58,11 @@ IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPRO
HHOOK Window::s_hcbtHook = 0; HHOOK Window::s_hcbtHook = 0;
Window::WINDOWCREATORFUNC Window::s_window_creator = NULL; Window::CREATORFUNC Window::s_window_creator = NULL;
const void* Window::s_new_info = NULL; const void* Window::s_new_info = NULL;
HWND Window::Create(WINDOWCREATORFUNC creator, DWORD dwExStyle, HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle,
LPCTSTR lpClassName, LPCTSTR lpWindowName, LPCTSTR lpClassName, LPCTSTR lpWindowName,
DWORD dwStyle, int x, int y, int w, int h, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent, HMENU hMenu, LPVOID lpParam) HWND hwndParent, HMENU hMenu, LPVOID lpParam)
@ -75,7 +75,7 @@ HWND Window::Create(WINDOWCREATORFUNC creator, DWORD dwExStyle,
hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/); hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/);
} }
HWND Window::Create(WINDOWCREATORFUNC creator, const void* info, DWORD dwExStyle, HWND Window::Create(CREATORFUNC creator, const void* info, DWORD dwExStyle,
LPCTSTR lpClassName, LPCTSTR lpWindowName, LPCTSTR lpClassName, LPCTSTR lpWindowName,
DWORD dwStyle, int x, int y, int w, int h, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent, HMENU hMenu, LPVOID lpParam) HWND hwndParent, HMENU hMenu, LPVOID lpParam)
@ -91,7 +91,7 @@ HWND Window::Create(WINDOWCREATORFUNC creator, const void* info, DWORD dwExStyle
static Window* s_new_child_wnd = NULL; static Window* s_new_child_wnd = NULL;
Window* Window::create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, WINDOWCREATORFUNC creator, const void* info) Window* Window::create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info)
{ {
s_window_creator = creator; s_window_creator = creator;
s_new_info = info; s_new_info = info;
@ -141,7 +141,7 @@ Window* Window::get_window(HWND hwnd)
const void* info = s_new_info; const void* info = s_new_info;
s_new_info = NULL; s_new_info = NULL;
WINDOWCREATORFUNC window_creator = s_window_creator; CREATORFUNC window_creator = s_window_creator;
s_window_creator = NULL; s_window_creator = NULL;
wnd = window_creator(hwnd, info); wnd = window_creator(hwnd, info);
@ -227,7 +227,7 @@ ChildWindow::ChildWindow(HWND hwnd)
} }
ChildWindow* ChildWindow::create(HWND hmdiclient, const RECT& rect, WINDOWCREATORFUNC creator, LPCTSTR classname, LPCTSTR title) ChildWindow* ChildWindow::create(HWND hmdiclient, const RECT& rect, CREATORFUNC creator, LPCTSTR classname, LPCTSTR title)
{ {
MDICREATESTRUCT mcs; MDICREATESTRUCT mcs;
@ -464,7 +464,7 @@ int Window::MessageLoop()
Button::Button(HWND parent, LPCTSTR text, int left, int top, int width, int height, Button::Button(HWND parent, LPCTSTR text, int left, int top, int width, int height,
UINT id, DWORD flags, DWORD exStyle) int id, DWORD flags, DWORD exStyle)
{ {
_hwnd = CreateWindowEx(exStyle, TEXT("BUTTON"), text, flags, left, top, width, height, _hwnd = CreateWindowEx(exStyle, TEXT("BUTTON"), text, flags, left, top, width, height,
parent, (HMENU)id, g_Globals._hInstance, 0); parent, (HMENU)id, g_Globals._hInstance, 0);
@ -481,6 +481,14 @@ LRESULT OwnerdrawnButton::WndProc(UINT message, WPARAM wparam, LPARAM lparam)
} }
Static::Static(HWND parent, LPCTSTR text, int left, int top, int width, int height,
int id, DWORD flags, DWORD exStyle)
{
_hwnd = CreateWindowEx(exStyle, TEXT("STATIC"), text, flags, left, top, width, height,
parent, (HMENU)id, g_Globals._hInstance, 0);
}
static RECT s_MyDrawText_Rect = {0, 0, 0, 0}; static RECT s_MyDrawText_Rect = {0, 0, 0, 0};
static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt) static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt)

View file

@ -68,19 +68,19 @@ struct Window
operator HWND() const {return _hwnd;} operator HWND() const {return _hwnd;}
typedef Window* (*WINDOWCREATORFUNC)(HWND, const void*); typedef Window* (*CREATORFUNC)(HWND, const void*);
static HWND Create(WINDOWCREATORFUNC creator, DWORD dwExStyle, static HWND Create(CREATORFUNC creator, DWORD dwExStyle,
LPCTSTR lpClassName, LPCTSTR lpWindowName, LPCTSTR lpClassName, LPCTSTR lpWindowName,
DWORD dwStyle, int x, int y, int w, int h, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0); HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0);
static HWND Create(WINDOWCREATORFUNC creator, const void* info, static HWND Create(CREATORFUNC creator, const void* info,
DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
DWORD dwStyle, int x, int y, int w, int h, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0); HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0);
static Window* create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, WINDOWCREATORFUNC creator, const void* info=NULL); static Window* create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info=NULL);
static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
static Window* get_window(HWND hwnd); static Window* get_window(HWND hwnd);
@ -108,7 +108,7 @@ protected:
static const void* s_new_info; //TODO: protect for multithreaded access static const void* s_new_info; //TODO: protect for multithreaded access
static WINDOWCREATORFUNC s_window_creator; //TODO: protect for multithreaded access static CREATORFUNC s_window_creator; //TODO: protect for multithreaded access
// MDI child creation // MDI child creation
static HHOOK s_hcbtHook; static HHOOK s_hcbtHook;
@ -147,7 +147,7 @@ template<typename WND_CLASS> struct WindowCreator
}; };
#define WINDOW_CREATOR(WND_CLASS) \ #define WINDOW_CREATOR(WND_CLASS) \
(Window::WINDOWCREATORFUNC) WindowCreator<WND_CLASS>::window_creator (Window::CREATORFUNC) WindowCreator<WND_CLASS>::window_creator
template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo
@ -159,7 +159,7 @@ template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo
}; };
#define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \ #define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \
(Window::WINDOWCREATORFUNC) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator (Window::CREATORFUNC) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator
/** /**
@ -239,7 +239,7 @@ struct ChildWindow : public Window
ChildWindow(HWND hwnd); ChildWindow(HWND hwnd);
static ChildWindow* create(HWND hmdiclient, const RECT& rect, static ChildWindow* create(HWND hmdiclient, const RECT& rect,
WINDOWCREATORFUNC creator, LPCTSTR classname, LPCTSTR title=NULL); CREATORFUNC creator, LPCTSTR classname, LPCTSTR title=NULL);
protected: protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
@ -295,7 +295,24 @@ struct Dialog : public Window
struct Button struct Button
{ {
Button(HWND parent, LPCTSTR text, int left, int top, int width, int height, Button(HWND parent, LPCTSTR text, int left, int top, int width, int height,
UINT id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD ex_flags=0); int id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD exStyle=0);
operator HWND() const {return _hwnd;}
protected:
HWND _hwnd;
};
/**
This class constructs static controls.
The control will remain existent when the C++ object is destroyed.
There is no conjunction between C++ object and windows control life time.
*/
struct Static
{
Static(HWND parent, LPCTSTR text, int left, int top, int width, int height,
int id, DWORD flags=WS_VISIBLE|WS_CHILD|SS_SIMPLE, DWORD ex_flags=0);
operator HWND() const {return _hwnd;} operator HWND() const {return _hwnd;}