2 * Copyright 2003 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 // Martin Fuchs, 23.07.2003
27 // Credits: Thanks to Leon Finker for his explorer window example
31 #include "utility/utility.h"
34 #include "desktop/desktop.h"
37 #include "externals.h"
39 #include "explorer_intres.h"
41 #include <locale.h> // for setlocale()
44 ExplorerGlobals g_Globals
;
47 ExplorerGlobals::ExplorerGlobals()
53 _prescan_nodes
= false;
54 _desktop_mode
= false;
56 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
65 void ExplorerGlobals::init(HINSTANCE hInstance
)
67 _hInstance
= hInstance
;
69 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
70 _SHRestricted
= (DWORD(STDAPICALLTYPE
*)(RESTRICTIONS
)) GetProcAddress(GetModuleHandle(TEXT("SHELL32")), "SHRestricted");
77 void _log_(LPCTSTR txt
)
79 FmtString
msg(TEXT("%s\n"), txt
);
82 _fputts(msg
, g_Globals
._log
);
84 OutputDebugString(msg
);
88 bool FileTypeManager::is_exe_file(LPCTSTR ext
)
90 static const LPCTSTR s_executable_extensions
[] = {
101 TCHAR ext_buffer
[_MAX_EXT
];
106 for(s
=ext
+1,d
=ext_buffer
; (*d
=toupper(*s
)); s
++)
109 for(p
=s_executable_extensions
; *p
; p
++)
110 if (!lstrcmp(ext_buffer
, *p
))
117 const FileTypeInfo
& FileTypeManager::operator[](String ext
)
119 _tcslwr((LPTSTR
)ext
.c_str());
121 iterator found
= find(ext
);
123 return found
->second
;
125 FileTypeInfo
& ftype
= super::operator[](ext
);
127 ftype
._neverShowExt
= false;
130 TCHAR value
[MAX_PATH
], display_name
[MAX_PATH
];;
131 LONG valuelen
= sizeof(value
);
133 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ext
, value
, &valuelen
)) {
134 ftype
._classname
= value
;
136 valuelen
= sizeof(display_name
);
137 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ftype
._classname
, display_name
, &valuelen
))
138 ftype
._displayname
= display_name
;
140 if (!RegOpenKey(HKEY_CLASSES_ROOT
, ftype
._classname
, &hkey
)) {
141 if (!RegQueryValueEx(hkey
, TEXT("NeverShowExt"), 0, NULL
, NULL
, NULL
))
142 ftype
._neverShowExt
= true;
151 LPCTSTR
FileTypeManager::set_type(Entry
* entry
, bool dont_hide_ext
)
153 LPCTSTR ext
= _tcsrchr(entry
->_data
.cFileName
, TEXT('.'));
156 const FileTypeInfo
& type
= (*this)[ext
];
158 if (!type
._displayname
.empty())
159 entry
->_type_name
= _tcsdup(type
._displayname
);
161 // hide some file extensions
162 if (type
._neverShowExt
&& !dont_hide_ext
) {
163 int len
= ext
- entry
->_data
.cFileName
;
164 entry
->_display_name
= (LPTSTR
) malloc((len
+1)*sizeof(TCHAR
));
165 _tcsncpy(entry
->_display_name
, entry
->_data
.cFileName
, len
);
166 entry
->_display_name
[len
] = TEXT('\0');
169 if (is_exe_file(ext
))
170 entry
->_data
.dwFileAttributes
|= ATTRIBUTE_EXECUTABLE
;
184 Icon::Icon(ICON_ID id
, UINT nid
)
187 _hicon(SmallIcon(nid
))
191 Icon::Icon(ICON_TYPE itype
, int id
, HICON hIcon
)
198 Icon::Icon(ICON_TYPE itype
, int id
, int sys_idx
)
205 void Icon::draw(HDC hdc
, int x
, int y
, int cx
, int cy
, COLORREF bk_color
, HBRUSH bk_brush
) const
207 if (_itype
== IT_SYSCACHE
)
208 ImageList_DrawEx(g_Globals
._icon_cache
.get_sys_imagelist(), _sys_idx
, hdc
, x
, y
, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
210 DrawIconEx(hdc
, x
, y
, _hicon
, cx
, cy
, 0, bk_brush
, DI_NORMAL
);
213 HBITMAP
Icon::create_bitmap(COLORREF bk_color
, HBRUSH hbrBkgnd
, HDC hdc_wnd
) const
215 if (_itype
== IT_SYSCACHE
) {
216 HIMAGELIST himl
= g_Globals
._icon_cache
.get_sys_imagelist();
219 ImageList_GetIconSize(himl
, &cx
, &cy
);
221 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
222 HDC hdc
= CreateCompatibleDC(hdc_wnd
);
223 HBITMAP hbmp_old
= SelectBitmap(hdc
, hbmp
);
224 ImageList_DrawEx(himl
, _sys_idx
, hdc
, 0, 0, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
225 SelectBitmap(hdc
, hbmp_old
);
229 return create_bitmap_from_icon(_hicon
, hbrBkgnd
, hdc_wnd
);
232 HBITMAP
create_bitmap_from_icon(HICON hIcon
, HBRUSH hbrush_bkgnd
, HDC hdc_wnd
)
234 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, 16, 16);
237 BitmapSelection
sel(canvas
, hbmp
);
239 RECT rect
= {0, 0, 16, 16};
240 FillRect(canvas
, &rect
, hbrush_bkgnd
);
242 DrawIconEx(canvas
, 0, 0, hIcon
, 16, 16, 0, hbrush_bkgnd
, DI_NORMAL
);
248 int IconCache::s_next_id
= ICID_DYNAMIC
;
251 void IconCache::init()
253 _icons
[ICID_NONE
] = Icon(IT_STATIC
, ICID_NONE
, (HICON
)0);
255 _icons
[ICID_FOLDER
] = Icon(ICID_FOLDER
, IDI_FOLDER
);
256 //_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
257 _icons
[ICID_EXPLORER
] = Icon(ICID_EXPLORER
, IDI_EXPLORER
);
258 _icons
[ICID_APP
] = Icon(ICID_APP
, IDI_APPICON
);
260 _icons
[ICID_CONFIG
] = Icon(ICID_CONFIG
, IDI_CONFIG
);
261 _icons
[ICID_DOCUMENTS
] = Icon(ICID_DOCUMENTS
, IDI_DOCUMENTS
);
262 _icons
[ICID_FAVORITES
] = Icon(ICID_FAVORITES
, IDI_FAVORITES
);
263 _icons
[ICID_INFO
] = Icon(ICID_INFO
, IDI_INFO
);
264 _icons
[ICID_APPS
] = Icon(ICID_APPS
, IDI_APPS
);
265 _icons
[ICID_SEARCH
] = Icon(ICID_SEARCH
, IDI_SEARCH
);
266 _icons
[ICID_ACTION
] = Icon(ICID_ACTION
, IDI_ACTION
);
267 _icons
[ICID_SEARCH_DOC
] = Icon(ICID_SEARCH_DOC
, IDI_SEARCH_DOC
);
268 _icons
[ICID_PRINTER
] = Icon(ICID_PRINTER
, IDI_PRINTER
);
269 _icons
[ICID_NETWORK
] = Icon(ICID_NETWORK
, IDI_NETWORK
);
270 _icons
[ICID_COMPUTER
] = Icon(ICID_COMPUTER
, IDI_COMPUTER
);
271 _icons
[ICID_LOGOFF
] = Icon(ICID_LOGOFF
, IDI_LOGOFF
);
275 const Icon
& IconCache::extract(const String
& path
)
277 PathMap::iterator found
= _pathMap
.find(path
);
279 if (found
!= _pathMap
.end())
280 return _icons
[found
->second
];
284 #if 1 // use system image list
285 HIMAGELIST himlSys
= (HIMAGELIST
) SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_SYSICONINDEX
|SHGFI_SMALLICON
);
290 const Icon
& icon
= add(sfi
.iIcon
/*, IT_SYSCACHE*/);
292 if (SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_ICON
|SHGFI_SMALLICON
)) {
293 const Icon
& icon
= add(sfi
.hIcon
, IT_CACHED
);
296 ///@todo limit cache size
297 _pathMap
[path
] = icon
;
301 return _icons
[ICID_NONE
];
304 const Icon
& IconCache::extract(LPCTSTR path
, int idx
)
306 CachePair
key(path
, idx
);
308 _tcslwr((LPTSTR
)key
.first
.c_str());
310 PathIdxMap::iterator found
= _pathIdxMap
.find(key
);
312 if (found
!= _pathIdxMap
.end())
313 return _icons
[found
->second
];
317 if ((int)ExtractIconEx(path
, idx
, NULL
, &hIcon
, 1) > 0) {
318 const Icon
& icon
= add(hIcon
, IT_CACHED
);
320 _pathIdxMap
[key
] = icon
;
324 return _icons
[ICID_NONE
];
327 const Icon
& IconCache::extract(IExtractIcon
* pExtract
, LPCTSTR path
, int idx
)
329 HICON hIconLarge
= 0;
332 HRESULT hr
= pExtract
->Extract(path
, idx
, &hIconLarge
, &hIcon
, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON
)));
336 DestroyIcon(hIconLarge
);
342 return _icons
[ICID_NONE
];
345 const Icon
& IconCache::add(HICON hIcon
, ICON_TYPE type
)
347 int id
= ++s_next_id
;
349 return _icons
[id
] = Icon(type
, id
, hIcon
);
352 const Icon
& IconCache::add(int sys_idx
/*, ICON_TYPE type=IT_SYSCACHE*/)
354 int id
= ++s_next_id
;
356 return _icons
[id
] = SysCacheIcon(id
, sys_idx
);
359 const Icon
& IconCache::get_icon(int id
)
364 void IconCache::free_icon(int icon_id
)
366 IconMap::iterator found
= _icons
.find(icon_id
);
368 if (found
!= _icons
.end()) {
369 Icon
& icon
= found
->second
;
377 ResString::ResString(UINT nid
)
379 TCHAR buffer
[BUFFER_LEN
];
381 int len
= LoadString(g_Globals
._hInstance
, nid
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
383 super::assign(buffer
, len
);
387 ResIcon::ResIcon(UINT nid
)
389 _hicon
= LoadIcon(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
392 SmallIcon::SmallIcon(UINT nid
)
394 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
397 ResIconEx::ResIconEx(UINT nid
, int w
, int h
)
399 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, w
, h
, LR_SHARED
);
403 void SetWindowIcon(HWND hwnd
, UINT nid
)
405 HICON hIcon
= ResIcon(nid
);
406 Window_SetIcon(hwnd
, ICON_BIG
, hIcon
);
408 HICON hIconSmall
= SmallIcon(nid
);
409 Window_SetIcon(hwnd
, ICON_SMALL
, hIconSmall
);
413 ResBitmap::ResBitmap(UINT nid
)
415 _hBmp
= LoadBitmap(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
419 void explorer_show_frame(int cmdshow
, LPTSTR lpCmdLine
)
421 if (g_Globals
._hMainWnd
) {
422 if (IsIconic(g_Globals
._hMainWnd
))
423 ShowWindow(g_Globals
._hMainWnd
, SW_RESTORE
);
425 SetForegroundWindow(g_Globals
._hMainWnd
);
430 g_Globals
._prescan_nodes
= false;
432 // create main window
433 HWND hMainFrame
= MainFrame::Create();
436 g_Globals
._hMainWnd
= hMainFrame
;
438 ShowWindow(hMainFrame
, cmdshow
);
439 UpdateWindow(hMainFrame
);
441 bool valid_dir
= false;
444 DWORD attribs
= GetFileAttributes(lpCmdLine
);
446 if (attribs
!=INVALID_FILE_ATTRIBUTES
&& (attribs
&FILE_ATTRIBUTE_DIRECTORY
))
448 else if (*lpCmdLine
==':' || *lpCmdLine
=='"')
452 // Open the first child window after initializing the application
454 PostMessage(hMainFrame
, PM_OPEN_WINDOW
, 0, (LPARAM
)lpCmdLine
);
456 PostMessage(hMainFrame
, PM_OPEN_WINDOW
, 0/*OWM_EXPLORE|OWM_DETAILS*/, 0);
461 PopupMenu::PopupMenu(UINT nid
)
463 HMENU hMenu
= LoadMenu(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
464 _hmenu
= GetSubMenu(hMenu
, 0);
468 /// "About Explorer" Dialog
469 struct ExplorerAboutDlg
: public
471 OwnerDrawParent
<Dialog
>
474 typedef CtlColorParent
<
475 OwnerDrawParent
<Dialog
>
478 ExplorerAboutDlg(HWND hwnd
)
481 SetWindowIcon(hwnd
, IDI_REACTOS
);
483 new FlatButton(hwnd
, IDOK
);
485 _hfont
= CreateFont(20, 0, 0, 0, FW_BOLD
, TRUE
, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
486 new ColorStatic(hwnd
, IDC_ROS_EXPLORER
, RGB(32,32,128), 0, _hfont
);
488 new HyperlinkCtrl(hwnd
, IDC_WWW
);
495 DeleteObject(_hfont
);
498 LRESULT
WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
506 return super::WndProc(nmsg
, wparam
, lparam
);
514 PaintCanvas
canvas(_hwnd
);
516 HICON hicon
= (HICON
) LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(IDI_REACTOS_BIG
), IMAGE_ICON
, 0, 0, LR_SHARED
);
518 DrawIconEx(canvas
, 20, 10, hicon
, 0, 0, 0, 0, DI_NORMAL
);
525 void explorer_about(HWND hwndParent
)
527 Dialog::DoModal(IDD_ABOUT_EXPLORER
, WINDOW_CREATOR(ExplorerAboutDlg
), hwndParent
);
531 static void InitInstance(HINSTANCE hInstance
)
533 CONTEXT("InitInstance");
535 setlocale(LC_COLLATE
, ""); // set collating rules to local settings for compareName
537 // register frame window class
538 g_Globals
._hframeClass
= IconWindowClass(CLASSNAME_FRAME
,IDI_EXPLORER
);
540 // register child windows class
541 WindowClass(CLASSNAME_CHILDWND
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
543 // register tree windows class
544 WindowClass(CLASSNAME_WINEFILETREE
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
546 g_Globals
._cfStrFName
= RegisterClipboardFormat(CFSTR_FILENAME
);
550 int explorer_main(HINSTANCE hInstance
, LPTSTR lpCmdLine
, int cmdshow
)
552 CONTEXT("explorer_main");
554 // initialize Common Controls library
555 CommonControlInit usingCmnCtrl
;
558 InitInstance(hInstance
);
559 } catch(COMException
& e
) {
560 HandleException(e
, GetDesktopWindow());
564 if (cmdshow
!= SW_HIDE
) {
565 /* // don't maximize if being called from the ROS desktop
566 if (cmdshow == SW_SHOWNORMAL)
567 ///@todo read window placement from registry
568 cmdshow = SW_MAXIMIZE;
571 explorer_show_frame(cmdshow
, lpCmdLine
);
574 return Window::MessageLoop();
578 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
579 #if defined(__MINGW32__) && defined(UNICODE)
581 #define _tWinMain wWinMain
582 int WINAPI
wWinMain(HINSTANCE
, HINSTANCE
, LPWSTR
, int);
584 int main(int argc
, char* argv
[])
588 STARTUPINFO startupinfo
;
589 int nShowCmd
= SW_SHOWNORMAL
;
591 GetStartupInfo(&startupinfo
);
593 if (startupinfo
.dwFlags
& STARTF_USESHOWWINDOW
)
594 nShowCmd
= startupinfo
.wShowWindow
;
596 LPWSTR cmdline
= GetCommandLineW();
598 while(*cmdline
&& !_istspace(*cmdline
))
601 return wWinMain(GetModuleHandle(NULL
), 0, cmdline
, nShowCmd
);
604 #endif // __MINGW && UNICODE
607 int WINAPI
_tWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPTSTR lpCmdLine
, int nShowCmd
)
609 CONTEXT("WinMain()");
611 BOOL any_desktop_running
= IsAnyDesktopRunning();
613 // create desktop window and task bar only, if there is no other shell and we are
614 // the first explorer instance
615 BOOL startup_desktop
= !any_desktop_running
;
617 bool autostart
= !any_desktop_running
;
619 // disable autostart if the SHIFT key is pressed
620 if (GetAsyncKeyState(VK_SHIFT
) < 0)
623 #ifdef _DEBUG //MF: disabled for debugging
627 // If there is given the command line option "-desktop", create desktop window anyways
628 if (_tcsstr(lpCmdLine
,TEXT("-desktop")))
629 startup_desktop
= TRUE
;
630 else if (_tcsstr(lpCmdLine
,TEXT("-nodesktop")))
631 startup_desktop
= FALSE
;
633 // Don't display cabinet window in desktop mode
634 if (startup_desktop
&& !_tcsstr(lpCmdLine
,TEXT("-explorer")))
637 if (_tcsstr(lpCmdLine
,TEXT("-noautostart")))
640 g_Globals
.init(hInstance
);
642 // initialize COM and OLE before creating the desktop window
645 if (startup_desktop
) {
646 g_Globals
._desktops
.init();
648 g_Globals
._hwndDesktop
= DesktopWindow::Create();
651 char* argv
[] = {"", "s"}; // call startup routine in SESSION_START mode
656 /**TODO fix command line handling */
657 if (*lpCmdLine
=='"' && lpCmdLine
[_tcslen(lpCmdLine
)-1]=='"') {
659 lpCmdLine
[_tcslen(lpCmdLine
)-1] = '\0';
662 if (g_Globals
._hwndDesktop
)
663 g_Globals
._desktop_mode
= true;
665 int ret
= explorer_main(hInstance
, lpCmdLine
, nShowCmd
);