//
- // Explorer clone, lean version
+ // Explorer clone
//
// startmenu.cpp
//
//
-#include "../utility/utility.h"
+#include <precomp.h>
-#include "../explorer.h"
-#include "../globals.h"
-#include "../externals.h"
-#include "../explorer_intres.h"
+#include "../resource.h"
#include "desktopbar.h"
#include "startmenu.h"
+#include "../dialogs/searchprogram.h"
#include "../dialogs/settings.h"
-StartMenu::StartMenu(HWND hwnd)
- : super(hwnd)
+#define SHELLPATH_CONTROL_PANEL TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}")
+#define SHELLPATH_PRINTERS TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}")
+#define SHELLPATH_NET_CONNECTIONS TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}")
+
+
+StartMenu::StartMenu(HWND hwnd, bool large_icons)
+ : super(hwnd),
+ _large_icons(large_icons)
{
_next_id = IDC_FIRST_MENU;
_submenu_id = 0;
#endif
}
-StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
+StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info, bool large_icons)
: super(hwnd),
- _create_info(create_info)
+ _create_info(create_info),
+ _large_icons(large_icons)
{
for(StartMenuFolders::const_iterator it=create_info._folders.begin(); it!=create_info._folders.end(); ++it)
if (*it)
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, const String& filter)
{
UINT style, ex_style;
int top_height;
top_height = 0;
}
+ bool large_icons = false;
RECT rect = {x, y-STARTMENU_LINE_HEIGHT-top_height, x+STARTMENU_WIDTH_MIN, y};
#ifndef _LIGHT_STARTMENU
create_info._folders = folders;
create_info._border_top = top_height;
create_info._creator = creator;
+ create_info._info = info;
+ create_info._filter = filter;
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_DONT_EXTRACT_ICONS); // lazy icon extraction, try to read directly from filesystem
#else
- dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+ dir.smart_scan(SORT_NAME);
#endif
}
- AddShellEntries(dir, -1, smd._subfolders);
+ AddShellEntries(dir, -1, smd._ignore);
}
}
-void StartMenu::AddShellEntries(const ShellDirectory& dir, int max, bool subfolders)
+static LPTSTR trim_path_slash(LPTSTR path)
{
- int cnt = 0;
+ LPTSTR p = path;
+
+ while(*p)
+ ++p;
+
+ if (p>path && (p[-1]=='\\' || p[-1]=='/'))
+ *--p = '\0';
+
+ return path;
+}
+
+void StartMenu::AddShellEntries(const ShellDirectory& dir, int max, const String& ignore)
+{
+ TCHAR ignore_path[MAX_PATH], ignore_dir[MAX_PATH], ignore_name[_MAX_FNAME], ignore_ext[_MAX_EXT];
+ TCHAR dir_path[MAX_PATH];
+
+ if (!ignore.empty()) {
+ _tsplitpath_s(ignore, ignore_path, COUNTOF(ignore_path), ignore_dir, COUNTOF(ignore_dir), ignore_name, COUNTOF(ignore_name), ignore_ext, COUNTOF(ignore_ext));
+
+ _tcscat(ignore_path, ignore_dir);
+ _tcscat(ignore_name, ignore_ext);
+ dir.get_path(dir_path, COUNTOF(dir_path));
+
+ if (_tcsicmp(trim_path_slash(dir_path), trim_path_slash(ignore_path)))
+ *ignore_name = '\0';
+ } else
+ *ignore_name = '\0';
+
+ String lwr_filter = _create_info._filter;
+ lwr_filter.toLower();
+
+ int cnt = 0;
for(Entry*entry=dir._down; entry; entry=entry->_next) {
// hide files like "desktop.ini"
if (entry->_shell_attribs & SFGAO_HIDDEN)
//not appropriate for drive roots: if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
continue;
- // hide subfolders if requested
- if (!subfolders)
- if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- continue;
+ // hide "Programs" subfolders if requested
+ if (*ignore_name && !_tcsicmp(entry->_data.cFileName, ignore_name))
+ continue;
// only 'max' entries shall be added.
if (++cnt == max)
break;
+ // filter only non-directory entries
+ if (!(entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && !lwr_filter.empty()) {
+ String lwr_name = entry->_data.cFileName;
+ String lwr_disp = entry->_display_name;
+
+ lwr_name.toLower();
+ lwr_disp.toLower();
+
+ if (!_tcsstr(lwr_name,lwr_filter) && !_tcsstr(lwr_disp,lwr_filter))
+ continue;
+ }
+
if (entry->_etype == ET_SHELL)
AddEntry(dir._folder, static_cast<ShellEntry*>(entry));
else
break;
case WM_MOVE: {
- POINTS& pos = MAKEPOINTS(lparam);
+ const POINTS& pos = MAKEPOINTS(lparam);
// move open submenus of floating menus
if (_submenu) {
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();
}
if (_arrow_btns) {
RECT rect_up, rect_down;
- GetArrowButtonRects(&rect_up, &rect_down);
+ GetArrowButtonRects(&rect_up, &rect_down, _large_icons);
SCROLL_MODE scroll_mode = SCROLL_NOT;
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);
}
int StartMenu::ButtonHitTest(POINT pt)
{
ClientRect clnt(_hwnd);
+ const bool large_icons = _large_icons;
RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
if (pt.x<rect.left || pt.x>rect.right)
void StartMenu::InvalidateSelection()
{
- if (!_selected_id)
+ if (_selected_id <= 0)
return;
ClientRect clnt(_hwnd);
+ const bool large_icons = _large_icons;
RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
{
#ifdef _LIGHT_STARTMENU
ClientRect clnt(_hwnd);
+ const bool large_icons = _large_icons;
RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
}
-void StartMenu::DrawArrows(HDC hdc)
+void StartMenu::DrawArrows(HDC hdc, bool large_icons)
{
- static ResIconEx arrowUpIcon(IDI_ARROW_UP, 8, 4);
- static ResIconEx arrowDownIcon(IDI_ARROW_DOWN, 8, 4);
+ int cx = large_icons? 16: 8;
+ int cy = large_icons? 8: 4;
+
+ ResIconEx arrowUpIcon(IDI_ARROW_UP, cx, cy);
+ ResIconEx arrowDownIcon(IDI_ARROW_DOWN, cx, cy);
ClientRect clnt(_hwnd);
- DrawIconEx(hdc, clnt.right/2-4, _floating_btn?3:1, arrowUpIcon, 8, 4, 0, 0, DI_NORMAL);
- DrawIconEx(hdc, clnt.right/2-4, clnt.bottom-5, arrowDownIcon, 8, 4, 0, 0, DI_NORMAL);
+ DrawIconEx(hdc, clnt.right/2-cx/2, _floating_btn?3:1, arrowUpIcon, cx, cy, 0, 0, DI_NORMAL);
+ DrawIconEx(hdc, clnt.right/2-cx/2, clnt.bottom-cy-1, arrowDownIcon, cx, cy, 0, 0, DI_NORMAL);
}
-void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down)
+void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down, bool large_icons)
{
+ int cx = large_icons? 16: 8;
+ int cy = large_icons? 8: 4;
+
GetClientRect(_hwnd, prect_up);
*prect_down = *prect_up;
-// prect_up->left = prect_up->right/2 - 4;
-// prect_up->right = prect_up->left + 8;
- prect_up->right -= 8;
- prect_up->top = _floating_btn? 3: 1;
- prect_up->bottom = prect_up->top + 4;
+// prect_up->left = prect_up->right/2 - cx/2;
+// prect_up->right = prect_up->left + cy;
+ prect_up->right -= cx;
+ prect_up->top = _floating_btn? cy-1: 1;
+ prect_up->bottom = prect_up->top + cy;
-// prect_down->left = prect_down->right/2 - 4;
-// prect_down->right = prect_down->left + 8;
- prect_down->right -= 8;
- prect_down->top = prect_down->bottom - 5;
+// prect_down->left = prect_down->right/2 - cx/2;
+// prect_down->right = prect_down->left + cy;
+ prect_down->right -= cx;
+ prect_down->top = prect_down->bottom - cy - 1;
}
#ifdef _LIGHT_STARTMENU
if (_arrow_btns)
- DrawArrows(canvas);
+ DrawArrows(canvas, _large_icons);
ClientRect clnt(_hwnd);
+ const bool large_icons = _large_icons;
RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
int sep_width = rect.right-rect.left - 4;
break;
if (rect.top >= canvas.rcPaint.top)
- DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false);
+ DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false, _large_icons);
}
rect.top = rect.bottom;
Entry* entry = *it;
if (entry->_icon_id == ICID_UNKNOWN)
- try {
- entry->extract_icon();
- } catch(COMException&) {
- // ignore unexpected exceptions while extracting icons
- }
+ entry->_icon_id = entry->safe_extract_icon(_large_icons? ICF_LARGE: ICF_NORMAL);
if (entry->_icon_id > ICID_NONE) {
btn._icon_id = (ICON_ID)/*@@*/ entry->_icon_id;
break;
WindowCanvas canvas(_hwnd);
- DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false);
+ DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false, _large_icons);
//InvalidateRect(_hwnd, &rect, FALSE);
//UpdateWindow(_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;
FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT));
// widen window, if it is too small
- int text_width = GetStartMenuBtnTextWidth(canvas, title, _hwnd) + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/;
+ int text_width = GetStartMenuBtnTextWidth(canvas, title, _hwnd) + ICON_SIZE_X + 10/*placeholder*/ + 16/*arrow*/;
int cx = clnt.right - _border_left;
if (text_width > cx)
}
-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))
ClientToScreen(_hwnd, &rect);
x = rect.right; // Submenus should overlap their parent a bit.
+ const bool large_icons = _large_icons;
y = rect.top+STARTMENU_LINE_HEIGHT +_border_top/*own border*/ -STARTMENU_TOP_BTN_SPACE/*border of new submenu*/;
} else {
WindowRect pos(_hwnd);
}
_submenu_id = id;
- _submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, creator);
+ _submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, creator, info, _create_info._filter);
}
else {
TCHAR path[MAX_PATH];
- if (entry->get_path(path))
+ if (entry->get_path(path, COUNTOF(path)))
new_folders.push_back(path);
}
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;
}
#ifdef _LIGHT_STARTMENU
-void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed)
+void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed, bool large_icons)
#else
void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
- bool hasSubmenu, bool enabled, bool has_focus, bool pushed);
+ bool hasSubmenu, bool enabled, bool has_focus, bool pushed, bool large_icons);
#endif
{
UINT style = DFCS_BUTTONPUSH;
if (!btn._enabled)
style |= DFCS_INACTIVE;
- POINT iconPos = {rect.left+2, (rect.top+rect.bottom-16)/2};
- RECT textRect = {rect.left+16+4, rect.top+2, rect.right-4, rect.bottom-4};
+ POINT iconPos = {rect.left+2, (rect.top+rect.bottom-ICON_SIZE_Y)/2};
+ RECT textRect = {rect.left+ICON_SIZE_X+4, rect.top+2, rect.right-4, rect.bottom-4};
if (pushed) {
style |= DFCS_PUSHED;
FillRect(hdc, &rect, bk_brush);
if (btn._icon_id > ICID_NONE)
- g_Globals._icon_cache.get_icon(btn._icon_id).draw(hdc, iconPos.x, iconPos.y, 16, 16, bk_color, bk_brush);
+ g_Globals._icon_cache.get_icon(btn._icon_id).draw(hdc, iconPos.x, iconPos.y, ICON_SIZE_X, ICON_SIZE_Y, bk_color, bk_brush/*, large_icons*/);
// draw submenu arrow at the right
if (btn._hasSubmenu) {
- static SmallIcon arrowIcon(IDI_ARROW);
- static SmallIcon selArrowIcon(IDI_ARROW_SELECTED);
+ ResIconEx arrowIcon(IDI_ARROW, ICON_SIZE_X, ICON_SIZE_Y);
+ ResIconEx selArrowIcon(IDI_ARROW_SELECTED, ICON_SIZE_X, ICON_SIZE_Y);
- DrawIconEx(hdc, rect.right-16, iconPos.y,
+ DrawIconEx(hdc, rect.right-ICON_SIZE_X, iconPos.y,
has_focus? selArrowIcon: arrowIcon,
- 16, 16, 0, bk_brush, DI_NORMAL);
+ ICON_SIZE_X, ICON_SIZE_Y, 0, bk_brush, DI_NORMAL);
}
if (title) {
WindowCanvas canvas(_hwnd);
FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT));
+ const bool large_icons = _large_icons;
+
int max_width = STARTMENU_WIDTH_MIN;
int height = 0;
}
// calculate new window size
- int text_width = max_width + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/;
+ int text_width = max_width + ICON_SIZE_X + 10/*placeholder*/ + 16/*arrow*/;
RECT rt_hgt = {rect.left, rect.bottom-_border_top-height, rect.left+_border_left+text_width, rect.bottom};
AdjustWindowRectEx(&rt_hgt, GetWindowStyle(_hwnd), FALSE, GetWindowExStyle(_hwnd));
StartMenuRoot::StartMenuRoot(HWND hwnd)
- : super(hwnd)
+ : super(hwnd, false) ///@todo big icons in start menu root
{
#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
if (!g_Globals._SHRestricted || !SHRestricted(REST_NOCOMMONGROUPS))
try {
// insert directory "All Users\Start Menu"
ShellDirectory cmn_startmenu(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_STARTMENU, _hwnd), _hwnd);
- _dirs.push_back(StartMenuDirectory(cmn_startmenu, false)); // don't add subfolders
+ _dirs.push_back(StartMenuDirectory(cmn_startmenu, (LPCTSTR)SpecialFolderFSPath(CSIDL_COMMON_PROGRAMS, _hwnd)));
} catch(COMException&) {
// ignore exception and don't show additional shortcuts
}
try {
// insert directory "<user name>\Start Menu"
-
ShellDirectory usr_startmenu(GetDesktopFolder(), SpecialFolderPath(CSIDL_STARTMENU, _hwnd), _hwnd);
- _dirs.push_back(StartMenuDirectory(usr_startmenu, false)); // don't add subfolders
+ _dirs.push_back(StartMenuDirectory(usr_startmenu, (LPCTSTR)SpecialFolderFSPath(CSIDL_PROGRAMS, _hwnd)));
} catch(COMException&) {
// ignore exception and don't show additional shortcuts
}
+ ReadLogoSize();
+}
+
+void StartMenuRoot::ReadLogoSize()
+{
// read size of logo bitmap
BITMAP bmp_hdr;
- GetObject(ResBitmap(IDB_LOGOV), sizeof(BITMAP), &bmp_hdr);
+ GetObject(ResBitmap(GetLogoResId()), sizeof(BITMAP), &bmp_hdr);
_logo_size.cx = bmp_hdr.bmWidth;
_logo_size.cy = bmp_hdr.bmHeight;
+ // cache logo width
_border_left = _logo_size.cx + 1;
}
-HWND StartMenuRoot::Create(HWND hwndOwner)
+static void CalculateStartPos(HWND hwndOwner, RECT& rect, bool large_icons)
{
WindowRect pos(hwndOwner);
- RECT rect = {pos.left, pos.top-STARTMENU_LINE_HEIGHT-4, pos.left+STARTMENU_WIDTH_MIN, pos.top};
+ rect.left = pos.left;
+ rect.top = pos.top-STARTMENU_LINE_HEIGHT-4;
+ rect.right = pos.left+STARTMENU_WIDTH_MIN;
+ rect.bottom = pos.top;
#ifndef _LIGHT_STARTMENU
rect.top += STARTMENU_LINE_HEIGHT;
#endif
AdjustWindowRectEx(&rect, WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, FALSE, 0);
+}
+
+HWND StartMenuRoot::Create(HWND hwndOwner, bool large_icons)
+{
+ RECT rect;
+
+ CalculateStartPos(hwndOwner, rect, large_icons);
return Window::Create(WINDOW_CREATOR(StartMenuRoot), 0, GetWndClasss(), TITLE_STARTMENU,
WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN,
_selected_id = -1;
#endif
+#ifdef _LIGHT_STARTMENU
+ // recalculate start menu root position
+ RECT rect;
+
+ CalculateStartPos(GetParent(hwnd), rect, _large_icons);
+
+ SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0);
+
+ ResizeToButtons();
+#endif
+
// show previously hidden start menu
ShowWindow(hwnd, SW_SHOW);
SetForegroundWindow(hwnd);
- while(IsWindow(hwnd)) {
+ while(IsWindow(hwnd) && IsWindowVisible(hwnd)) {
if (!GetMessage(&msg, 0, 0, 0)) {
PostQuitMessage(msg.wParam);
break;
}
- // Check for a mouse click on any window, which is not part of the start menu
+ // Check for a mouse click on any window, that is not part of the start menu
if (msg.message==WM_LBUTTONDOWN || msg.message==WM_MBUTTONDOWN || msg.message==WM_RBUTTONDOWN) {
StartMenu* menu_wnd = NULL;
#else
if (IS_VALUE_ZERO(hkey, _T("NoRecentDocsMenu")))
#endif
- AddButton(ResString(IDS_RECENT), ICID_DOCUMENTS, true, IDC_RECENT);
+ AddButton(ResString(IDS_RECENT), ICID_RECENT, true, IDC_RECENT);
AddButton(ResString(IDS_FAVORITES), ICID_FAVORITES, true, IDC_FAVORITES);
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
#else
if (IS_VALUE_ZERO(hkey, _T("NoClose")))
#endif
- AddButton(ResString(IDS_SHUTDOWN), ICID_LOGOFF, false, IDC_SHUTDOWN);
+ AddButton(ResString(IDS_SHUTDOWN), ICID_SHUTDOWN, false, IDC_SHUTDOWN);
+
+
+#ifndef _ROS_
+ AddButton(ResString(IDS_TERMINATE), ICID_LOGOFF, false, IDC_TERMINATE);
+#endif
#ifdef __MINGW32__
Paint(canvas);
break;}
+ case WM_DISPLAYCHANGE:
+ // re-evaluate logo size using the correct color depth
+ ReadLogoSize();
+ break;
+
default:
return super::WndProc(nmsg, wparam, lparam);
}
void StartMenuRoot::Paint(PaintCanvas& canvas)
{
- int clr_bits;
- {WindowCanvas dc(_hwnd); clr_bits=GetDeviceCaps(dc, BITSPIXEL);}
-
MemCanvas mem_dc;
- ResBitmap bmp(clr_bits<=8? clr_bits<=4? IDB_LOGOV16: IDB_LOGOV256: IDB_LOGOV);
+ ResBitmap bmp(GetLogoResId());
BitmapSelection sel(mem_dc, bmp);
ClientRect clnt(_hwnd);
PatBlt(canvas, _logo_size.cx, 0, 1, clnt.bottom, WHITENESS);
- BitBlt(canvas, 0, clnt.bottom-h, _logo_size.cx, h, mem_dc, 0, 0, SRCCOPY);
+ BitBlt(canvas, 0, clnt.bottom-h, _logo_size.cx, h, mem_dc, 0, ( h<_logo_size.cy ? _logo_size.cy-h : 0) , SRCCOPY);
super::Paint(canvas);
}
+UINT StartMenuRoot::GetLogoResId()
+{
+ WindowCanvas dc(_hwnd);
+
+ int clr_bits = GetDeviceCaps(dc, BITSPIXEL);
+
+ if (clr_bits > 8)
+ return IDB_LOGOV;
+ else if (clr_bits > 4)
+ return IDB_LOGOV256;
+ else
+ return IDB_LOGOV16;
+}
+
void StartMenuRoot::CloseStartMenu(int id)
{
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:
break;
case IDC_LOGOFF:
- /* The shell32 Dialog prompts about some system setting change. This is not what we want to display here.
CloseStartMenu(id);
- ShowRestartDialog(g_Globals._hwndDesktopBar, EWX_LOGOFF);*/
+ ShowLogoffDialog(g_Globals._hwndDesktopBar);
+ break;
+
+#ifndef _ROS_
+ case IDC_TERMINATE:
DestroyWindow(GetParent(_hwnd));
break;
+#endif
case IDC_SHUTDOWN:
CloseStartMenu(id);
ExplorerPropertySheet(g_Globals._hwndDesktopBar);
break;
- case IDC_PRINTERS:
+ case IDC_CONTROL_PANEL: {
CloseStartMenu(id);
- MainFrame::Create(SpecialFolderPath(CSIDL_PRINTERS, _hwnd), OWM_PIDL);
+#ifndef ROSSHELL
+#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_CONTROL_PANEL:
+ case IDC_PRINTERS: {
CloseStartMenu(id);
- MainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
+
+#ifndef ROSSHELL
+#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;}
+
+#if 0 ///@todo use printer start menu folder per default and allow opening "printers" cabinet window using the context menu
+ 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;
+#endif
case IDC_ADMIN:
- CloseStartMenu(id);
- MainFrame::Create(SpecialFolderPath(CSIDL_COMMON_ADMINTOOLS, _hwnd), OWM_PIDL);
+#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);
- MainFrame::Create(SpecialFolderPath(CSIDL_CONNECTIONS, _hwnd), OWM_PIDL);
+#ifndef ROSSHELL
+#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;
+
+
+ // browse menu
+
+ case IDC_NETWORK:
+#ifdef _ROS_ ///@todo to be removed when network browsing will be implemented in shell namespace
+ MessageBox(0, TEXT("network not yet implemented"), ResString(IDS_TITLE), MB_OK);
+#else
+ 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();
void StartMenuHandler::ShowSearchDialog()
{
+#ifndef _ROS_ ///@todo to be removed when SHFindFiles() will be implemented in shell32.dll
static DynamicFct<SHFINDFILES> SHFindFiles(TEXT("SHELL32"), 90);
if (SHFindFiles)
(*SHFindFiles)(NULL, NULL);
else
+#endif
MessageBox(0, TEXT("SHFindFiles() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
}
void StartMenuHandler::ShowSearchComputer()
{
+#ifndef _ROS_ ///@todo to be removed when SHFindComputer() will be implemented in shell32.dll
static DynamicFct<SHFINDCOMPUTER> SHFindComputer(TEXT("SHELL32"), 91);
if (SHFindComputer)
(*SHFindComputer)(NULL, NULL);
else
+#endif
MessageBox(0, TEXT("SHFindComputer() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
}
// 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];
}
}
-void StartMenuHandler::ShowRestartDialog(HWND hwndOwner, UINT flags)
+void StartMenuHandler::ShowLogoffDialog(HWND hwndOwner)
{
- static DynamicFct<RESTARTWINDOWSDLG> RestartDlg(TEXT("SHELL32"), 59);
+ static DynamicFct<LOGOFFWINDOWSDIALOG> LogoffWindowsDialog(TEXT("SHELL32"), 54);
+// static DynamicFct<RESTARTWINDOWSDLG> RestartDialog(TEXT("SHELL32"), 59);
- if (RestartDlg)
- (*RestartDlg)(hwndOwner, (LPWSTR)L"You selected <Log Off>.\n\n", flags); ///@todo ANSI string conversion if needed
+ if (LogoffWindowsDialog)
+ (*LogoffWindowsDialog)(0);
+/* The RestartDialog function prompts about some system setting change. This is not what we want to display here.
+ else if (RestartDialog)
+ return (*RestartDialog)(hwndOwner, (LPWSTR)L"You selected <Log Off>.\n\n", EWX_LOGOFF) == 1; ///@todo ANSI string conversion if needed
+*/
else
- MessageBox(hwndOwner, TEXT("RestartDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+ MessageBox(hwndOwner, TEXT("LogoffWindowsDialog() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
}
void ShowExitWindowsDialog(HWND hwndOwner)
{
- static DynamicFct<EXITWINDOWSDLG> ExitWindowsDlg(TEXT("SHELL32"), 60);
+ static DynamicFct<EXITWINDOWSDLG> ExitWindowsDialog(TEXT("SHELL32"), 60);
- if (ExitWindowsDlg)
- (*ExitWindowsDlg)(hwndOwner);
+ if (ExitWindowsDialog)
+ (*ExitWindowsDialog)(hwndOwner);
else
- MessageBox(hwndOwner, TEXT("ExitWindowsDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+ MessageBox(hwndOwner, TEXT("ExitWindowsDialog() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
}
{
super::AddEntries();
+#if defined(ROSSHELL) || defined(_ROS_) // _ROS_ to be removed when printer/network will be implemented
+//TODO AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, false, IDC_PRINTERS_MENU);
+ AddButton(ResString(IDS_CONNECTIONS), ICID_NETWORK, false, IDC_CONNECTIONS);
+#else
+//TODO AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, true, IDC_PRINTERS_MENU);
+ AddButton(ResString(IDS_CONNECTIONS), ICID_NETCONNS, false, IDC_CONNECTIONS);
+#endif
+ AddButton(ResString(IDS_ADMIN), ICID_ADMINISTRATION, 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_CONTROL_PANEL), ICID_CONFIG, false, IDC_CONTROL_PANEL);
+ AddButton(ResString(IDS_SETTINGS_MENU), ICID_CONFIG, true, IDC_SETTINGS_MENU);
+
+ AddButton(ResString(IDS_DESKTOPBAR_SETTINGS), ICID_DESKSETTING, false, ID_DESKTOPBAR_SETTINGS);
- 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);
+ AddButton(ResString(IDS_PRINTERS), ICID_PRINTER, false, IDC_PRINTERS);
- 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_NOCONTROLPANEL))
+#endif
+ AddButton(ResString(IDS_CONTROL_PANEL), ICID_CONTROLPAN, false, IDC_CONTROL_PANEL);
+}
+
+void BrowseMenu::AddEntries()
+{
+ super::AddEntries();
+
+#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
+ if (!g_Globals._SHRestricted || !SHRestricted(REST_NONETHOOD)) // or REST_NOENTIRENETWORK ?
+#endif
+#if defined(ROSSHELL) || defined(_ROS_) // _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_DONT_EXTRACT_ICONS);
#else
- dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+ dir.smart_scan(SORT_NAME);
#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._ignore); ///@todo read max. count of entries from registry
}
}
+
+
+#ifndef _SHELL32_FAVORITES
+
+void FavoritesMenu::AddEntries()
+{
+ super::AddEntries();
+
+ String lwr_filter = _create_info._filter;
+ lwr_filter.toLower();
+
+ 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);
+
+ // filter non-directory entries
+ if (!lwr_filter.empty()) {
+ String lwr_name = bookmark._name;
+ String lwr_desc = bookmark._description;
+ String lwr_url = bookmark._url;
+
+ lwr_name.toLower();
+ lwr_desc.toLower();
+ lwr_url.toLower();
+
+ if (!_tcsstr(lwr_name,lwr_filter) && !_tcsstr(lwr_desc,lwr_filter) && !_tcsstr(lwr_url,lwr_filter))
+ continue;
+ }
+
+ 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