# Makefile.MinGW
#
-
CC = gcc
CXX = g++
LINK = g++
CFLAGS = -DWIN32 -D_ROS_ -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -fexceptions -Wall
-CXXFLAGS= $(CFLAGS)
RCFLAGS = -DWIN32 -D_ROS_
LFLAGS = -Wl,--subsystem,windows
# LFLAGS+= -Wl,--entry,_wWinMain@16
endif
+CXXFLAGS = $(CFLAGS)
+
EXEC_SUFFIX = .exe
RES_SUFFIX = .coff
windres $(RCFLAGS) -o $@ $^
clean:
- rm -f $(TARGET) *.o *$(RES_SUFFIX)
+ rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX)
- activate accelerator keys like <DEL> in shell view folders
- program manager "progman" DDE server
- command line parameters like "/e,/root,c:\" and "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}" (launch of control panel)
-- search functionality in start menu
- Windows-key combos
- Application Desktop Toolbars
- desktop switching
created a Makefile for compiling as standalone project using MinGW
eliminated all warnings displayed when using -Wall
activated option for compiling as UNICODE version
+ merged start menus of the same name (e.g. "All Users\Startup" with "<User>\Startup")
# TARGTYPE "Win32 (x86) External Target" 0x0106
-CFG=make_explorer - Win32 Debug
+CFG=make_explorer - Win32 Unicode Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!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 "make_explorer.mak" CFG="make_explorer - Win32 Debug"
+!MESSAGE NMAKE /f "make_explorer.mak" CFG="make_explorer - Win32 Unicode Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "make_explorer - Win32 Release" (based on "Win32 (x86) External Target")
!MESSAGE "make_explorer - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "make_explorer - Win32 Unicode Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "make_explorer - Win32 Unicode Release" (based on "Win32 (x86) External Target")
!MESSAGE
# Begin Project
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
-# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1"
+# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW"
# PROP Rebuild_Opt "clean all"
# PROP Target_File "explorer.exe"
# PROP Bsc_Name ""
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1"
+# PROP Rebuild_Opt "clean all"
+# PROP Target_File "explorer.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "UDebug"
+# PROP BASE Intermediate_Dir "UDebug"
+# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1"
+# PROP BASE Rebuild_Opt "clean all"
+# PROP BASE Target_File "explorer.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "UDebug"
+# PROP Intermediate_Dir "UDebug"
# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1"
# PROP Rebuild_Opt "clean all"
# PROP Target_File "explorer.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""
+!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "URelease"
+# PROP BASE Intermediate_Dir "URelease"
+# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1"
+# PROP BASE Rebuild_Opt "clean all"
+# PROP BASE Target_File "explorer.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "URelease"
+# PROP Intermediate_Dir "URelease"
+# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1"
+# PROP Rebuild_Opt "clean all"
+# PROP Target_File "explorer.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
!ENDIF
# Begin Target
# Name "make_explorer - Win32 Release"
# Name "make_explorer - Win32 Debug"
+# Name "make_explorer - Win32 Unicode Debug"
+# Name "make_explorer - Win32 Unicode Release"
!IF "$(CFG)" == "make_explorer - Win32 Release"
!ELSEIF "$(CFG)" == "make_explorer - Win32 Debug"
+!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug"
+
+!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release"
+
!ENDIF
# Begin Source File
LRESULT StartMenu::Init(LPCREATESTRUCT pcs)
{
- WaitCursor wait;
-
try {
AddEntries();
const StartMenuEntry& sme = it->second;
bool hasSubmenu = false;
- if (sme._entry && (sme._entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
- hasSubmenu = true;
+ for(ShellEntrySet::const_iterator it=sme._entries.begin(); it!=sme._entries.end(); ++it)
+ if ((*it)->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ hasSubmenu = true;
AddButton(sme._title, sme._hIcon, hasSubmenu, it->first);
}
StartMenuDirectory& smd = *it;
ShellDirectory& dir = smd._dir;
- dir.smart_scan();
+ if (!dir._scanned) {
+ WaitCursor wait;
+
+ dir.smart_scan();
+ }
AddShellEntries(dir, -1, smd._subfolders);
}
break;
default: {
- ShellEntryMap::const_iterator found = _entries.find(id);
+ ShellEntryMap::iterator found = _entries.find(id);
if (found != _entries.end()) {
- ShellEntry* entry = const_cast<ShellEntry*>(found->second._entry);
-
- if (entry)
- ActivateEntry(id, entry);
+ ActivateEntry(id, found->second._entries);
break;
}
const String& entry_name = folder.get_name(entry->_pidl);
+ // search for an already existing subdirectory entry with the same name
+ for(ShellEntryMap::iterator it=_entries.begin(); it!=_entries.end(); ++it) {
+ StartMenuEntry& sme = it->second;
+
+ if (sme._title == entry_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;
+ }
+ }
+ }
+
StartMenuEntry& sme = AddEntry(entry_name, hIcon);
- sme._entry = entry;
+ sme._entries.insert(entry);
return sme;
}
}
-void StartMenu::ActivateEntry(int id, ShellEntry* entry)
+void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries)
{
- if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- // Only open one submenu at a time.
- if (!CloseOtherSubmenus(id))
- return;
+ StartMenuFolders new_folders;
- StartMenuFolders new_folders;
+ for(ShellEntrySet::const_iterator it=entries.begin(); it!=entries.end(); ++it) {
+ ShellEntry* entry = const_cast<ShellEntry*>(*it);
- new_folders.push_back(entry->create_absolute_pidl(_hwnd));
+ if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ new_folders.push_back(entry->create_absolute_pidl(_hwnd));
+ else {
+ // If the entry is no subdirectory, there can only be one shell entry.
+ assert(entries.size()==1);
- //TODO: merge all entries of subdirectories with the same name, like "All Users\...\Accessories" and "<user>\...\Accessories"
+ entry->launch_entry(_hwnd); //TODO: launch in the background; specify correct HWND for error message box titles
- CreateSubmenu(id, new_folders);
- } else {
- entry->launch_entry(_hwnd); //TODO: launch in the background; specify correct HWND for error message box titles
+ // close start menus after launching the selected entry
+ CloseStartMenu(id);
- // close start menus after launching the selected entry
- CloseStartMenu(id);
+ // we deleted 'this' - ensure we leave loop and function
+ return;
+ }
+ }
+
+ if (!new_folders.empty()) {
+ // Only open one submenu at a time.
+ if (!CloseOtherSubmenus(id))
+ return;
+
+ CreateSubmenu(id, new_folders);
}
}
StartMenuDirectory& smd = *it;
ShellDirectory& dir = smd._dir;
- dir.smart_scan();
+ if (!dir._scanned) {
+ WaitCursor wait;
+
+ dir.smart_scan();
+ }
dir.sort_directory(SORT_DATE);
AddShellEntries(dir, 16, smd._subfolders); //TODO: read max. count of entries from registry
};
typedef list<StartMenuDirectory> StartMenuShellDirs;
+typedef set<const ShellEntry*> ShellEntrySet;
struct StartMenuEntry
{
- StartMenuEntry() : _hIcon(0), _entry(NULL) {}
+ StartMenuEntry() : _hIcon(0) {}
String _title;
HICON _hIcon;
- const ShellEntry* _entry;
+ ShellEntrySet _entries;
};
void CreateSubmenu(int id, int folder, CREATORFUNC creator=s_def_creator);
void CreateSubmenu(int id, int folder1, int folder2, CREATORFUNC creator=s_def_creator);
void CreateSubmenu(int id, const StartMenuFolders& new_folders, CREATORFUNC creator=s_def_creator);
- void ActivateEntry(int id, ShellEntry* entry);
+ void ActivateEntry(int id, const ShellEntrySet& entries);
void CloseStartMenu(int id=0);
};