explorer: merge changes from lean explorer branch (shell namespace iteration, icon extraction)

svn path=/trunk/; revision=20501
This commit is contained in:
Martin Fuchs
2006-01-01 10:40:23 +00:00
parent 396f717775
commit 20c1c8ae3b
12 changed files with 143 additions and 68 deletions
@@ -246,6 +246,7 @@ void FindProgramDlg::add_entry(const FPDEntry& cache_entry)
item.iItem = ListView_InsertItem(_list_ctrl, &item); // We could use the information in _sort to enable manual sorting while populating the list.
item.mask = LVIF_TEXT;
item.iSubItem = 1;
item.pszText = (LPTSTR)(LPCTSTR)cache_entry._path;
ListView_SetItem(_list_ctrl, &item);
@@ -26,11 +26,20 @@
//
#define _LIGHT_STARTMENU
#define _LAZY_ICONEXTRACT
#define _SINGLE_ICONEXTRACT
//#define _NO_WIN_FS
#include "utility/shellclasses.h"
#include "shell/entries.h"
#ifndef _NO_WIN_FS
#include "shell/winfs.h"
#endif
#include "shell/shellfs.h"
#ifndef ROSSHELL
@@ -326,16 +326,20 @@ int Entry::extract_icon(ICONCACHE_FLAGS flags)
ICON_ID icon_id = ICID_NONE;
if (get_path(path, COUNTOF(path)) && _tcsncmp(path,TEXT("::{"),3))
// not for ET_SHELL to display the correct desktop icon
if (_etype!=ET_SHELL && get_path(path, COUNTOF(path)))
icon_id = g_Globals._icon_cache.extract(path, flags);
if (icon_id == ICID_NONE) {
if (!(flags & (ICF_OPEN|ICF_OVERLAYS))) {
if (!(flags & ICF_OVERLAYS)) {
IExtractIcon* pExtract;
if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) {
unsigned gil_flags;
int idx;
if (flags & ICF_OPEN)
gil_flags |= GIL_OPENICON;
if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path), &idx, &gil_flags))) {
if (gil_flags & GIL_NOTFILENAME)
icon_id = g_Globals._icon_cache.extract(pExtract, path, idx, flags);
@@ -377,7 +381,7 @@ int Entry::extract_icon(ICONCACHE_FLAGS flags)
const ShellPath& pidl_abs = create_absolute_pidl();
LPCITEMIDLIST pidl = pidl_abs;
int shgfi_flags = SHGFI_SYSICONINDEX|SHGFI_PIDL;
int shgfi_flags = SHGFI_PIDL;
if (!(flags & ICF_LARGE))
shgfi_flags |= SHGFI_SMALLICON;
@@ -385,15 +389,19 @@ int Entry::extract_icon(ICONCACHE_FLAGS flags)
if (flags & ICF_OPEN)
shgfi_flags |= SHGFI_OPENICON;
// ICF_OVERLAYS is not supported in this case.
if (flags & ICF_SYSCACHE) {
assert(!(flags&ICF_OVERLAYS));
HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), shgfi_flags);
if (himlSys)
icon_id = g_Globals._icon_cache.add(sfi.iIcon);
/*
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|(g_Globals._large_icons? SHGFI_SMALLICON: 0)))
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
*/
HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|shgfi_flags);
if (himlSys)
icon_id = g_Globals._icon_cache.add(sfi.iIcon);
} else {
if (flags & ICF_OVERLAYS)
shgfi_flags |= SHGFI_ADDOVERLAYS;
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_ICON|shgfi_flags))
icon_id = g_Globals._icon_cache.add(sfi.hIcon);
}
}
}
@@ -675,9 +683,11 @@ bool Entry::get_path_base ( PTSTR path, size_t path_count, ENTRY_TYPE etype ) co
memcpy(path+1, name, l*sizeof(TCHAR));
len += l+1;
if ( etype == ET_WINDOWS && entry->_up && !(entry->_up->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // a NTFS stream?
#ifndef _NO_WIN_FS
if (etype == ET_WINDOWS && entry->_up && !(entry->_up->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // a NTFS stream?
path[0] = TEXT(':');
else
#endif
path[0] = TEXT('\\');
}
@@ -28,7 +28,9 @@
enum ENTRY_TYPE {
ET_UNKNOWN,
#ifndef _NO_WIN_FS
ET_WINDOWS,
#endif
#ifdef __WINE__
ET_UNIX,
#endif
@@ -39,6 +39,7 @@ FileChildWndInfo::FileChildWndInfo(HWND hmdiclient, LPCTSTR path, ENTRY_TYPE ety
: super(hmdiclient),
_etype(etype)
{
#ifndef _NO_WIN_FS
if (etype == ET_UNKNOWN)
#ifdef __WINE__
if (*path == '/')
@@ -46,6 +47,7 @@ FileChildWndInfo::FileChildWndInfo(HWND hmdiclient, LPCTSTR path, ENTRY_TYPE ety
else
#endif
_etype = ET_WINDOWS;
#endif
_path = path;
@@ -134,20 +136,6 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
_right = NULL;
switch(info._etype) {
case ET_SHELL: { //@@ separate FileChildWindow into ShellChildWindow, WinChildWindow, UnixChildWindow ?
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NAME;
lstrcpy(drv, TEXT("\\"));
lstrcpy(_root._volname, TEXT("Desktop"));
_root._fs_flags = 0;
lstrcpy(_root._fs, TEXT("Shell"));
_root._entry = new ShellDirectory(GetDesktopFolder(), DesktopFolderPath(), hwnd);
const ShellChildWndInfo& shell_info = static_cast<const ShellChildWndInfo&>(info);
entry = _root.read_tree(&*shell_info._shell_path);
break;}
#ifdef __WINE__
case ET_UNIX:
_root._drive_type = GetDriveType(info._path);
@@ -207,6 +195,7 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
}
break;}
#ifndef _NO_WIN_FS
default: // ET_WINDOWS
_root._drive_type = GetDriveType(info._path);
_root._sort_order = SORT_NAME;
@@ -217,6 +206,24 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
lstrcpy(_root._path, drv);
_root._entry = new WinDirectory(_root._path);
entry = _root.read_tree(info._path+_tcslen(_root._path));
break;
#else
default:
#endif
case ET_SHELL: { //@@ separate FileChildWindow into ShellChildWindow, WinChildWindow, UnixChildWindow ?
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NAME;
lstrcpy(drv, TEXT("\\"));
lstrcpy(_root._volname, TEXT("Desktop"));
_root._fs_flags = 0;
lstrcpy(_root._fs, TEXT("Shell"));
_root._entry = new ShellDirectory(GetDesktopFolder(), DesktopFolderPath(), hwnd);
const ShellChildWndInfo& shell_info = static_cast<const ShellChildWndInfo&>(info);
entry = _root.read_tree(&*shell_info._shell_path);
break;}
}
if (_root._entry) {
@@ -794,6 +794,7 @@ MDIMainFrame::MDIMainFrame(HWND hwnd)
TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
#ifndef _NO_WIN_FS
PTSTR p;
#ifndef _NO_REBAR
@@ -807,11 +808,13 @@ MDIMainFrame::MDIMainFrame(HWND hwnd)
WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn, 1,
16, 13, 16, 13, sizeof(TBBUTTON));
#endif
#endif
CheckMenuItem(_menu_info._hMenuView, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED);
#ifndef _NO_WIN_FS
GetLogicalDriveStrings(BUFFER_LEN, _drives);
// register windows drive root strings
@@ -835,6 +838,7 @@ MDIMainFrame::MDIMainFrame(HWND hwnd)
while(*p++);
}
#endif
#ifndef _NO_REBAR
@@ -856,6 +860,7 @@ MDIMainFrame::MDIMainFrame(HWND hwnd)
rbBand.cx = 284;
SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
#ifndef _NO_WIN_FS
rbBand.fStyle |= RBBS_BREAK;
rbBand.lpText = TEXT("Drives");
rbBand.hwndChild = _hdrivebar;
@@ -864,6 +869,7 @@ MDIMainFrame::MDIMainFrame(HWND hwnd)
rbBand.cx = 400;
SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
#endif
#endif
}
@@ -937,13 +943,13 @@ LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
TCHAR buffer[MAX_PATH];
LPCTSTR path;
ShellPath root_path = DesktopFolderPath();
ShellPath shell_path = DesktopFolderPath();
if (lparam) {
if (wparam & OWM_PIDL) {
// take over PIDL from lparam
root_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
FileSysShellPath fsp(root_path);
shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
FileSysShellPath fsp(shell_path);
path = fsp;
if (path) {
@@ -954,7 +960,7 @@ LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
} else {
// take over path from lparam
path = (LPCTSTR)lparam;
root_path = path; // create as "rooted" window
shell_path = path; // create as "rooted" window
}
} else {
///@todo read paths and window placements from registry
@@ -972,7 +978,7 @@ LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
OBJ_CONTEXT("create ShellChildWndInfo", path);
// Shell Namespace as default view
ShellChildWndInfo create_info(_hmdiclient, path, root_path);
ShellChildWndInfo create_info(_hmdiclient, path, shell_path);
create_info._pos.showCmd = wparam&OWM_SEPARATE? SW_SHOWNORMAL: SW_SHOWMAXIMIZED;
create_info._pos.rcNormalPosition.left = CW_USEDEFAULT;
@@ -1010,6 +1016,7 @@ int MDIMainFrame::Command(int id, int code)
if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
return 0;
#ifndef _NO_WIN_FS
if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
LPCTSTR root = _drives;
@@ -1034,6 +1041,7 @@ int MDIMainFrame::Command(int id, int code)
return 1;
}
#endif
switch(id) {
case ID_WINDOW_NEW: {
@@ -1064,9 +1072,11 @@ int MDIMainFrame::Command(int id, int code)
toggle_child(_hwnd, id, _hextrabar, 1);
break;
#ifndef _NO_WIN_FS
case ID_VIEW_DRIVE_BAR:
toggle_child(_hwnd, id, _hdrivebar, 2);
break;
#endif
#ifdef __WINE__
case ID_DRIVE_UNIX_FS: {
@@ -1174,10 +1184,12 @@ void MDIMainFrame::frame_get_clientspace(PRECT prect)
{
super::frame_get_clientspace(prect);
#ifndef _NO_WIN_FS
if (IsWindowVisible(_hdrivebar)) {
ClientRect rt(_hdrivebar);
prect->top += rt.bottom+2;
}
#endif
}
void MDIMainFrame::resize_frame(int cx, int cy)
@@ -1208,6 +1220,7 @@ void MDIMainFrame::resize_frame(int cx, int cy)
// rect.bottom -= rt.bottom;
}
#ifndef _NO_WIN_FS
if (IsWindowVisible(_hdrivebar)) {
SendMessage(_hdrivebar, WM_SIZE, 0, 0);
WindowRect rt(_hdrivebar);
@@ -1216,6 +1229,7 @@ void MDIMainFrame::resize_frame(int cx, int cy)
rect.top = new_top;
// rect.bottom -= rt.bottom;
}
#endif
}
if (IsWindowVisible(_hstatusbar)) {
@@ -1476,13 +1490,13 @@ LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
TCHAR buffer[MAX_PATH];
LPCTSTR path;
ShellPath root_path = DesktopFolderPath();
ShellPath shell_path = DesktopFolderPath();
if (lparam) {
if (wparam & OWM_PIDL) {
// take over PIDL from lparam
root_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
FileSysShellPath fsp(root_path);
shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
FileSysShellPath fsp(shell_path);
path = fsp;
if (path) {
@@ -1493,7 +1507,7 @@ LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
} else {
// take over path from lparam
path = (LPCTSTR)lparam;
root_path = path; // create as "rooted" window
shell_path = path; // create as "rooted" window
}
} else {
///@todo read paths and window placements from registry
@@ -1501,10 +1515,15 @@ LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
*buffer = '\0';
path = buffer;
root_path = path;
shell_path = path;
}
jump_to(root_path, wparam); //@todo content of 'path' not used any more
if (wparam & OWM_ROOTED)
_shellpath_info._root_shell_path = shell_path;
else
_shellpath_info._root_shell_path = SpecialFolderPath(CSIDL_DESKTOP, _hwnd); // CSIDL_DRIVES
jump_to(shell_path, wparam); //@todo content of 'path' not used any more
return TRUE;} // success
default: def:
@@ -1620,8 +1639,6 @@ void SDIMainFrame::update_shell_browser()
delete _shellBrowser.release();
}
///@todo use OWM_ROOTED flag
// create explorer treeview
if (_shellpath_info._open_mode & OWM_EXPLORE) {
if (!_left_hwnd) {
@@ -1709,7 +1726,6 @@ void SDIMainFrame::jump_to(LPCTSTR path, int mode)
} else */{
_shellpath_info._open_mode = mode;
_shellpath_info._shell_path = path;
_shellpath_info._root_shell_path = SpecialFolderPath(CSIDL_DRIVES, _hwnd); //@@ path
update_shell_browser();
}
@@ -1726,7 +1742,6 @@ void SDIMainFrame::jump_to(LPCITEMIDLIST path, int mode)
} else {
_shellpath_info._open_mode = mode;
_shellpath_info._shell_path = path;
_shellpath_info._root_shell_path = path; //@@ MF 02.10.2005 was: SpecialFolderPath(CSIDL_DRIVES, _hwnd);
update_shell_browser();
}
@@ -112,7 +112,9 @@ protected:
HWND _hmdiclient;
WindowHandle _hextrabar;
#ifndef _NO_WIN_FS
WindowHandle _hdrivebar;
#endif
protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
@@ -128,7 +130,9 @@ protected:
virtual bool go_to(LPCTSTR url, bool new_window);
#ifndef _NO_WIN_FS
TCHAR _drives[BUFFER_LEN];
#endif
};
#endif
@@ -1,5 +1,5 @@
/*
* Copyright 2004 Martin Fuchs
* Copyright 2004, 2005 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -262,12 +262,14 @@ void NtObjDirectory::read_directory(int scan_flags)
entry = NULL;
#ifndef _NO_WIN_FS
if (*w32fd.cFileName>='A' &&*w32fd.cFileName<='Z' && w32fd.cFileName[1]==':')
if (!_tcsncmp(buffer,TEXT("\\??\\"),4) || // NT4
!_tcsncmp(buffer,TEXT("\\GLOBAL??"),9)) { // XP
w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
entry = new WinDirectory(this, w32fd.cFileName);
}
#endif
if (!entry)
entry = new NtObjDirectory(this, buffer);
@@ -117,26 +117,31 @@ void ShellBrowser::jump_to(LPCITEMIDLIST pidl)
//LOG(FmtString(TEXT("ShellBrowser::jump_to(): pidl=%s"), (LPCTSTR)FileSysShellPath(pidl)));
// We could call read_tree() here to iterate through the hierarchy and open all folders
// from _create_info._root_shell_path (_cur_dir) to _create_info._shell_path (pidl).
// To make it easier we just use ILFindChild() instead.
if (_cur_dir) {
static DynamicFct<LPITEMIDLIST(WINAPI*)(LPCITEMIDLIST, LPCITEMIDLIST)> ILFindChild(TEXT("SHELL32"), 24);
/*@todo
we should call read_tree() here to iterate through the hierarchy and open all folders from _create_info._root_shell_path (_cur_dir) to _create_info._shell_path (pidl)
_root._entry->read_tree(_create_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME);
-> see FileChildWindow::FileChildWindow()_create_info._shell_path
*/
if (ILFindChild) {
for(;;) {
LPCITEMIDLIST child_pidl = (*ILFindChild)(_cur_dir->create_absolute_pidl(), pidl);
if (!child_pidl || !child_pidl->mkid.cb)
break;
LPCITEMIDLIST child_pidl;
_cur_dir->smart_scan();
if (ILFindChild)
child_pidl = (*ILFindChild)(_cur_dir->create_absolute_pidl(), pidl);
else
child_pidl = pidl; // This is not correct in the common case, but works on the desktop level.
entry = _cur_dir->find_entry(child_pidl);
if (!entry)
break;
if (child_pidl) {
_cur_dir = static_cast<ShellDirectory*>(entry);
_callback->entry_selected(entry);
}
} else {
_cur_dir->smart_scan();
entry = _cur_dir->find_entry(child_pidl);
entry = _cur_dir->find_entry(pidl); // This is not correct in the common case, but works on the desktop level.
if (entry) {
_cur_dir = static_cast<ShellDirectory*>(entry);
@@ -145,7 +150,7 @@ void ShellBrowser::jump_to(LPCITEMIDLIST pidl)
}
}
//@@ work around as long as we don't iterate correctly through the ShellEntry tree
// If not already called, now directly call UpdateFolderView() using pidl
if (!entry)
UpdateFolderView(ShellFolder(pidl));
}
@@ -325,6 +330,12 @@ int ShellBrowser::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFold
HandleException(e, g_Globals._hMainWnd);
}
// remove old children items
for(HTREEITEM hchild,hnext=TreeView_GetChild(_left_hwnd, hParentItem); hchild=hnext; ) {
hnext = TreeView_GetNextSibling(_left_hwnd, hchild);
TreeView_DeleteItem(_left_hwnd, hchild);
}
TV_ITEM tvItem;
TV_INSERTSTRUCT tvInsert;
@@ -623,8 +634,6 @@ void MDIShellBrowserChild::update_shell_browser()
delete _shellBrowser.release();
}
///@todo use OWM_ROOTED flag
// create explorer treeview
if (_create_info._open_mode & OWM_EXPLORE) {
if (!_left_hwnd) {
@@ -1,5 +1,5 @@
/*
* Copyright 2003, 2004 Martin Fuchs
* Copyright 2003, 2004, 2005 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -240,6 +240,7 @@ void ShellDirectory::read_directory(int scan_flags)
/*if (_folder.empty())
return;*/
#ifndef _NO_WIN_FS
TCHAR buffer[MAX_PATH];
if ((scan_flags&SCAN_FILESYSTEM) && get_path(buffer, COUNTOF(buffer)) && _tcsncmp(buffer,TEXT("::{"),3)) {
@@ -304,7 +305,7 @@ void ShellDirectory::read_directory(int scan_flags)
DWORD attribs = SFGAO_FILESYSTEM;
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
attribs |= SFGAO_FOLDER;
attribs |= SFGAO_FOLDER|SFGAO_HASSUBFOLDER;
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
attribs |= SFGAO_READONLY;
@@ -332,8 +333,10 @@ void ShellDirectory::read_directory(int scan_flags)
FindClose(hFind);
}
} else { // !SCAN_FILESYSTEM
}
else // !SCAN_FILESYSTEM
#endif
{
ShellItemEnumerator enumerator(_folder, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN|SHCONTF_SHAREABLE|SHCONTF_STORAGE);
+20 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2003, 2004 Martin Fuchs
* Copyright 2003, 2004, 2005 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,8 @@
#include <precomp.h>
#ifndef _NO_WIN_FS
//#include "winfs.h"
@@ -138,6 +140,19 @@ void WinDirectory::read_directory(int scan_flags)
if (hFind != INVALID_HANDLE_VALUE) {
do {
#ifdef _NO_WIN_FS //@todo not really correct: We shouldn't hide . and ..
// ignore hidden files (usefull in the start menu)
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
continue;
// ignore directory entries "." and ".."
if ((w32fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) &&
w32fd.cFileName[0]==TEXT('.') &&
(w32fd.cFileName[1]==TEXT('\0') ||
(w32fd.cFileName[1]==TEXT('.') && w32fd.cFileName[2]==TEXT('\0'))))
continue;
#endif
lstrcpy(pname+1, w32fd.cFileName);
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
@@ -175,7 +190,8 @@ void WinDirectory::read_directory(int scan_flags)
last = entry; // There is always at least one entry, because FindFirstFile() succeeded and we don't filter the file entries.
} while(FindNextFile(hFind, &w32fd));
last->_next = NULL;
if (last)
last->_next = NULL;
FindClose(hFind);
}
@@ -245,3 +261,5 @@ ShellPath WinEntry::create_absolute_pidl() const
return ShellPath();
}
#endif // _NO_WIN_FS
@@ -26,11 +26,6 @@
//
#define _LIGHT_STARTMENU
#define _LAZY_ICONEXTRACT
#define _SINGLE_ICONEXTRACT
#define CLASSNAME_STARTMENU TEXT("ReactosStartmenuClass")
#define TITLE_STARTMENU TEXT("Start Menu")