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
29 #include "../utility/utility.h"
31 #include "../explorer.h"
32 #include "../globals.h"
34 #include "../explorer_intres.h"
37 MainFrame::MainFrame(HWND hwnd)
40 _hMenuFrame = GetMenu(hwnd);
41 _hMenuWindow = GetSubMenu(_hMenuFrame, GetMenuItemCount(_hMenuFrame)-2);
43 _menu_info._hMenuView = GetSubMenu(_hMenuFrame, 3);
44 _menu_info._hMenuOptions = GetSubMenu(_hMenuFrame, 4);
46 _hAccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_EXPLORER));
49 CLIENTCREATESTRUCT ccs;
51 ccs.hWindowMenu = _hMenuWindow;
52 ccs.idFirstChild = IDW_FIRST_CHILD;
55 _hmdiclient = CreateWindowEx(0, TEXT("MDICLIENT"), NULL,
56 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
58 hwnd, 0, g_Globals._hInstance, &ccs);
61 TBBUTTON toolbarBtns[] = {
62 {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
63 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
64 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
65 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
66 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
68 {4, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
69 {5, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
72 _htoolbar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE,
73 IDW_TOOLBAR, 2, g_Globals._hInstance, IDB_TOOLBAR, toolbarBtns,
74 sizeof(toolbarBtns)/sizeof(TBBUTTON), 16, 15, 16, 15, sizeof(TBBUTTON));
76 CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
79 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
83 _hdrivebar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
84 IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn,
85 1, 16, 13, 16, 13, sizeof(TBBUTTON));
86 CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED);
89 GetLogicalDriveStrings(BUFFER_LEN, _drives);
91 drivebarBtn.fsStyle = BTNS_BUTTON;
94 // insert unix file system button
95 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)TEXT("/\0"));
97 drivebarBtn.idCommand = ID_DRIVE_UNIX_FS;
98 SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
99 ++drivebarBtn.iString;
102 // insert explorer window button
103 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)TEXT("Explore\0"));
105 drivebarBtn.idCommand = ID_DRIVE_DESKTOP;
106 SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
107 ++drivebarBtn.iString;
109 // insert shell namespace button
110 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)TEXT("Shell\0"));
112 drivebarBtn.idCommand = ID_DRIVE_SHELL_NS;
113 SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
114 ++drivebarBtn.iString;
116 // register windows drive root strings
117 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)_drives);
119 drivebarBtn.idCommand = ID_DRIVE_FIRST;
121 for(p=_drives; *p; ) {
122 // insert drive letter
123 TCHAR b[3] = {tolower(*p)};
124 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)b);
126 switch(GetDriveType(p)) {
127 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
128 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
129 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
130 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
131 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
134 SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
135 ++drivebarBtn.idCommand;
136 ++drivebarBtn.iString;
142 /* CreateStatusWindow does not accept WS_BORDER
143 _hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
144 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
145 hwnd, (HMENU)IDW_STATUSBAR, g_Globals._hInstance, 0);*/
147 _hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, hwnd, IDW_STATUSBAR);
148 CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
152 MainFrame::~MainFrame()
154 // don't exit desktop when closing file manager window
155 if (!g_Globals._desktop_mode)
160 HWND MainFrame::Create()
162 HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_MAINFRAME));
164 return super::Create(WINDOW_CREATOR(MainFrame), 0,
165 (LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW,
166 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
167 0/*hwndDesktop*/, hMenuFrame);
170 HWND MainFrame::Create(LPCTSTR path, BOOL mode_explore)
172 HWND hMainFrame = Create();
176 ShowWindow(hMainFrame, SW_SHOW);
178 MainFrame* pMainFrame = GET_WINDOW(MainFrame, hMainFrame);
181 pMainFrame->CreateChild(path, mode_explore);
187 ChildWindow* MainFrame::CreateChild(LPCTSTR path, BOOL mode_explore)
189 return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode_explore, (LPARAM)path));
193 LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
196 case PM_TRANSLATE_MSG: {
197 MSG* pmsg = (MSG*) lparam;
200 if (_hmdiclient && TranslateMDISysAccel(_hmdiclient, pmsg))
204 if (TranslateAccelerator(_hwnd, _hAccel, pmsg))
210 DestroyWindow(_hwnd);
211 g_Globals._hMainWnd = 0;
218 resize_frame(LOWORD(lparam), HIWORD(lparam));
219 break; // do not pass message to DefFrameProc
221 case WM_GETMINMAXINFO: {
222 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
224 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
225 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
228 case PM_FRM_CALC_CLIENT:
229 frame_get_clientspace((PRECT)lparam);
232 case PM_FRM_GET_MENUINFO:
233 return (LPARAM)&_menu_info;
235 case PM_OPEN_WINDOW: {
236 TCHAR buffer[MAX_PATH];
238 ShellPath shell_path = DesktopFolder();
241 // take over path from lparam
242 path = (LPCTSTR)lparam;
243 shell_path = path; // create as "rooted" window
245 //TODO: read paths and window placements from registry
246 GetCurrentDirectory(MAX_PATH, buffer);
250 // Shell Namespace as default view
251 ShellChildWndInfo create_info(path, shell_path);
253 create_info._pos.showCmd = SW_SHOWMAXIMIZED;
254 create_info._pos.rcNormalPosition.left = 0;
255 create_info._pos.rcNormalPosition.top = 0;
256 create_info._pos.rcNormalPosition.right = 600;
257 create_info._pos.rcNormalPosition.bottom = 280;
259 create_info._mode_explore = wparam? true: false;
261 // FileChildWindow::create(_hmdiclient, create_info);
262 return (LRESULT)ShellBrowserChild::create(_hmdiclient, create_info);}
264 case PM_GET_CONTROLWINDOW:
265 if (wparam == FCW_STATUS)
266 return (LRESULT)(HWND)_hstatusbar;
271 return DefFrameProc(_hwnd, _hmdiclient, nmsg, wparam, lparam);
273 return super::WNdProc(nmsg, wparam, lparam);
281 int MainFrame::Command(int id, int code)
284 HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
286 if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
290 if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
291 TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
292 LPCTSTR root = _drives;
294 for(int i=id-ID_DRIVE_FIRST; i--; root++)
298 if (activate_drive_window(root))
301 _tsplitpath(root, drv, 0, 0, 0);
303 if (!SetCurrentDirectory(drv)) {
304 display_error(_hwnd, GetLastError());
308 GetCurrentDirectory(MAX_PATH, path); //TODO: store last directory per drive
311 FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
313 //TODO: SDI implementation
320 SendMessage(_hwnd, WM_CLOSE, 0, 0);
323 case ID_WINDOW_NEW: {
324 TCHAR path[MAX_PATH];
326 GetCurrentDirectory(MAX_PATH, path);
329 FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
331 //TODO: SDI implementation
336 case ID_WINDOW_CASCADE:
337 SendMessage(_hmdiclient, WM_MDICASCADE, 0, 0);
340 case ID_WINDOW_TILE_HORZ:
341 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
344 case ID_WINDOW_TILE_VERT:
345 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
348 case ID_WINDOW_ARRANGE:
349 SendMessage(_hmdiclient, WM_MDIICONARRANGE, 0, 0);
353 case ID_VIEW_TOOL_BAR:
354 toggle_child(_hwnd, id, _htoolbar);
357 case ID_VIEW_DRIVE_BAR:
358 toggle_child(_hwnd, id, _hdrivebar);
361 case ID_VIEW_STATUSBAR:
362 toggle_child(_hwnd, id, _hstatusbar);
366 ExecuteDialog dlg = {{0}, 0};
368 if (DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(IDD_EXECUTE), _hwnd, ExecuteDialog::WndProc, (LPARAM)&dlg) == IDOK) {
369 HINSTANCE hinst = ShellExecute(_hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
371 if ((int)hinst <= 32)
372 display_error(_hwnd, GetLastError());
377 WinHelp(_hwnd, TEXT("explorer")/*file explorer.hlp*/, HELP_INDEX, 0);
380 case ID_VIEW_FULLSCREEN:
381 CheckMenuItem(_menu_info._hMenuOptions, id, toggle_fullscreen()?MF_CHECKED:0);
385 case ID_DRIVE_UNIX_FS: {
386 TCHAR path[MAX_PATH];
387 FileChildWindow* child;
389 if (activate_fs_window(TEXT("unixfs")))
392 getcwd(path, MAX_PATH);
395 FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
397 //TODO: SDI implementation
401 case ID_DRIVE_SHELL_NS: {
402 TCHAR path[MAX_PATH];
404 if (activate_fs_window(TEXT("Shell")))
407 GetCurrentDirectory(MAX_PATH, path);
410 FileChildWindow::create(_hmdiclient, ShellChildWndInfo(path,DesktopFolder()));
412 //TODO: SDI implementation
416 case ID_DRIVE_DESKTOP: {
417 TCHAR path[MAX_PATH];
420 if (activate_fs_window(TEXT("Desktop")))
424 GetCurrentDirectory(MAX_PATH, path);
426 ShellBrowserChild::create(_hmdiclient, ShellChildWndInfo(path,DesktopFolder()));
429 //TODO: There are even more menu items!
432 ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0);
436 /*TODO: if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
437 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE);
438 else */if ((id<IDW_FIRST_CHILD || id>=IDW_FIRST_CHILD+0x100) &&
439 (id<SC_SIZE || id>SC_RESTORE))
440 MessageBox(_hwnd, TEXT("Not yet implemented"), ResString(IDS_TITLE), MB_OK);
443 return DefFrameProc(_hwnd, _hmdiclient, WM_COMMAND, MAKELONG(id,code), 0);
453 void MainFrame::resize_frame_rect(PRECT prect)
457 if (IsWindowVisible(_htoolbar)) {
458 SendMessage(_htoolbar, WM_SIZE, 0, 0);
459 ClientRect rt(_htoolbar);
460 prect->top = rt.bottom+3;
461 prect->bottom -= rt.bottom+3;
464 if (IsWindowVisible(_hdrivebar)) {
465 SendMessage(_hdrivebar, WM_SIZE, 0, 0);
466 ClientRect rt(_hdrivebar);
467 new_top = --prect->top + rt.bottom+3;
468 MoveWindow(_hdrivebar, 0, prect->top, rt.right, new_top, TRUE);
469 prect->top = new_top;
470 prect->bottom -= rt.bottom+2;
473 if (IsWindowVisible(_hstatusbar)) {
474 int parts[] = {300, 500};
476 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
477 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
478 ClientRect rt(_hstatusbar);
479 prect->bottom -= rt.bottom;
483 MoveWindow(_hmdiclient, prect->left-1,prect->top-1,prect->right+2,prect->bottom+1, TRUE);
487 void MainFrame::resize_frame(int cx, int cy)
496 resize_frame_rect(&rect);
499 void MainFrame::resize_frame_client()
501 ClientRect rect(_hwnd);
503 resize_frame_rect(&rect);
506 void MainFrame::frame_get_clientspace(PRECT prect)
508 if (!IsIconic(_hwnd))
509 GetClientRect(_hwnd, prect);
513 GetWindowPlacement(_hwnd, &wp);
515 prect->left = prect->top = 0;
516 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
517 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
518 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
519 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
520 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
523 if (IsWindowVisible(_htoolbar)) {
524 ClientRect rt(_htoolbar);
525 prect->top += rt.bottom+2;
528 if (IsWindowVisible(_hdrivebar)) {
529 ClientRect rt(_hdrivebar);
530 prect->top += rt.bottom+2;
533 if (IsWindowVisible(_hstatusbar)) {
534 ClientRect rt(_hstatusbar);
535 prect->bottom -= rt.bottom;
539 BOOL MainFrame::toggle_fullscreen()
543 if ((_fullscreen._mode=!_fullscreen._mode)) {
544 GetWindowRect(_hwnd, &_fullscreen._orgPos);
545 _fullscreen._wasZoomed = IsZoomed(_hwnd);
547 Frame_CalcFrameClient(_hwnd, &rt);
548 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
549 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
551 rt.left = _fullscreen._orgPos.left-rt.left;
552 rt.top = _fullscreen._orgPos.top-rt.top;
553 rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right;
554 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom;
556 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
558 MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top,
559 _fullscreen._orgPos.right-_fullscreen._orgPos.left,
560 _fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE);
562 if (_fullscreen._wasZoomed)
563 ShowWindow(_hwnd, WS_MAXIMIZE);
566 return _fullscreen._mode;
569 void MainFrame::fullscreen_move()
572 GetWindowRect(_hwnd, &pos);
574 Frame_CalcFrameClient(_hwnd, &rt);
575 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
576 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
578 rt.left = pos.left-rt.left;
579 rt.top = pos.top-rt.top;
580 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
581 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
583 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
587 void MainFrame::toggle_child(HWND hwnd, UINT cmd, HWND hchild)
589 BOOL vis = IsWindowVisible(hchild);
591 CheckMenuItem(_menu_info._hMenuOptions, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
593 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
595 if (_fullscreen._mode)
598 resize_frame_client();
602 bool MainFrame::activate_drive_window(LPCTSTR path)
604 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
607 _tsplitpath(path, drv1, 0, 0, 0);
609 // search for a already open window for the same drive
610 for(child_wnd=::GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=::GetNextWindow(child_wnd, GW_HWNDNEXT)) {
611 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
614 _tsplitpath(child->get_root()._path, drv2, 0, 0, 0);
616 if (!lstrcmpi(drv2, drv1)) {
617 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
619 if (IsMinimized(child_wnd))
620 ShowWindow(child_wnd, SW_SHOWNORMAL);
630 bool MainFrame::activate_fs_window(LPCTSTR filesys)
634 // search for a already open window of the given file system name
635 for(child_wnd=::GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=::GetNextWindow(child_wnd, GW_HWNDNEXT)) {
636 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
639 if (!lstrcmpi(child->get_root()._fs, filesys)) {
640 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
642 if (IsMinimized(child_wnd))
643 ShowWindow(child_wnd, SW_SHOWNORMAL);