diff --git a/reactos/ChangeLog b/reactos/ChangeLog index c17bd257bd6..2d1507520e4 100644 --- a/reactos/ChangeLog +++ b/reactos/ChangeLog @@ -1,7 +1,13 @@ -2003-08-16 Martin Fuchs +2003-08-19 Martin Fuchs + + * subsys/system/explorer/taskbar/startmenu.cpp: + Implemented navigation in submenus of the start menu. + Start menus can now resolve shortcuts and launch programs. + +2003-08-18 Martin Fuchs * subsys/system/explorer/taskbar/taskbar.cpp: - first draft of explorer start menu + First draft of explorer start menu. 2003-08-17 James Tabor diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index a578f12c11b..ee83c059fa1 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -32,9 +32,9 @@ #include "explorer.h" #include "globals.h" +#include "externals.h" #include "explorer_intres.h" -#include "externals.h" ExplorerGlobals g_Globals; @@ -118,26 +118,25 @@ int explorer_main(HINSTANCE hInstance, HWND hwndDesktop, int cmdshow) try { InitInstance(hInstance); - - if (hwndDesktop) - g_Globals._desktop_mode = true; - - if (cmdshow != SW_HIDE) { -#ifndef _ROS_ // don't maximize if being called from the ROS desktop - if (cmdshow == SW_SHOWNORMAL) - /*TODO: read window placement from registry */ - cmdshow = SW_MAXIMIZE; -#endif - - explorer_show_frame(hwndDesktop, cmdshow); - } - - return Window::MessageLoop(); } catch(COMException& e) { HandleException(e, g_Globals._hMainWnd); + return -1; } - return -1; + if (hwndDesktop) + g_Globals._desktop_mode = true; + + if (cmdshow != SW_HIDE) { +#ifndef _ROS_ // don't maximize if being called from the ROS desktop + if (cmdshow == SW_SHOWNORMAL) + /*TODO: read window placement from registry */ + cmdshow = SW_MAXIMIZE; +#endif + + explorer_show_frame(hwndDesktop, cmdshow); + } + + return Window::MessageLoop(); } diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp index cf096c279f6..d9a2fab9a3e 100644 --- a/reactos/subsys/system/explorer/explorer.dsp +++ b/reactos/subsys/system/explorer/explorer.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Console Application" 0x0103 -CFG=explorer - Win32 Unicode Debug +CFG=explorer - Win32 _NO_COMUTIL !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,7 +13,7 @@ CFG=explorer - Win32 Unicode Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "explorer.mak" CFG="explorer - Win32 Unicode Debug" +!MESSAGE NMAKE /f "explorer.mak" CFG="explorer - Win32 _NO_COMUTIL" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE @@ -22,6 +22,7 @@ CFG=explorer - Win32 Unicode Debug !MESSAGE "explorer - Win32 Debug Release" (based on "Win32 (x86) Console Application") !MESSAGE "explorer - Win32 Unicode Release" (based on "Win32 (x86) Console Application") !MESSAGE "explorer - Win32 Unicode Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 _NO_COMUTIL" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project @@ -159,6 +160,33 @@ LINK32=link.cmd # ADD LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # SUBTRACT LINK32 /pdb:none +!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "explorer___Win32__NO_COMUTIL" +# PROP BASE Intermediate_Dir "explorer___Win32__NO_COMUTIL" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "_NO_COMUTIL" +# PROP Intermediate_Dir "_NO_COMUTIL" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /D "_NO_COMUTIL" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.cmd +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + !ENDIF # Begin Target @@ -168,6 +196,7 @@ LINK32=link.cmd # Name "explorer - Win32 Debug Release" # Name "explorer - Win32 Unicode Release" # Name "explorer - Win32 Unicode Debug" +# Name "explorer - Win32 _NO_COMUTIL" # Begin Group "utility" # PROP Default_Filter "" @@ -241,6 +270,11 @@ SOURCE=.\de.rc # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 +!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + !ENDIF # End Source File @@ -274,6 +308,11 @@ SOURCE=.\en.rc # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 +!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + !ENDIF # End Source File @@ -327,6 +366,11 @@ SOURCE=.\resource.rc # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 +!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + !ENDIF # End Source File diff --git a/reactos/subsys/system/explorer/res/reactos.ico b/reactos/subsys/system/explorer/res/reactos.ico index 0b2987ce907..c0c0ac504ce 100644 Binary files a/reactos/subsys/system/explorer/res/reactos.ico and b/reactos/subsys/system/explorer/res/reactos.ico differ diff --git a/reactos/subsys/system/explorer/shell/entries.cpp b/reactos/subsys/system/explorer/shell/entries.cpp index f0316fa821c..565c1a5d605 100644 --- a/reactos/subsys/system/explorer/shell/entries.cpp +++ b/reactos/subsys/system/explorer/shell/entries.cpp @@ -42,6 +42,7 @@ Entry::Entry(ENTRY_TYPE etype) _down = NULL; _expanded = false; _scanned = false; + _bhfi_valid = false; _level = 0; _hicon = 0; } @@ -54,6 +55,7 @@ Entry::Entry(Entry* parent) _down = NULL; _expanded = false; _scanned = false; + _bhfi_valid = false; _level = 0; _hicon = 0; } diff --git a/reactos/subsys/system/explorer/shell/entries.h b/reactos/subsys/system/explorer/shell/entries.h index cd5f38473c5..97a67a09c96 100644 --- a/reactos/subsys/system/explorer/shell/entries.h +++ b/reactos/subsys/system/explorer/shell/entries.h @@ -60,14 +60,14 @@ public: WIN32_FIND_DATA _data; - BY_HANDLE_FILE_INFORMATION _bhfi; - bool _bhfi_valid; - SFGAOF _shell_attribs; ENTRY_TYPE _etype; HICON _hicon; + BY_HANDLE_FILE_INFORMATION _bhfi; + bool _bhfi_valid; + void free_subentries(); void read_directory(SORT_ORDER sortOrder); @@ -78,8 +78,8 @@ public: virtual void read_directory() {} virtual const void* get_next_path_component(const void*) {return NULL;} virtual Entry* find_entry(const void*) {return NULL;} - virtual void get_path(PTSTR path) = 0; - virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow); + virtual void get_path(PTSTR path) const = 0; + virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); }; struct Directory { diff --git a/reactos/subsys/system/explorer/shell/filechild.cpp b/reactos/subsys/system/explorer/shell/filechild.cpp index 69e937c46c6..ffad4a6361e 100644 --- a/reactos/subsys/system/explorer/shell/filechild.cpp +++ b/reactos/subsys/system/explorer/shell/filechild.cpp @@ -80,7 +80,7 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) lstrcpy(_root._fs, TEXT("Shell")); const ShellChildWndInfo& shell_info = static_cast(info); - _root._entry = new ShellDirectory(Desktop(), shell_info._shell_path, hwnd); + _root._entry = new ShellDirectory(Desktop(), DesktopFolder(), hwnd); entry = _root._entry->read_tree((LPCTSTR)&*shell_info._shell_path, SORT_NAME/*_sortOrder*/); } else @@ -111,10 +111,10 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) entry = _root._entry->read_tree(info._path, SORT_NAME/*_sortOrder*/); } - if (info._etype == ET_SHELL) - lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); - else + if (info._etype != ET_SHELL) wsprintf(_root._entry->_data.cFileName, TEXT("%s - %s"), drv, _root._fs); +/*@@else + lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop"));*/ _root._entry->_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; @@ -425,7 +425,7 @@ void FileChildWindow::activate_entry(Pane* pane, HWND hwnd) pane->set_header(); } } else { - entry->launch_entry(_hwnd, SW_SHOWNORMAL); + entry->launch_entry(_hwnd); } } diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.cpp b/reactos/subsys/system/explorer/shell/shellbrowser.cpp index a821ee37e27..6ba071acd02 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.cpp +++ b/reactos/subsys/system/explorer/shell/shellbrowser.cpp @@ -113,13 +113,14 @@ void ShellBrowserChild::InitializeTree(/*const FileChildWndInfo& info*/) lstrcpy(_root._fs, TEXT("Shell")); -//@@ _root._entry->read_tree(ShellFolder(shell_info._root_shell_path), info._shell_path, SORT_NAME/*_sortOrder*/); +//@@ _root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME/*_sortOrder*/); - //@@ fängt zunächst nur einmal mit dem Desktop-Objekt an + //@@ should call read_tree() here; see FileChildWindow::FileChildWindow() _root._entry = new ShellDirectory(Desktop(), DesktopFolder(), _hwnd); _root._entry->read_directory(); - lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); + /* already filled by ShellDirectory constructor + lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); */ TV_ITEM tvItem; @@ -328,7 +329,7 @@ void ShellBrowserChild::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShe tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; tvItem.pszText = LPSTR_TEXTCALLBACK; tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK; - tvItem.lParam= (LPARAM)entry; + tvItem.lParam = (LPARAM)entry; tvItem.cChildren = entry->_shell_attribs & SFGAO_HASSUBFOLDER? 1: 0; if (entry->_shell_attribs & SFGAO_SHARE) { @@ -359,7 +360,7 @@ void ShellBrowserChild::OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv) if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) folder = static_cast(entry)->_folder; else - folder = entry->_up? static_cast(entry->_up)->_folder: Desktop(); + folder = entry->get_parent_folder(); if (!folder) { assert(folder); diff --git a/reactos/subsys/system/explorer/shell/shellfs.cpp b/reactos/subsys/system/explorer/shell/shellfs.cpp index 1b967295017..06c3d9f0b51 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.cpp +++ b/reactos/subsys/system/explorer/shell/shellfs.cpp @@ -115,18 +115,16 @@ LPITEMIDLIST ShellEntry::create_absolute_pidl(HWND hwnd) // get full path of a shell entry -void ShellEntry::get_path(PTSTR path) +void ShellEntry::get_path(PTSTR path) const { path[0] = TEXT('\0'); - IShellFolder* parent = _up? static_cast(_up)->_folder: Desktop(); - - HRESULT hr = path_from_pidl(parent, &*_pidl, path, MAX_PATH); + HRESULT hr = path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH); } // get full path of a shell folder -void ShellDirectory::get_path(PTSTR path) +void ShellDirectory::get_path(PTSTR path) const { path[0] = TEXT('\0'); @@ -134,13 +132,10 @@ void ShellDirectory::get_path(PTSTR path) HRESULT hr = S_OK; if (!_folder.empty()) - hr = _folder->GetAttributesOf(1, (LPCITEMIDLIST*)&_pidl, &attribs); + hr = const_cast(_folder)->GetAttributesOf(1, (LPCITEMIDLIST*)&_pidl, &attribs); - if (SUCCEEDED(hr) && (attribs&SFGAO_FILESYSTEM)) { - IShellFolder* parent = _up? static_cast(_up)->_folder: Desktop(); - - hr = path_from_pidl(parent, &*_pidl, path, MAX_PATH); - } + if (SUCCEEDED(hr) && (attribs&SFGAO_FILESYSTEM)) + hr = path_from_pidl(get_parent_folder(), &*_pidl, path, MAX_PATH); } diff --git a/reactos/subsys/system/explorer/shell/shellfs.h b/reactos/subsys/system/explorer/shell/shellfs.h index 1177fe4502c..b5bcdd6464d 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.h +++ b/reactos/subsys/system/explorer/shell/shellfs.h @@ -31,9 +31,10 @@ struct ShellEntry : public Entry ShellEntry(Entry* parent, LPITEMIDLIST shell_path) : Entry(parent), _pidl(shell_path) {} ShellEntry(Entry* parent, const ShellPath& shell_path) : Entry(parent), _pidl(shell_path) {} - virtual void get_path(PTSTR path); - virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow); + virtual void get_path(PTSTR path) const; + virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); + IShellFolder* get_parent_folder() const; LPITEMIDLIST create_absolute_pidl(HWND hwnd); ShellPath _pidl; @@ -43,6 +44,7 @@ protected: ShellEntry(const ShellPath& shell_path) : Entry(ET_SHELL), _pidl(shell_path) {} }; + struct ShellDirectory : public ShellEntry, public Directory { ShellDirectory(IShellFolder* shell_root, const ShellPath& shell_path, HWND hwnd) @@ -50,17 +52,26 @@ struct ShellDirectory : public ShellEntry, public Directory _folder(shell_root, shell_path), _hwnd(hwnd) { + lstrcpy(_data.cFileName, ShellFolder(shell_root).get_name(shell_path)); + _data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + _shell_attribs = SFGAO_FOLDER; + ShellFolder folder(shell_root, shell_path); IShellFolder* pFolder = folder; pFolder->AddRef(); _path = pFolder; } - ShellDirectory(ShellDirectory* parent, IShellFolder* shell_root, LPITEMIDLIST shell_path, HWND hwnd) + explicit ShellDirectory(ShellDirectory* parent, IShellFolder* shell_root, LPITEMIDLIST shell_path, HWND hwnd) : ShellEntry(parent, shell_path), _folder(shell_root), _hwnd(hwnd) { + /* not neccessary - the caller will fill the info + lstrcpy(_data.cFileName, _folder.get_name(shell_path)); + _data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + _shell_attribs = SFGAO_FOLDER; */ + shell_root->AddRef(); _path = shell_root; } @@ -76,7 +87,7 @@ struct ShellDirectory : public ShellEntry, public Directory virtual const void* get_next_path_component(const void*); virtual Entry* find_entry(const void* p); - virtual void get_path(PTSTR path); + virtual void get_path(PTSTR path) const; ShellFolder _folder; HWND _hwnd; @@ -84,3 +95,12 @@ struct ShellDirectory : public ShellEntry, public Directory protected: bool fill_w32fdata_shell(LPCITEMIDLIST pidl, SFGAOF attribs, WIN32_FIND_DATA*, BY_HANDLE_FILE_INFORMATION*); }; + + +inline IShellFolder* ShellEntry::get_parent_folder() const +{ + if (_up) + return static_cast(_up)->_folder; + else + return Desktop(); +} diff --git a/reactos/subsys/system/explorer/shell/unixfs.cpp b/reactos/subsys/system/explorer/shell/unixfs.cpp index fbd2150a625..2ca30d12eff 100644 --- a/reactos/subsys/system/explorer/shell/unixfs.cpp +++ b/reactos/subsys/system/explorer/shell/unixfs.cpp @@ -157,7 +157,7 @@ Entry* UnixDirectory::find_entry(const void* p) // get full path of specified directory entry -void UnixEntry::get_path(PTSTR path) +void UnixEntry::get_path(PTSTR path) const { int level = 0; int len = 0; diff --git a/reactos/subsys/system/explorer/shell/unixfs.h b/reactos/subsys/system/explorer/shell/unixfs.h index 4a5b99cfd38..304773f42fe 100644 --- a/reactos/subsys/system/explorer/shell/unixfs.h +++ b/reactos/subsys/system/explorer/shell/unixfs.h @@ -35,7 +35,7 @@ struct UnixEntry : public Entry protected: UnixEntry() : Entry(ET_UNIX) {} - virtual void get_path(PTSTR path); + virtual void get_path(PTSTR path) const; }; struct UnixDirectory : public UnixEntry, public Directory diff --git a/reactos/subsys/system/explorer/shell/winfs.cpp b/reactos/subsys/system/explorer/shell/winfs.cpp index bdfc6d77bf4..e0c4a6671d2 100644 --- a/reactos/subsys/system/explorer/shell/winfs.cpp +++ b/reactos/subsys/system/explorer/shell/winfs.cpp @@ -140,12 +140,12 @@ Entry* WinDirectory::find_entry(const void* p) // get full path of specified directory entry -void WinEntry::get_path(PTSTR path) +void WinEntry::get_path(PTSTR path) const { int level = 0; int len = 0; - for(Entry* entry=this; entry; level++) { + for(const Entry* entry=this; entry; level++) { LPCTSTR name = entry->_data.cFileName; int l = 0; diff --git a/reactos/subsys/system/explorer/shell/winfs.h b/reactos/subsys/system/explorer/shell/winfs.h index c0a3d639cf8..c5a7d1dd6aa 100644 --- a/reactos/subsys/system/explorer/shell/winfs.h +++ b/reactos/subsys/system/explorer/shell/winfs.h @@ -33,7 +33,7 @@ struct WinEntry : public Entry protected: WinEntry() : Entry(ET_WINDOWS) {} - virtual void get_path(PTSTR path); + virtual void get_path(PTSTR path) const; }; struct WinDirectory : public WinEntry, public Directory diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index 281725b6c43..b7927845fa4 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -22,6 +22,8 @@ // // startmenu.cpp // + // Explorer start menu + // // Martin Fuchs, 19.08.2003 // @@ -30,6 +32,7 @@ #include "../explorer.h" #include "../globals.h" +#include "../externals.h" #include "../explorer_intres.h" #include "taskbar.h" @@ -49,6 +52,8 @@ StartMenu::StartMenu(HWND hwnd, const StartMenuFolders& info) { for(StartMenuFolders::const_iterator it=info.begin(); it!=info.end(); ++it) _dirs.push_back(ShellDirectory(Desktop(), *it, _hwnd)); + + _next_id = IDC_FIRST_MENU; } @@ -88,22 +93,23 @@ LRESULT StartMenu::Init(LPCREATESTRUCT pcs) void StartMenu::AddShellEntries(const ShellDirectory& dir, bool subfolders) { for(const Entry*entry=dir._down; entry; entry=entry->_next) { + // hide files like "desktop.ini" if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) continue; - HICON hIcon = entry->_hicon; - - if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (!subfolders) + // hide subfolders if requested + if (!subfolders) + if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; - hIcon = SmallIcon(IDI_EXPLORER); - } + const ShellEntry* shell_entry = static_cast(entry); - AddButton(dir._folder.get_name(&*static_cast(entry)->_pidl).c_str(), hIcon); + AddButton(dir._folder, shell_entry); } } + + LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { @@ -112,13 +118,12 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) if (res>=HTSIZEFIRST && res<=HTSIZELAST) return HTCLIENT; // disable window resizing - else - return res; - } + + return res;} case WM_SYSCOMMAND: if ((wparam&0xFFF0) == SC_SIZE) - return 0; // disable window resizing + return 0; // disable window resizing goto def; default: def: @@ -135,14 +140,21 @@ int StartMenu::Command(int id, int code) DestroyWindow(_hwnd); break; - default: - return super::Command(id, code); + default: { + ShellEntryMap::const_iterator found = _entry_map.find(id); + + if (found != _entry_map.end()) { + ActivateEntry(const_cast(found->second)); + break; + } + + return super::Command(id, code);} } return 0; } -void StartMenu::AddButton(LPCTSTR text, HICON hIcon, UINT id) +UINT StartMenu::AddButton(LPCTSTR text, HICON hIcon, UINT id) { if (id == (UINT)-1) id = ++_next_id; @@ -159,6 +171,38 @@ void StartMenu::AddButton(LPCTSTR text, HICON hIcon, UINT id) 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); + + return id; +} + +UINT StartMenu::AddButton(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); + + UINT id = AddButton(entry_name, hIcon); + + _entry_map[id] = entry; + + return id; +} + +void StartMenu::ActivateEntry(ShellEntry* entry) +{ + if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + StartMenuFolders new_folders; + + new_folders.push_back(entry->create_absolute_pidl(_hwnd)); + + WindowRect my_pos(_hwnd); + StartMenu::Create(my_pos.right, my_pos.top+STARTMENU_HEIGHT-4, new_folders, _hwnd); + } else { + entry->launch_entry(_hwnd); + } } @@ -190,7 +234,7 @@ LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs) AddShellEntries(usr_startmenu, false); // 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_FAVORITES), 0, IDC_FAVORITES); AddButton(ResString(IDS_DOCUMENTS), 0, IDC_DOCUMENTS); @@ -201,23 +245,26 @@ LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs) AddButton(ResString(IDS_SHUTDOWN), SmallIcon(IDI_LOGOFF), IDC_SHUTDOWN); AddButton(ResString(IDS_LOGOFF), SmallIcon(IDI_LOGOFF), IDC_LOGOFF); - - //TEST: open programs menu folder - StartMenuFolders prg_folders; - - 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); - - return 0; } int StartMenuRoot::Command(int id, int code) { switch(id) { + case IDC_PROGRAMS: { + StartMenuFolders prg_folders; + + 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: + explorer_show_frame(_hwnd, SW_SHOWNORMAL); + break; + case IDC_LOGOFF: DestroyWindow(GetParent(_hwnd)); //TODO: show dialog and ask for acknowledge break; diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index ae8e81f7061..092abb0ec78 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -49,6 +49,8 @@ struct StartMenuButton : public Button typedef list StartMenuFolders; typedef list StartMenuShellDirs; +typedef map ShellEntryMap; + // Startmenu window struct StartMenu : public OwnerDrawParent @@ -64,6 +66,7 @@ struct StartMenu : public OwnerDrawParent protected: int _next_id; StartMenuShellDirs _dirs; + ShellEntryMap _entry_map; static BtnWindowClass s_wcStartMenu; @@ -71,8 +74,12 @@ protected: LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); int Command(int id, int code); - void AddButton(LPCTSTR text, HICON hIcon=0, UINT id=(UINT)-1); + UINT AddButton(LPCTSTR text, HICON hIcon=0, UINT id=(UINT)-1); + UINT AddButton(const ShellFolder folder, const ShellEntry* entry); + void AddShellEntries(const ShellDirectory& dir, bool subfolders=true); + + void ActivateEntry(ShellEntry* entry); }; diff --git a/reactos/subsys/system/explorer/taskbar/taskbar.cpp b/reactos/subsys/system/explorer/taskbar/taskbar.cpp index d74c0e412ad..bbf5138bf52 100644 --- a/reactos/subsys/system/explorer/taskbar/taskbar.cpp +++ b/reactos/subsys/system/explorer/taskbar/taskbar.cpp @@ -61,6 +61,7 @@ DesktopBar::DesktopBar(HWND hwnd) : super(hwnd) { _hwndTaskBar = 0; + _startMenuRoot = 0; } DesktopBar::~DesktopBar() @@ -143,12 +144,18 @@ LRESULT DesktopBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) int DesktopBar::Command(int id, int code) { switch(id) { - case IDC_START: { - // create Startmenu - WindowRect my_pos(_hwnd); + case IDC_START: + if (_startMenuRoot && IsWindow(_startMenuRoot)) { + // dispose Startmenu + DestroyWindow(_startMenuRoot); + _startMenuRoot = 0; + } else { + // create Startmenu + WindowRect my_pos(_hwnd); - StartMenuRoot::Create(my_pos.left, my_pos.top-4, _hwnd); - break;} + _startMenuRoot = StartMenuRoot::Create(my_pos.left, my_pos.top-4, _hwnd); + } + break; } return 0; diff --git a/reactos/subsys/system/explorer/taskbar/taskbar.h b/reactos/subsys/system/explorer/taskbar/taskbar.h index aaafaabe4f4..2accae85865 100644 --- a/reactos/subsys/system/explorer/taskbar/taskbar.h +++ b/reactos/subsys/system/explorer/taskbar/taskbar.h @@ -77,6 +77,7 @@ protected: int Command(int id, int code); HWND _hwndTaskBar; + HWND _startMenuRoot; }; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.cpp b/reactos/subsys/system/explorer/utility/shellclasses.cpp index a2487075004..bb41b57825d 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.cpp +++ b/reactos/subsys/system/explorer/utility/shellclasses.cpp @@ -74,7 +74,7 @@ CommonDesktop::~CommonDesktop() } -HRESULT path_from_pidlA(IShellFolder* folder, LPITEMIDLIST pidl, LPSTR buffer, int len) +HRESULT path_from_pidlA(IShellFolder* folder, LPCITEMIDLIST pidl, LPSTR buffer, int len) { StrRetA str; @@ -88,7 +88,7 @@ HRESULT path_from_pidlA(IShellFolder* folder, LPITEMIDLIST pidl, LPSTR buffer, i return hr; } -HRESULT path_from_pidlW(IShellFolder* folder, LPITEMIDLIST pidl, LPWSTR buffer, int len) +HRESULT path_from_pidlW(IShellFolder* folder, LPCITEMIDLIST pidl, LPWSTR buffer, int len) { StrRetW str; @@ -102,7 +102,7 @@ HRESULT path_from_pidlW(IShellFolder* folder, LPITEMIDLIST pidl, LPWSTR buffer, return hr; } -HRESULT name_from_pidl(IShellFolder* folder, LPITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags) +HRESULT name_from_pidl(IShellFolder* folder, LPCITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags) { StrRet str; @@ -132,6 +132,7 @@ ShellFolder::ShellFolder() ShellFolder::ShellFolder(IShellFolder* p) : IShellFolderPtr(p) { + p->AddRef(); } ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl) @@ -179,16 +180,24 @@ void ShellFolder::attach(IShellFolder* parent, LPCITEMIDLIST pidl) ShellFolder::ShellFolder() { CheckError(SHGetDesktopFolder(&_p)); + + _p->AddRef(); } ShellFolder::ShellFolder(IShellFolder* p) : SIfacePtr(p) { + _p->AddRef(); } ShellFolder::ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl) { - CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); + if (pidl->mkid.cb) + CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); + else + _p = Desktop(); + + _p->AddRef(); } ShellFolder::ShellFolder(LPCITEMIDLIST pidl) @@ -197,6 +206,8 @@ ShellFolder::ShellFolder(LPCITEMIDLIST pidl) CheckError(Desktop()->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); else _p = Desktop(); + + _p->AddRef(); } void ShellFolder::attach(IShellFolder* parent, LPCITEMIDLIST pidl) @@ -205,6 +216,7 @@ void ShellFolder::attach(IShellFolder* parent, LPCITEMIDLIST pidl) CheckError(parent->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID*)&_p)); + _p->AddRef(); h->Release(); } diff --git a/reactos/subsys/system/explorer/utility/shellclasses.h b/reactos/subsys/system/explorer/utility/shellclasses.h index a468d031fa9..7fdbbfaaafc 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.h +++ b/reactos/subsys/system/explorer/utility/shellclasses.h @@ -33,7 +33,9 @@ #include #ifndef _INC_COMUTIL // is comutil.h of MS headers available? +#ifndef _NO_COMUTIL #define _NO_COMUTIL +#endif #endif @@ -393,9 +395,9 @@ extern ShellFolder& Desktop(); #define path_from_pidl path_from_pidlA #endif -extern HRESULT path_from_pidlA(IShellFolder* folder, LPITEMIDLIST pidl, LPSTR buffer, int len); -extern HRESULT path_from_pidlW(IShellFolder* folder, LPITEMIDLIST pidl, LPWSTR buffer, int len); -extern HRESULT name_from_pidl(IShellFolder* folder, LPITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags); +extern HRESULT path_from_pidlA(IShellFolder* folder, LPCITEMIDLIST pidl, LPSTR buffer, int len); +extern HRESULT path_from_pidlW(IShellFolder* folder, LPCITEMIDLIST pidl, LPWSTR buffer, int len); +extern HRESULT name_from_pidl(IShellFolder* folder, LPCITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags); // wrapper class for item ID lists @@ -578,7 +580,7 @@ struct ShellPath : public SShellPtr // convert an item id list from relative to absolute (=relative to the desktop) format - LPITEMIDLIST create_absolute_pidl(IShellFolder* parent_folder, HWND hwnd) + LPITEMIDLIST create_absolute_pidl(IShellFolder* parent_folder, HWND hwnd) const { WCHAR buffer[MAX_PATH]; diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index c9d23b68a18..f0f49497503 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -53,6 +53,10 @@ #ifdef __cplusplus +#ifdef _MSC_VER +#pragma warning(disable: 4786) // disable warnings about too long debug information symbols +#endif + // STL headers for strings and streams #include #include @@ -64,7 +68,7 @@ using namespace std; #include using namespace _com_util; -#endif // _MSC_VER +#endif // _MSC_VER && !_NO_COMUTIL #define for if (0) {} else for diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index b1e90ef1901..d74daf6b3ab 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -440,16 +440,20 @@ int Window::MessageLoop() MSG msg; while(GetMessage(&msg, 0, 0, 0)) { - if (pretranslate_msg(&msg)) - continue; - - if (dispatch_dialog_msg(&msg)) - continue; - - TranslateMessage(&msg); - try { - DispatchMessage(&msg); + if (pretranslate_msg(&msg)) + continue; + + if (dispatch_dialog_msg(&msg)) + continue; + + TranslateMessage(&msg); + + try { + DispatchMessage(&msg); + } catch(COMException& e) { + HandleException(e, g_Globals._hMainWnd); + } } catch(COMException& e) { HandleException(e, g_Globals._hMainWnd); }