//
- // Explorer clone, lean version
+ // Explorer clone
//
// startmenu.cpp
//
#include "desktopbar.h"
#include "startmenu.h"
+#include "../dialogs/searchprogram.h"
#include "../dialogs/settings.h"
Window::CREATORFUNC_INFO StartMenu::s_def_creator = STARTMENU_CREATOR(StartMenu);
-HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent, LPCTSTR title, CREATORFUNC_INFO creator)
+HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent, LPCTSTR title, CREATORFUNC_INFO creator, void* info)
{
UINT style, ex_style;
int top_height;
create_info._folders = folders;
create_info._border_top = top_height;
create_info._creator = creator;
+ create_info._info = info;
if (title)
create_info._title = title;
WaitCursor wait;
#ifdef _LAZY_ICONEXTRACT
- dir.smart_scan(SCAN_FILESYSTEM); // lazy icon extraction, try to read directly from filesystem
+ dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM); // lazy icon extraction, try to read directly from filesystem
#else
- dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+ dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
#endif
}
WindowRect pos(_hwnd);
///@todo do something similar to StartMenuRoot::TrackStartmenu() in order to automatically close submenus when clicking on the desktop background
- StartMenu::Create(pos.left+3, pos.bottom-3, _create_info._folders, 0, _create_info._title, _create_info._creator);
+ StartMenu::Create(pos.left+3, pos.bottom-3, _create_info._folders, 0, _create_info._title, _create_info._creator, _create_info._info);
CloseStartMenu();
}
int new_id = ButtonHitTest(pt);
- if (new_id != _selected_id)
+ if (new_id > 0 && new_id != _selected_id)
SelectButton(new_id);
_last_mouse_pos = lparam;
break;
case PM_SELECT_ENTRY:
- SelectButtonIndex(0, wparam?true:false);
+ SelectButtonIndex(0, wparam!=0);
break;
+#ifdef _LIGHT_STARTMENU
+ case WM_CONTEXTMENU: {
+ Point screen_pt(lparam), clnt_pt=screen_pt;
+ ScreenToClient(_hwnd, &clnt_pt);
+
+ int id = ButtonHitTest(clnt_pt);
+
+ if (id) {
+ StartMenuEntry& sme = _entries[id];
+
+ for(ShellEntrySet::iterator it=sme._entries.begin(); it!=sme._entries.end(); ++it) {
+ Entry* entry = *it;
+
+ if (entry) {
+ CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs)); // may close start menu because of focus loss
+ break; ///@todo handle context menu for more than one entry
+ }
+ }
+ }
+ break;}
+#endif
+
default: def:
return super::WndProc(nmsg, wparam, lparam);
}
void StartMenu::InvalidateSelection()
{
- if (!_selected_id)
+ if (_selected_id <= 0)
return;
ClientRect clnt(_hwnd);
}
-StartMenuEntry& StartMenu::AddEntry(const String& title, ICON_ID icon_id, Entry* entry)
+ShellEntryMap::iterator StartMenu::AddEntry(const String& title, ICON_ID icon_id, 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
+ if (!_tcsicmp(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;
+
+ return it;
}
}
}
- StartMenuEntry& sme = AddEntry(title, icon_id);
+ ShellEntryMap::iterator sme = AddEntry(title, icon_id);
- sme._entries.insert(entry);
+ sme->second._entries.insert(entry);
return sme;
}
-StartMenuEntry& StartMenu::AddEntry(const String& title, ICON_ID icon_id, int id)
+ShellEntryMap::iterator StartMenu::AddEntry(const String& title, ICON_ID icon_id, int id)
{
if (id == -1)
id = ++_next_id;
- StartMenuEntry& sme = _entries[id];
+ StartMenuEntry sme;
sme._title = title;
sme._icon_id = icon_id;
- return sme;
+ ShellEntryMap::iterator it = _entries.insert(make_pair(id, sme)).first;
+
+ return it;
}
-StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, ShellEntry* entry)
+ShellEntryMap::iterator StartMenu::AddEntry(const ShellFolder folder, ShellEntry* entry)
{
ICON_ID icon_id;
return AddEntry(folder.get_name(entry->_pidl), icon_id, entry);
}
-StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, Entry* entry)
+ShellEntryMap::iterator StartMenu::AddEntry(const ShellFolder folder, Entry* entry)
{
ICON_ID icon_id;
}
-void StartMenu::CreateSubmenu(int id, LPCTSTR title, CREATORFUNC_INFO creator)
+void StartMenu::CreateSubmenu(int id, LPCTSTR title, CREATORFUNC_INFO creator, void* info)
{
- CreateSubmenu(id, StartMenuFolders(), title, creator);
+ CreateSubmenu(id, StartMenuFolders(), title, creator, info);
}
-bool StartMenu::CreateSubmenu(int id, int folder_id, LPCTSTR title, CREATORFUNC_INFO creator)
+bool StartMenu::CreateSubmenu(int id, int folder_id, LPCTSTR title, CREATORFUNC_INFO creator, void* info)
{
try {
SpecialFolderPath folder(folder_id, _hwnd);
StartMenuFolders new_folders;
new_folders.push_back(folder);
- CreateSubmenu(id, new_folders, title, creator);
+ CreateSubmenu(id, new_folders, title, creator, info);
return true;
} catch(COMException&) {
}
}
-bool StartMenu::CreateSubmenu(int id, int folder_id1, int folder_id2, LPCTSTR title, CREATORFUNC_INFO creator)
+bool StartMenu::CreateSubmenu(int id, int folder_id1, int folder_id2, LPCTSTR title, CREATORFUNC_INFO creator, void* info)
{
StartMenuFolders new_folders;
}
if (!new_folders.empty()) {
- CreateSubmenu(id, new_folders, title, creator);
+ CreateSubmenu(id, new_folders, title, creator, info);
return true;
} else {
CloseOtherSubmenus(id);
}
}
-void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTSTR title, CREATORFUNC_INFO creator)
+void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTSTR title, CREATORFUNC_INFO creator, void* info)
{
// Only open one submenu at a time.
if (!CloseOtherSubmenus(id))
}
_submenu_id = id;
- _submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, creator);
+ _submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, creator, info);
}
HWND hparent = GetParent(_hwnd);
ShellPath shell_path = entry->create_absolute_pidl();
- // close start menus after launching the selected entry
+ // close start menus when launching the selected entry
CloseStartMenu(id);
///@todo launch in the background; specify correct HWND for error message box titles
SHELLEXECUTEINFO shexinfo;
shexinfo.cbSize = sizeof(SHELLEXECUTEINFO);
- shexinfo.fMask = SEE_MASK_INVOKEIDLIST; // SEE_MASK_IDLIST is also possible.
+ shexinfo.fMask = SEE_MASK_IDLIST; // SEE_MASK_INVOKEIDLIST is also possible.
shexinfo.hwnd = hparent;
shexinfo.lpVerb = NULL;
shexinfo.lpFile = NULL;
AddButton(ResString(IDS_SETTINGS), ICID_CONFIG, true, IDC_SETTINGS);
+ AddButton(ResString(IDS_BROWSE), ICID_FOLDER, true, IDC_BROWSE);
+
#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
if (!g_Globals._SHRestricted || !SHRestricted(REST_NOFIND))
#else
break;
case IDC_FAVORITES:
- CreateSubmenu(id, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
+#ifndef _SHELL32_FAVORITES
+ CreateSubmenu(id, ResString(IDS_FAVORITES), STARTMENU_CREATOR(FavoritesMenu), &static_cast<BookmarkList&>(g_Globals._favorites));
+#else
+ CreateSubmenu(id, CSIDL_COMMON_FAVORITES, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
+#endif
+ break;
+
+ case IDC_BROWSE:
+ CreateSubmenu(id, ResString(IDS_BROWSE), STARTMENU_CREATOR(BrowseMenu));
break;
case IDC_SETTINGS:
ExplorerPropertySheet(g_Globals._hwndDesktopBar);
break;
- case IDC_CONTROL_PANEL:
+ case IDC_CONTROL_PANEL: {
CloseStartMenu(id);
#ifndef ROSSHELL
- MainFrame::Create(SHELLPATH_CONTROL_PANEL, 0);
+#ifndef _NO_MDI
+ XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
+ bool mdi = XMLBool(explorer_options, "mdi", true);
+
+ if (mdi)
+ MDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
+ else
+#endif
+ SDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
#else
launch_file(_hwnd, SHELLPATH_CONTROL_PANEL);
#endif
+ break;}
+
+ case IDC_SETTINGS_MENU:
+ CreateSubmenu(id, CSIDL_CONTROLS, ResString(IDS_SETTINGS_MENU));
break;
- case IDC_PRINTERS:
+ case IDC_PRINTERS: {
CloseStartMenu(id);
+
#ifndef ROSSHELL
- MainFrame::Create(SpecialFolderPath(CSIDL_PRINTERS, _hwnd), OWM_PIDL);
+#ifdef _ROS_ // to be removed when printer folder will be implemented
+ MessageBox(0, TEXT("printer folder not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+#else
+#ifndef _NO_MDI
+ XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
+ bool mdi = XMLBool(explorer_options, "mdi", true);
+
+ if (mdi)
+ MDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"), 0);
+ else
+#endif
+ SDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"), 0);
+#endif
#else
launch_file(_hwnd, SHELLPATH_PRINTERS);
+#endif
+ break;}
+
+ case IDC_PRINTERS_MENU:
+ CreateSubmenu(id, CSIDL_PRINTERS, CSIDL_PRINTHOOD, ResString(IDS_PRINTERS));
+/* StartMenuFolders new_folders;
+
+ try {
+ new_folders.push_back(ShellPath(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}")));
+ } catch(COMException&) {
+ }
+
+ CreateSubmenu(id, new_folders, ResString(IDS_PRINTERS));*/
+ break;
+
+ case IDC_ADMIN:
+#ifndef ROSSHELL
+ CreateSubmenu(id, CSIDL_COMMON_ADMINTOOLS, CSIDL_ADMINTOOLS, ResString(IDS_ADMIN));
+ //CloseStartMenu(id);
+ //MainFrame::Create(SpecialFolderPath(CSIDL_COMMON_ADMINTOOLS, _hwnd), OWM_PIDL);
+#else
+ launch_file(_hwnd, SpecialFolderFSPath(CSIDL_COMMON_ADMINTOOLS, _hwnd));
#endif
break;
case IDC_CONNECTIONS:
- CloseStartMenu(id);
#ifndef ROSSHELL
- MainFrame::Create(SpecialFolderPath(CSIDL_CONNECTIONS, _hwnd), OWM_PIDL);
+#ifdef _ROS_ // to be removed when RAS will be implemented
+ MessageBox(0, TEXT("RAS folder not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+#else
+ CreateSubmenu(id, CSIDL_CONNECTIONS, ResString(IDS_CONNECTIONS));
+ //CloseStartMenu(id);
+ //MainFrame::Create(SpecialFolderPath(CSIDL_CONNECTIONS, _hwnd), OWM_PIDL);
+#endif
#else
launch_file(_hwnd, SHELLPATH_NET_CONNECTIONS);
#endif
break;
- case IDC_ADMIN:
- CloseStartMenu(id);
-#ifndef ROSSHELL
- MainFrame::Create(SpecialFolderPath(CSIDL_COMMON_ADMINTOOLS, _hwnd), OWM_PIDL);
+
+ // browse menu
+
+ case IDC_NETWORK:
+#ifdef _ROS_ // to be removed when network will be implemented
+ MessageBox(0, TEXT("network not yet implemented"), ResString(IDS_TITLE), MB_OK);
#else
- launch_file(_hwnd, SpecialFolderFSPath(CSIDL_COMMON_ADMINTOOLS, _hwnd));
+ CreateSubmenu(id, CSIDL_NETWORK, ResString(IDS_NETWORK));
#endif
break;
+ case IDC_DRIVES:
+ ///@todo exclude removable drives
+ CreateSubmenu(id, CSIDL_DRIVES, ResString(IDS_DRIVES));
+ break;
+
// search menu
+ case IDC_SEARCH_PROGRAM:
+ CloseStartMenu(id);
+ Dialog::DoModal(IDD_SEARCH_PROGRAM, WINDOW_CREATOR(FindProgramDlg));
+ break;
+
case IDC_SEARCH_FILES:
CloseStartMenu(id);
ShowSearchDialog();
// Show "Run..." dialog
if (RunFileDlg) {
#ifndef _ROS_ /* FIXME: our shell32 always expects Ansi strings */
-#define W_VER_NT 0
if ((HIWORD(GetVersion())>>14) == W_VER_NT) {
WCHAR wTitle[40], wText[256];
{
super::AddEntries();
+#ifdef _ROS_ // to be removed when printer/network will be implemented
+ AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, false, IDC_PRINTERS_MENU);
+ AddButton(ResString(IDS_CONNECTIONS), ICID_NETWORK, false, IDC_CONNECTIONS);
+#else
+ AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, true, IDC_PRINTERS_MENU);
+ AddButton(ResString(IDS_CONNECTIONS), ICID_NETWORK, true, IDC_CONNECTIONS);
+#endif
+ AddButton(ResString(IDS_ADMIN), ICID_CONFIG, true, IDC_ADMIN);
+
+#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
+ if (!g_Globals._SHRestricted || !SHRestricted(REST_NOCONTROLPANEL))
+#endif
+ AddButton(ResString(IDS_SETTINGS_MENU), ICID_CONFIG, true, IDC_SETTINGS_MENU);
+
+ AddButton(ResString(IDS_DESKTOPBAR_SETTINGS), ICID_CONFIG, false, ID_DESKTOPBAR_SETTINGS);
+
+ AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, false, IDC_PRINTERS);
+
#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
if (!g_Globals._SHRestricted || !SHRestricted(REST_NOCONTROLPANEL))
#endif
AddButton(ResString(IDS_CONTROL_PANEL), ICID_CONFIG, false, IDC_CONTROL_PANEL);
+}
- AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, false, IDC_PRINTERS);
- AddButton(ResString(IDS_CONNECTIONS), ICID_NETWORK, false, IDC_CONNECTIONS);
- AddButton(ResString(IDS_ADMIN), ICID_CONFIG, false, IDC_ADMIN);
+void BrowseMenu::AddEntries()
+{
+ super::AddEntries();
- AddButton(ResString(IDS_DESKTOPBAR_SETTINGS), ICID_CONFIG, false, ID_DESKTOPBAR_SETTINGS);
+#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
+ if (!g_Globals._SHRestricted || !SHRestricted(REST_NONETHOOD)) // or REST_NOENTIRENETWORK ?
+#endif
+#ifdef _ROS_ // to be removed when printer/network will be implemented
+ AddButton(ResString(IDS_NETWORK), ICID_NETWORK, false, IDC_NETWORK);
+#else
+ AddButton(ResString(IDS_NETWORK), ICID_NETWORK, true, IDC_NETWORK);
+#endif
+
+ AddButton(ResString(IDS_DRIVES), ICID_FOLDER, true, IDC_DRIVES);
}
void SearchMenu::AddEntries()
{
super::AddEntries();
- AddButton(ResString(IDS_SEARCH_FILES), ICID_SEARCH_DOC, false, IDC_SEARCH_FILES);
+ AddButton(ResString(IDS_SEARCH_FILES), ICID_SEARCH_DOC, false, IDC_SEARCH_FILES);
#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
if (!g_Globals._SHRestricted || !SHRestricted(REST_HASFINDCOMPUTERS))
#endif
- AddButton(ResString(IDS_SEARCH_COMPUTER), ICID_COMPUTER, false, IDC_SEARCH_COMPUTER);
+ AddButton(ResString(IDS_SEARCH_COMPUTER),ICID_COMPUTER, false, IDC_SEARCH_COMPUTER);
+
+ AddButton(ResString(IDS_SEARCH_PRG), ICID_APPS, false, IDC_SEARCH_PROGRAM);
}
WaitCursor wait;
#ifdef _LAZY_ICONEXTRACT
- dir.smart_scan(SCAN_FILESYSTEM);
+ dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);
#else
- dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+ dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
#endif
}
dir.sort_directory(SORT_DATE);
- AddShellEntries(dir, RECENT_DOCS_COUNT, smd._subfolders); ///@todo read max. count of entries from registry
+ AddShellEntries(dir, RECENT_DOCS_COUNT, smd._subfolders);
}
}
+
+
+#ifndef _SHELL32_FAVORITES
+
+void FavoritesMenu::AddEntries()
+{
+ super::AddEntries();
+
+ for(BookmarkList::iterator it=_bookmarks.begin(); it!=_bookmarks.end(); ++it) {
+ BookmarkNode& node = *it;
+
+ int id = ++_next_id;
+
+ _entries[id] = node;
+
+ if (node._type == BookmarkNode::BMNT_FOLDER) {
+ BookmarkFolder& folder = *node._pfolder;
+
+ AddButton(folder._name, ICID_FOLDER, true, id);
+ } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
+ Bookmark& bookmark = *node._pbookmark;
+
+ ICON_ID icon = ICID_NONE;
+
+ if (!bookmark._icon_path.empty())
+ icon = g_Globals._icon_cache.extract(bookmark._icon_path, bookmark._icon_idx);
+
+ AddButton(bookmark._name, icon!=ICID_NONE?icon:ICID_BOOKMARK, false, id);
+ }
+ }
+}
+
+int FavoritesMenu::Command(int id, int code)
+{
+ BookmarkMap::iterator found = _entries.find(id);
+
+ if (found != _entries.end()) {
+ BookmarkNode& node = found->second;
+
+ if (node._type == BookmarkNode::BMNT_FOLDER) {
+ BookmarkFolder& folder = *node._pfolder;
+
+ if (CloseOtherSubmenus(id))
+ CreateSubmenu(id, folder._name, STARTMENU_CREATOR(FavoritesMenu), &static_cast<BookmarkList&>(folder._bookmarks));
+ } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
+ Bookmark& bookmark = *node._pbookmark;
+
+ String url = bookmark._url;
+ HWND hparent = GetParent(_hwnd);
+
+ CloseStartMenu(id);
+
+ launch_file(hparent, url, SW_SHOWNORMAL);
+ }
+
+ return 0;
+ }
+
+ return super::Command(id, code);
+}
+
+#endif