b3cf599b214cb5cedd3c948eae8b8fc37998bfb8
[reactos.git] / reactos / base / shell / explorer / shell / mainframe.cpp
1 /*
2 * Copyright 2003, 2004, 2005 Martin Fuchs
3 *
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.
8 *
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.
13 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // mainframe.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 #include <precomp.h>
30
31 /* We can't include webchild.h here - otherwise MinGW produces errors like: "multiple definition of `QACONTAINERFLAGS'"
32 #include "webchild.h"
33 */
34 extern HWND create_webchildwindow(const WebChildWndInfo& info);
35
36 #include "../resource.h"
37
38 #include "../dialogs/settings.h" // for MdiSdiDlg
39
40 //#define _NO_REBAR
41
42 HWND MainFrameBase::Create(const ExplorerCmd& cmd)
43 {
44 HWND hFrame;
45
46 #ifndef _NO_MDI
47 if (cmd._mdi)
48 hFrame = MDIMainFrame::Create();
49 else
50 #endif
51 hFrame = SDIMainFrame::Create();
52
53 if (hFrame) {
54 HWND hwndOld = g_Globals._hMainWnd;
55
56 g_Globals._hMainWnd = hFrame;
57
58 if (hwndOld)
59 DestroyWindow(hwndOld);
60
61 ShowWindow(hFrame, cmd._cmdShow);
62 UpdateWindow(hFrame);
63
64 // Open the first child window after initializing the application
65 if (cmd.IsValidPath()) {
66 // We use the static s_path variable to store the path string in order
67 // to avoid accessing prematurely freed memory in the PostMessage handlers.
68 static String s_path = cmd._path;
69
70 PostMessage(hFrame, PM_OPEN_WINDOW, cmd._flags, (LPARAM)(LPCTSTR)s_path);
71 } else
72 PostMessage(hFrame, PM_OPEN_WINDOW, OWM_EXPLORE|OWM_DETAILS, 0);
73 }
74
75 return hFrame;
76 }
77
78
79 int MainFrameBase::OpenShellFolders(LPIDA pida, HWND hFrameWnd)
80 {
81 int cnt = 0;
82
83 LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
84 ShellFolder folder(parent_pidl);
85 LOG(FmtString(TEXT("MainFrameBase::OpenShellFolders(): parent_pidl=%s"), (LPCTSTR)FileSysShellPath(parent_pidl)));
86
87 for(int i=pida->cidl; i>0; --i) {
88 LPCITEMIDLIST pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]);
89
90 SFGAOF attribs = SFGAO_FOLDER;
91 HRESULT hr = folder->GetAttributesOf(1, &pidl, &attribs);
92
93 if (SUCCEEDED(hr))
94 if (attribs & SFGAO_FOLDER) {
95 try {
96 XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
97
98 bool mdi = XMLBool(explorer_options, "mdi", true);
99 bool separateFolders = XMLBool(explorer_options, "separate-folders", false);
100
101 ShellPath pidl_abs = ShellPath(pidl).create_absolute_pidl(parent_pidl);
102 LOG(FmtString(TEXT("MainFrameBase::OpenShellFolders(): pidl_abs=%s"), (LPCTSTR)FileSysShellPath(pidl_abs)));
103
104 if (hFrameWnd && (mdi || !separateFolders)) {
105 int flags = OWM_PIDL;
106
107 if (separateFolders)
108 flags |= OWM_SEPARATE;
109
110 if (SendMessage(hFrameWnd, PM_OPEN_WINDOW, flags, (LPARAM)(LPCITEMIDLIST)pidl_abs))
111 ++cnt;
112 } else {
113 HWND hwnd;
114 #ifndef _NO_MDI
115 if (mdi)
116 hwnd = MDIMainFrame::Create(pidl_abs, 0);
117 else
118 #endif
119 hwnd = SDIMainFrame::Create(pidl_abs, 0);
120
121 if (hwnd)
122 ++cnt;
123 }
124 } catch(COMException& e) {
125 HandleException(e, g_Globals._hMainWnd);
126 }
127 }/*TEST
128 else { // !(attribs & SFGAO_FOLDER))
129 SHELLEXECUTEINFOA shexinfo;
130
131 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
132 shexinfo.fMask = SEE_MASK_INVOKEIDLIST;
133 shexinfo.hwnd = NULL;
134 shexinfo.lpVerb = NULL;
135 shexinfo.lpFile = NULL;
136 shexinfo.lpParameters = NULL;
137 shexinfo.lpDirectory = NULL;
138 shexinfo.nShow = SW_NORMAL;
139 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
140
141 if (ShellExecuteExA(&shexinfo))
142 ++cnt;
143
144 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
145 }*/
146 }
147
148 return cnt;
149 }
150
151
152 MainFrameBase::MainFrameBase(HWND hwnd)
153 : super(hwnd)
154 {
155 HDC hDC = GetDC(NULL);
156 #ifndef _NO_REBAR
157 //static TCHAR Title1[] = TEXT("Toolbar");
158 static TCHAR Title2[] = TEXT("Address :");
159 #endif
160
161 if (hDC)
162 {
163 DWORD ilMask;
164 INT bpp = GetDeviceCaps(hDC, BITSPIXEL);
165 ReleaseDC(NULL, hDC);
166
167 if (bpp <= 4)
168 ilMask = ILC_COLOR4;
169 else if (bpp <= 8)
170 ilMask = ILC_COLOR8;
171 else if (bpp <= 16)
172 ilMask = ILC_COLOR16;
173 else if (bpp <= 24)
174 ilMask = ILC_COLOR24;
175 else if (bpp <= 32)
176 ilMask = ILC_COLOR32;
177 else
178 ilMask = ILC_COLOR;
179
180 ilMask |= ILC_MASK;
181
182 _himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ilMask, 2, 0);
183 }
184
185 _hMenuFrame = GetMenu(hwnd);
186 _hMenuWindow = GetSubMenu(_hMenuFrame, GetMenuItemCount(_hMenuFrame)-3);
187
188 _menu_info._hMenuView = GetSubMenu(_hMenuFrame, 1);
189
190 _hAccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_EXPLORER));
191
192
193 TBBUTTON toolbarBtns[] = {
194 #ifdef _NO_REBAR
195 {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
196 #endif
197 {7, ID_GO_BACK, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
198 {8, ID_GO_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
199 {9, ID_GO_UP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
200 {10, ID_GO_HOME, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
201 {11, ID_GO_SEARCH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
202 {12, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
203 {13, ID_STOP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}
204 };
205
206 _htoolbar = CreateToolbarEx(hwnd,
207 #ifndef _NO_REBAR
208 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
209 #endif
210 WS_CHILD|TBSTYLE_FLAT|WS_VISIBLE, IDW_TOOLBAR, 2, g_Globals._hInstance, IDB_TOOLBAR,
211 toolbarBtns, sizeof(toolbarBtns)/sizeof(TBBUTTON),
212 16, 16, 16, 16, sizeof(TBBUTTON));
213
214 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
215
216
217 // address bar
218 _haddrcombo = CreateWindowEx(0,
219 WC_COMBOBOX,
220 TEXT("Address"),
221 WS_CHILD|WS_TABSTOP|WS_BORDER|WS_VISIBLE|CBS_DROPDOWN|
222 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|CCS_NOMOVEY,
223 0, 0, 0, 0,
224 hwnd,
225 (HMENU)IDW_ADDRESSBAR,
226 g_Globals._hInstance,
227 0);
228
229 HFONT hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
230 SendMessageW(_haddrcombo, WM_SETFONT, (WPARAM)hFont, 0);
231
232
233 _hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, hwnd, IDW_STATUSBAR);
234 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
235
236 _hsidebar = CreateWindowEx(WS_EX_STATICEDGE, WC_TREEVIEW, TEXT("Sidebar"),
237 WS_CHILD|WS_TABSTOP|WS_BORDER|/*WS_VISIBLE|*/WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_INFOTIP,
238 -1, -1, 200, 0, _hwnd, (HMENU)IDW_SIDEBAR, g_Globals._hInstance, 0);
239
240 _himl_old = TreeView_SetImageList(_hsidebar, _himl, TVSIL_NORMAL);
241
242 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_SIDE_BAR, MF_BYCOMMAND|MF_UNCHECKED/*MF_CHECKED*/);
243
244
245 // create rebar window to manage toolbar and drivebar
246 #ifndef _NO_REBAR
247 _hwndrebar = CreateWindowEx(WS_EX_TOOLWINDOW,
248 REBARCLASSNAME,
249 NULL,
250 WS_CHILD|WS_VISIBLE|WS_BORDER|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|
251 RBS_VARHEIGHT|RBS_DBLCLKTOGGLE| RBS_AUTOSIZE|RBS_BANDBORDERS,
252 0, 0, 0, 0,
253 _hwnd,
254 NULL,
255 g_Globals._hInstance,
256 0);
257
258 int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0));
259
260 REBARBANDINFO rbBand;
261
262 rbBand.cbSize = sizeof(REBARBANDINFO);
263 rbBand.fMask = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
264 rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE;
265
266 rbBand.cxMinChild = 0;
267 rbBand.cyMinChild = 0;
268 rbBand.cyChild = 0;
269 rbBand.cyMaxChild = 0;
270 rbBand.cyIntegral = btn_hgt;
271
272 rbBand.lpText = NULL;//Title1
273 rbBand.hwndChild = _htoolbar;
274 rbBand.cxMinChild = 0;
275 rbBand.cyMinChild = btn_hgt;
276 rbBand.cx = 284;
277 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)0, (LPARAM)&rbBand);
278
279 rbBand.fStyle &= ~RBBS_HIDETITLE;
280 rbBand.fStyle |= RBBS_BREAK;
281 rbBand.lpText = Title2;
282 rbBand.hwndChild = _haddrcombo;
283 rbBand.cxMinChild = 0;
284 rbBand.cyMinChild = btn_hgt;
285 rbBand.cx = 400;
286 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)3, (LPARAM)&rbBand);
287 #endif
288 }
289
290
291 MainFrameBase::~MainFrameBase()
292 {
293 (void)TreeView_SetImageList(_hsidebar, _himl_old, TVSIL_NORMAL);
294 ImageList_Destroy(_himl);
295
296 // don't exit desktop when closing file manager window
297 if (!g_Globals._desktop_mode)
298 if (g_Globals._hMainWnd == _hwnd) // don't quit when switching between MDI and SDI mode
299 PostQuitMessage(0);
300 }
301
302
303 LRESULT MainFrameBase::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
304 {
305 LRESULT res;
306
307 if (ProcessMessage(nmsg, wparam, lparam, &res))
308 return res;
309 else
310 return super::WndProc(nmsg, wparam, lparam);
311 }
312
313 bool MainFrameBase::ProcessMessage(UINT nmsg, WPARAM wparam, LPARAM lparam, LRESULT* pres)
314 {
315 switch(nmsg) {
316 case PM_TRANSLATE_MSG:
317 *pres = TranslateMsg((MSG*)lparam);
318 return true;
319
320 case WM_SHOWWINDOW:
321 if (wparam) { // trigger child resizing after window creation - now we can succesfully call IsWindowVisible()
322 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
323 MoveWindow(_hwndrebar, 0, 0, LOWORD(lparam), height, TRUE);
324 resize_frame_client();
325 }
326 return false; // goto def;
327
328 case WM_CLOSE:
329 DestroyWindow(_hwnd);
330 g_Globals._hMainWnd = 0;
331 break;
332
333 case WM_DESTROY:
334 break;
335
336 case WM_SIZE: {
337 #ifdef __REACTOS__ ///@todo Work around to display rebar in ROS (with flickering) as long as the control isn't fixed
338 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
339 MoveWindow(_hwndrebar, 0, 0, LOWORD(lparam), height, TRUE);
340 #else
341 resize_frame(LOWORD(lparam), HIWORD(lparam));
342 SendMessage(_hwndrebar, WM_SIZE, 0, 0);
343 #endif
344
345
346 break;} // do not pass message to DefFrameProc
347
348 case WM_GETMINMAXINFO: {
349 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
350
351 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
352 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
353 break;}
354
355 case PM_FRM_CALC_CLIENT:
356 frame_get_clientspace((PRECT)lparam);
357 *pres = TRUE;
358 return true;
359
360 case PM_FRM_GET_MENUINFO:
361 *pres = (LPARAM)&_menu_info;
362 return true;
363
364 case PM_GET_CONTROLWINDOW:
365 if (wparam == FCW_STATUS) {
366 *pres = (LRESULT)(HWND)_hstatusbar;
367 return true;
368 }
369 break;
370
371 case PM_SETSTATUSTEXT:
372 SendMessage(_hstatusbar, SB_SETTEXT, 0, lparam);
373 break;
374
375 case WM_SYSCOLORCHANGE:
376 SendMessage(_hwndrebar, WM_SYSCOLORCHANGE, 0, 0);
377 SendMessage(_htoolbar, WM_SYSCOLORCHANGE, 0, 0);
378 break;
379
380 default:
381 return false;
382 }
383
384 *pres = 0;
385 return true;
386 }
387
388 BOOL MainFrameBase::TranslateMsg(MSG* pmsg)
389 {
390 if (TranslateAccelerator(_hwnd, _hAccel, pmsg))
391 return TRUE;
392
393 return FALSE;
394 }
395
396
397 int MainFrameBase::Command(int id, int code)
398 {
399 CONTEXT("MainFrameBase::Command()");
400
401 switch(id) {
402 case ID_FILE_EXIT:
403 SendMessage(_hwnd, WM_CLOSE, 0, 0);
404 break;
405
406 case ID_VIEW_TOOL_BAR:
407 toggle_child(_hwnd, id, _htoolbar, 0);
408 break;
409
410 case ID_VIEW_STATUSBAR:
411 toggle_child(_hwnd, id, _hstatusbar);
412 break;
413
414 case ID_VIEW_SIDE_BAR:
415 // lazy initialization
416 if (!TreeView_GetCount(_hsidebar))
417 FillBookmarks();
418
419 toggle_child(_hwnd, id, _hsidebar);
420 break;
421
422 case ID_EXECUTE: {
423 ExecuteDialog dlg = {{0}, 0};
424
425 if (DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(IDD_EXECUTE), _hwnd, ExecuteDialog::WndProc, (LPARAM)&dlg) == IDOK) {
426 CONTEXT("ID_EXECUTE - ShellExecute()");
427
428 HINSTANCE hinst = ShellExecute(_hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
429
430 if ((int)hinst <= 32)
431 display_error(_hwnd, GetLastError());
432 }
433 break;}
434
435 case ID_HELP:
436 WinHelp(_hwnd, TEXT("explorer")/*file explorer.hlp*/, HELP_INDEX, 0);
437 break;
438
439 case ID_VIEW_FULLSCREEN:
440 CheckMenuItem(_menu_info._hMenuView, id, toggle_fullscreen()?MF_CHECKED:0);
441 break;
442
443 case ID_TOOLS_OPTIONS:
444 Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), _hwnd);
445 break;
446
447 case ID_ABOUT_WINDOWS:
448 ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0);
449 break;
450
451 case ID_ABOUT_EXPLORER:
452 explorer_about(_hwnd);
453 break;
454
455 case ID_EXPLORER_FAQ:
456 launch_file(_hwnd, TEXT("http://www.sky.franken.de/explorer/"), SW_SHOW);
457 break;
458
459 default:
460 return 1; // no command handlers in Window::Command()
461 }
462
463 return 0;
464 }
465
466 int MainFrameBase::Notify(int id, NMHDR* pnmh)
467 {
468 switch(pnmh->code) {
469 // resize children windows when the rebar size changes
470
471 case RBN_AUTOSIZE:
472 resize_frame_client();
473 break;
474
475 case TVN_GETINFOTIP: {
476 NMTVGETINFOTIP* pnmgit = (NMTVGETINFOTIP*)pnmh;
477
478 if (pnmgit->lParam) {
479 const BookmarkNode& node = *(BookmarkNode*)pnmgit->lParam;
480
481 if (node._type == BookmarkNode::BMNT_FOLDER) {
482 // display tooltips for bookmark folders
483 if (!node._pfolder->_description.empty())
484 lstrcpyn(pnmgit->pszText, node._pfolder->_description.c_str(), pnmgit->cchTextMax);
485 } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
486 // display tooltips for bookmark folders
487 String txt = node._pbookmark->_description;
488
489 if (!node._pbookmark->_url.empty()) {
490 if (!txt.empty())
491 txt += TEXT(" - ");
492
493 txt += node._pbookmark->_url;
494 }
495
496 lstrcpyn(pnmgit->pszText, txt.c_str(), pnmgit->cchTextMax);
497 }
498 }
499 break;}
500
501 case NM_DBLCLK: {
502 HTREEITEM hitem = TreeView_GetSelection(_hsidebar);
503 LPARAM lparam = TreeView_GetItemData(_hsidebar, hitem);
504
505 if (lparam) {
506 const BookmarkNode& node = *(BookmarkNode*)lparam;
507
508 if (node._type == BookmarkNode::BMNT_BOOKMARK) {
509 bool new_window = GetAsyncKeyState(VK_SHIFT)<0;
510
511 go_to(node._pbookmark->_url, new_window);
512 }
513 }
514 break;}
515 }
516
517 return 0;
518 }
519
520
521 void MainFrameBase::resize_frame(int cx, int cy)
522 {
523 if (cy <= 0)
524 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
525
526 RECT rect = {0, 0, cx, cy};
527
528 if (_hwndrebar) {
529 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
530 rect.top += height;
531 rect.top += 5;
532
533 SetWindowPos(_haddrcombo, NULL, 0, 0, cx, height, SWP_NOMOVE);
534 } else {
535 if (IsWindowVisible(_htoolbar)) {
536 SendMessage(_htoolbar, WM_SIZE, 0, 0);
537 WindowRect rt(_htoolbar);
538 rect.top = rt.bottom;
539 // rect.bottom -= rt.bottom;
540 }
541 }
542
543 if (IsWindowVisible(_hstatusbar)) {
544 int parts[] = {300, 500};
545
546 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
547 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
548 ClientRect rt(_hstatusbar);
549 rect.bottom -= rt.bottom;
550 }
551
552 if (IsWindowVisible(_hsidebar)) {
553 WindowRect rt(_hsidebar);
554 rect.left += rt.right-rt.left;
555
556 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
557 }
558 }
559
560 void MainFrameBase::resize_frame_client()
561 {
562 ClientRect rect(_hwnd);
563
564 resize_frame(rect.right, rect.bottom);
565 }
566
567 void MainFrameBase::frame_get_clientspace(PRECT prect)
568 {
569 if (!IsIconic(_hwnd))
570 GetClientRect(_hwnd, prect);
571 else {
572 WINDOWPLACEMENT wp;
573
574 GetWindowPlacement(_hwnd, &wp);
575
576 prect->left = prect->top = 0;
577 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
578 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
579 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
580 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
581 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
582 }
583
584 if (IsWindowVisible(_htoolbar)) {
585 ClientRect rt(_htoolbar);
586 prect->top += rt.bottom+2;
587 }
588
589 if (IsWindowVisible(_hstatusbar)) {
590 ClientRect rt(_hstatusbar);
591 prect->bottom -= rt.bottom;
592 }
593 }
594
595 BOOL MainFrameBase::toggle_fullscreen()
596 {
597 RECT rt;
598
599 if ((_fullscreen._mode=!_fullscreen._mode)) {
600 GetWindowRect(_hwnd, &_fullscreen._orgPos);
601 _fullscreen._wasZoomed = IsZoomed(_hwnd);
602
603 Frame_CalcFrameClient(_hwnd, &rt);
604 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
605 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
606
607 rt.left = _fullscreen._orgPos.left-rt.left;
608 rt.top = _fullscreen._orgPos.top-rt.top;
609 rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right;
610 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom;
611
612 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
613 } else {
614 MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top,
615 _fullscreen._orgPos.right-_fullscreen._orgPos.left,
616 _fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE);
617
618 if (_fullscreen._wasZoomed)
619 ShowWindow(_hwnd, WS_MAXIMIZE);
620 }
621
622 return _fullscreen._mode;
623 }
624
625 void MainFrameBase::fullscreen_move()
626 {
627 RECT rt, pos;
628 GetWindowRect(_hwnd, &pos);
629
630 Frame_CalcFrameClient(_hwnd, &rt);
631 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
632 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
633
634 rt.left = pos.left-rt.left;
635 rt.top = pos.top-rt.top;
636 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
637 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
638
639 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
640 }
641
642
643 void MainFrameBase::toggle_child(HWND hwnd, UINT cmd, HWND hchild, int band_idx)
644 {
645 BOOL vis = IsWindowVisible(hchild);
646
647 CheckMenuItem(_menu_info._hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
648
649 if (band_idx != -1)
650 SendMessage(_hwndrebar, RB_SHOWBAND, band_idx, !vis);
651 else
652 ShowWindow(hchild, vis? SW_HIDE: SW_SHOW);
653
654 if (_fullscreen._mode)
655 fullscreen_move();
656
657 resize_frame_client();
658 }
659
660 void MainFrameBase::FillBookmarks()
661 {
662 HiddenWindow hide(_hsidebar);
663 WindowCanvas canvas(_hwnd);
664
665 TreeView_DeleteAllItems(_hsidebar);
666
667 g_Globals._icon_cache.get_icon(ICID_FAVORITES).add_to_imagelist(_himl, canvas);
668 g_Globals._icon_cache.get_icon(ICID_BOOKMARK).add_to_imagelist(_himl, canvas);
669 ImageList_AddAlphaIcon(_himl, SmallIcon(IDI_DOT), GetStockBrush(WHITE_BRUSH), canvas);
670 g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
671 g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
672
673 TV_INSERTSTRUCT tvi;
674
675 tvi.hParent = TVI_ROOT;
676 tvi.hInsertAfter = TVI_LAST;
677 tvi.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
678 ResString sFavorites(IDS_FAVORITES);
679 tvi.item.pszText = sFavorites.str();
680 tvi.item.iSelectedImage = tvi.item.iImage = 0;
681
682 HTREEITEM hitem_bookmarks = TreeView_InsertItem(_hsidebar, &tvi);
683
684 g_Globals._favorites.fill_tree(_hsidebar, hitem_bookmarks, _himl, canvas);
685
686 TreeView_Expand(_hsidebar, hitem_bookmarks, TVE_EXPAND);
687 }
688
689
690 bool MainFrameBase::go_to(LPCTSTR url, bool new_window)
691 {
692 ///@todo SDI implementation
693
694 return false;
695 }
696
697
698 #ifndef _NO_MDI
699
700 MDIMainFrame::MDIMainFrame(HWND hwnd)
701 : super(hwnd)
702 {
703 TBBUTTON mdiBtns[] = {
704 {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
705 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
706 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
707 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
708 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}
709 };
710
711 SendMessage(_htoolbar, TB_ADDBUTTONS, sizeof(mdiBtns)/sizeof(TBBUTTON), (LPARAM)&mdiBtns);
712
713 CLIENTCREATESTRUCT ccs;
714
715 ccs.hWindowMenu = _hMenuWindow;
716 ccs.idFirstChild = IDW_FIRST_CHILD;
717
718 _hmdiclient = CreateWindowEx(WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, TEXT("MDICLIENT"), NULL,
719 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
720 0, 0, 0, 0,
721 hwnd, 0, g_Globals._hInstance, &ccs);
722
723 TBBUTTON extraBtns = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
724
725 #ifndef _NO_REBAR
726 _hextrabar = CreateToolbarEx(hwnd,
727 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
728 WS_CHILD|TBSTYLE_FLAT|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
729 IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
730 16, 16, 16, 16, sizeof(TBBUTTON));
731 #else
732 _hextrabar = CreateToolbarEx(hwnd,
733 WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,CCS_NODIVIDER|
734 IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &extraBtns, 1,
735 16, 13, 16, 13, sizeof(TBBUTTON));
736 #endif
737
738 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_EXTRA_BAR, MF_BYCOMMAND|MF_CHECKED);
739
740
741 extraBtns.fsStyle = BTNS_BUTTON;
742
743 #ifdef __WINE__
744 // insert unix file system button
745 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("/\0"));
746 extraBtns.idCommand = ID_DRIVE_UNIX_FS;
747 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
748 #endif
749
750 // insert explorer window button
751 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Explore\0"));
752 extraBtns.idCommand = ID_DRIVE_DESKTOP;
753 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
754
755 // insert shell namespace button
756 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Shell\0"));
757 extraBtns.idCommand = ID_DRIVE_SHELL_NS;
758 extraBtns.iBitmap = 6;
759 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
760
761 // insert web control button
762 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Web\0"));
763 extraBtns.idCommand = ID_WEB_WINDOW;
764 extraBtns.iBitmap = 7;
765 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
766
767 if ((HIWORD(GetVersion())>>14) == W_VER_NT) {
768 // insert NT object namespace button
769 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("NT Obj\0"));
770 extraBtns.idCommand = ID_DRIVE_NTOBJ_NS;
771 extraBtns.iBitmap = 8;
772 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
773 }
774 #ifndef __REACTOS__ // don't insert reg button for ROS. Regedit should be used.
775 // insert Registry button
776 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Reg.\0"));
777 extraBtns.idCommand = ID_DRIVE_REGISTRY;
778 extraBtns.iBitmap = 9;
779 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
780 #endif
781
782 #ifdef _DEBUG
783 // insert FAT direct file system access button
784 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("FAT\0"));
785 extraBtns.idCommand = ID_DRIVE_FAT;
786 extraBtns.iBitmap = 10;
787 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
788 #endif
789
790
791 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
792 #ifndef _NO_WIN_FS
793 PTSTR p;
794
795 #ifndef _NO_REBAR
796 _hdrivebar = CreateToolbarEx(hwnd,
797 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
798 WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|CCS_NOMOVEY|TBSTYLE_LIST,
799 IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
800 16, 16, 16, 16, sizeof(TBBUTTON));
801 #else
802 _hdrivebar = CreateToolbarEx(hwnd,
803 WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST|CCS_NODIVIDER,
804 IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn, 1,
805 16, 13, 16, 13, sizeof(TBBUTTON));
806 #endif
807 #endif
808
809 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_UNCHECKED);
810
811
812 #ifndef _NO_WIN_FS
813 GetLogicalDriveStrings(BUFFER_LEN, _drives);
814
815 // register windows drive root strings
816 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)_drives);
817
818 drivebarBtn.fsStyle = BTNS_BUTTON;
819 drivebarBtn.idCommand = ID_DRIVE_FIRST;
820
821 for(p=_drives; *p; ) {
822 switch(GetDriveType(p)) {
823 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
824 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
825 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
826 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
827 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
828 }
829
830 SendMessage(_hdrivebar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&drivebarBtn);
831 ++drivebarBtn.idCommand;
832 ++drivebarBtn.iString;
833
834 while(*p++);
835 }
836 #endif
837
838
839 #ifndef _NO_REBAR
840 int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0));
841
842 REBARBANDINFO rbBand;
843
844 rbBand.cbSize = sizeof(REBARBANDINFO);
845 rbBand.fMask = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
846 #ifndef RBBS_HIDETITLE // missing in MinGW headers as of 25.02.2004
847 #define RBBS_HIDETITLE 0x400
848 #endif
849 rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE;
850
851 TCHAR ExtrasBand[] = _T("Extras");
852 rbBand.lpText = ExtrasBand;
853 rbBand.hwndChild = _hextrabar;
854 rbBand.cxMinChild = 0;
855 rbBand.cyMinChild = btn_hgt;
856 rbBand.cx = 284;
857 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)1, (LPARAM)&rbBand);
858
859 #ifndef _NO_WIN_FS
860 rbBand.fStyle |= RBBS_BREAK;
861 TCHAR DrivesBand[] = _T("Drives");
862 rbBand.lpText = DrivesBand;
863 rbBand.hwndChild = _hdrivebar;
864 rbBand.cxMinChild = 0;
865 rbBand.cyMinChild = btn_hgt;
866 rbBand.cx = 400;
867 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)2, (LPARAM)&rbBand);
868
869 // hide the drivebar by default
870 SendMessage(_hwndrebar, RB_SHOWBAND, 2, FALSE);
871 #endif
872 #endif
873 }
874
875
876 HWND MDIMainFrame::Create()
877 {
878 HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_MDIFRAME));
879
880 return Window::Create(WINDOW_CREATOR(MDIMainFrame), 0,
881 (LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
882 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
883 0/*hwndDesktop*/, hMenuFrame);
884 }
885
886 HWND MDIMainFrame::Create(LPCTSTR path, int mode)
887 {
888 HWND hFrame = Create();
889 if (!hFrame)
890 return 0;
891
892 ShowWindow(hFrame, SW_SHOW);
893
894 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
895
896 if (pMainFrame)
897 pMainFrame->CreateChild(path, mode);
898
899 return hFrame;
900 }
901
902 HWND MDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
903 {
904 HWND hFrame = Create();
905 if (!hFrame)
906 return 0;
907
908 ShowWindow(hFrame, SW_SHOW);
909
910 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
911
912 if (pMainFrame)
913 pMainFrame->CreateChild(pidl, mode);
914
915 return hFrame;
916 }
917
918
919 ChildWindow* MDIMainFrame::CreateChild(LPCTSTR path, int mode)
920 {
921 return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode, (LPARAM)path));
922 }
923
924 ChildWindow* MDIMainFrame::CreateChild(LPCITEMIDLIST pidl, int mode)
925 {
926 return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode|OWM_PIDL, (LPARAM)pidl));
927 }
928
929
930 BOOL MDIMainFrame::TranslateMsg(MSG* pmsg)
931 {
932 if (_hmdiclient && TranslateMDISysAccel(_hmdiclient, pmsg))
933 return TRUE;
934
935 return super::TranslateMsg(pmsg);
936 }
937
938 LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
939 {
940 switch(nmsg) {
941 case PM_OPEN_WINDOW: {
942 CONTEXT("MDIMainFrame PM_OPEN_WINDOW");
943
944 TCHAR buffer[MAX_PATH];
945 LPCTSTR path;
946 ShellPath shell_path = DesktopFolderPath();
947
948 if (lparam) {
949 if (wparam & OWM_PIDL) {
950 // take over PIDL from lparam
951 shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
952 FileSysShellPath fsp(shell_path);
953 path = fsp;
954
955 if (path) {
956 LOG(FmtString(TEXT("MDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
957 lstrcpy(buffer, path);
958 path = buffer;
959 }
960 } else {
961 // take over path from lparam
962 path = (LPCTSTR)lparam;
963 shell_path = path; // create as "rooted" window
964 }
965 } else {
966 ///@todo read paths and window placements from registry
967 if (!GetCurrentDirectory(MAX_PATH, buffer))
968 *buffer = '\0';
969
970 path = buffer;
971 }
972
973 if (path && _tcsstr(path, TEXT("://"))) { // "http://...", "ftp://", ...
974 OBJ_CONTEXT("create WebChild window", path);
975
976 return (LRESULT)GET_WINDOW(ChildWindow, create_webchildwindow(WebChildWndInfo(_hmdiclient, path)));
977 } else {
978 OBJ_CONTEXT("create ShellChildWndInfo", path);
979
980 // Shell Namespace as default view
981 ShellChildWndInfo create_info(_hmdiclient, path, shell_path);
982
983 if (wparam & OWM_ROOTED)
984 create_info._root_shell_path = shell_path;
985 else
986 create_info._root_shell_path = DesktopFolderPath(); //SpecialFolderPath(CSIDL_DRIVES, _hwnd);
987
988 create_info._pos.showCmd = wparam&OWM_SEPARATE? SW_SHOWNORMAL: SW_SHOWMAXIMIZED;
989 create_info._pos.rcNormalPosition.left = CW_USEDEFAULT;
990 create_info._pos.rcNormalPosition.top = CW_USEDEFAULT;
991 create_info._pos.rcNormalPosition.right = CW_USEDEFAULT;
992 create_info._pos.rcNormalPosition.bottom = CW_USEDEFAULT;
993
994 create_info._open_mode = wparam;
995
996 // FileChildWindow::create(_hmdiclient, create_info);
997 return (LRESULT)MDIShellBrowserChild::create(create_info);
998 }
999 return TRUE;} // success
1000
1001 case WM_SYSCOLORCHANGE: {
1002 LRESULT res;
1003 HWND hChild;
1004
1005 /* Forward WM_SYSCOLORCHANGE to common controls */
1006 SendMessage(_hextrabar, WM_SYSCOLORCHANGE, 0, 0);
1007 SendMessage(_hdrivebar, WM_SYSCOLORCHANGE, 0, 0);
1008
1009 for(hChild = GetNextWindow(_hmdiclient,GW_CHILD); hChild; hChild = GetNextWindow(hChild, GW_HWNDNEXT))
1010 SendMessage(hChild, WM_SYSCOLORCHANGE, 0, 0);
1011
1012 super::ProcessMessage(nmsg, wparam, lparam, &res);
1013 break; }
1014
1015 default: {
1016 LRESULT res;
1017
1018 if (super::ProcessMessage(nmsg, wparam, lparam, &res))
1019 return res;
1020 else
1021 return DefFrameProc(_hwnd, _hmdiclient, nmsg, wparam, lparam);
1022 }
1023 }
1024
1025 return 0;
1026 }
1027
1028 int MDIMainFrame::Command(int id, int code)
1029 {
1030 CONTEXT("MDIMainFrame::Command()");
1031
1032 HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1033
1034 if (hwndClient)
1035 if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
1036 return 0;
1037
1038 #ifndef _NO_WIN_FS
1039 if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
1040 TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
1041 LPCTSTR root = _drives;
1042
1043 for(int i=id-ID_DRIVE_FIRST; i--; root++)
1044 while(*root)
1045 ++root;
1046
1047 if (activate_drive_window(root))
1048 return 0;
1049
1050 _tsplitpath_s(root, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
1051
1052 if (!SetCurrentDirectory(drv)) {
1053 display_error(_hwnd, GetLastError());
1054 return 0;
1055 }
1056
1057 GetCurrentDirectory(MAX_PATH, path); ///@todo store last directory per drive
1058
1059 FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1060
1061 return 1;
1062 }
1063 #endif
1064
1065 switch(id) {
1066 case ID_WINDOW_NEW: {
1067 TCHAR path[MAX_PATH];
1068
1069 GetCurrentDirectory(MAX_PATH, path);
1070
1071 FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1072 break;}
1073
1074 case ID_WINDOW_CASCADE:
1075 SendMessage(_hmdiclient, WM_MDICASCADE, 0, 0);
1076 break;
1077
1078 case ID_WINDOW_TILE_HORZ:
1079 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
1080 break;
1081
1082 case ID_WINDOW_TILE_VERT:
1083 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
1084 break;
1085
1086 case ID_WINDOW_ARRANGE:
1087 SendMessage(_hmdiclient, WM_MDIICONARRANGE, 0, 0);
1088 break;
1089
1090 case ID_VIEW_EXTRA_BAR:
1091 toggle_child(_hwnd, id, _hextrabar, 1);
1092 break;
1093
1094 #ifndef _NO_WIN_FS
1095 case ID_VIEW_DRIVE_BAR:
1096 toggle_child(_hwnd, id, _hdrivebar, 2);
1097 break;
1098 #endif
1099
1100 #ifdef __WINE__
1101 case ID_DRIVE_UNIX_FS: {
1102 TCHAR path[MAX_PATH];
1103 FileChildWindow* child;
1104
1105 getcwd(path, COUNTOF(path));
1106
1107 if (activate_child_window(TEXT("unixfs")))
1108 break;
1109
1110 FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
1111 break;}
1112 #endif
1113
1114 case ID_DRIVE_DESKTOP: {
1115 TCHAR path[MAX_PATH];
1116
1117 if (activate_child_window(TEXT("Desktop")))
1118 break;
1119
1120 GetCurrentDirectory(MAX_PATH, path);
1121
1122 MDIShellBrowserChild::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1123 break;}
1124
1125 case ID_DRIVE_SHELL_NS: {
1126 TCHAR path[MAX_PATH];
1127 GetCurrentDirectory(MAX_PATH, path);
1128
1129 if (activate_child_window(TEXT("Shell")))
1130 break;
1131
1132 FileChildWindow::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1133 break;}
1134
1135 case ID_DRIVE_NTOBJ_NS: {
1136 if (activate_child_window(TEXT("NTOBJ")))
1137 break;
1138
1139 FileChildWindow::create(NtObjChildWndInfo(_hmdiclient, TEXT("\\")));
1140 break;}
1141
1142 case ID_DRIVE_REGISTRY: {
1143 if (activate_child_window(TEXT("Registry")))
1144 break;
1145
1146 FileChildWindow::create(RegistryChildWndInfo(_hmdiclient, TEXT("\\")));
1147 break;}
1148
1149 case ID_DRIVE_FAT: {
1150
1151 ///@todo prompt for image file
1152
1153 if (activate_child_window(TEXT("FAT")))
1154 break;
1155
1156 FileChildWindow::create(FATChildWndInfo(_hmdiclient, TEXT("FAT Image"))); //@@
1157 break;}
1158
1159 case ID_WEB_WINDOW:
1160 #ifdef _DEBUG
1161 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://localhost")));
1162 #else
1163 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.reactos.org")));
1164 #endif
1165 break;
1166
1167 case ID_EXPLORER_FAQ:
1168 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.sky.franken.de/explorer/")));
1169 break;
1170
1171 case ID_VIEW_SDI:
1172 MainFrameBase::Create(ExplorerCmd());
1173 break;
1174
1175 ///@todo There are even more menu items!
1176
1177 default:
1178 if (super::Command(id, code) == 0)
1179 return 0;
1180 else
1181 return DefFrameProc(_hwnd, _hmdiclient, WM_COMMAND, MAKELONG(id,code), 0);
1182 }
1183
1184 return 0;
1185 }
1186
1187
1188 void MDIMainFrame::frame_get_clientspace(PRECT prect)
1189 {
1190 super::frame_get_clientspace(prect);
1191
1192 #ifndef _NO_WIN_FS
1193 if (IsWindowVisible(_hdrivebar)) {
1194 ClientRect rt(_hdrivebar);
1195 prect->top += rt.bottom+2;
1196 }
1197 #endif
1198 }
1199
1200 void MDIMainFrame::resize_frame(int cx, int cy)
1201 {
1202 if (cy <= 0)
1203 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1204
1205 RECT rect = {0, 0, cx, cy};
1206
1207 if (_hwndrebar) {
1208 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
1209 rect.top += height;
1210 rect.top += 5;
1211 } else {
1212 if (IsWindowVisible(_htoolbar)) {
1213 SendMessage(_htoolbar, WM_SIZE, 0, 0);
1214 WindowRect rt(_htoolbar);
1215 rect.top = rt.bottom;
1216 // rect.bottom -= rt.bottom;
1217 }
1218
1219 if (IsWindowVisible(_hextrabar)) {
1220 SendMessage(_hextrabar, WM_SIZE, 0, 0);
1221 WindowRect rt(_hextrabar);
1222 int new_top = --rect.top + rt.bottom;
1223 MoveWindow(_hextrabar, 0, rect.top, rt.right, new_top, TRUE);
1224 rect.top = new_top;
1225 // rect.bottom -= rt.bottom;
1226 }
1227
1228 #ifndef _NO_WIN_FS
1229 if (IsWindowVisible(_hdrivebar)) {
1230 SendMessage(_hdrivebar, WM_SIZE, 0, 0);
1231 WindowRect rt(_hdrivebar);
1232 int new_top = --rect.top + rt.bottom;
1233 MoveWindow(_hdrivebar, 0, rect.top, rt.right, new_top, TRUE);
1234 rect.top = new_top;
1235 // rect.bottom -= rt.bottom;
1236 }
1237 #endif
1238 }
1239
1240 if (IsWindowVisible(_hstatusbar)) {
1241 int parts[] = {300, 500};
1242
1243 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1244 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1245 ClientRect rt(_hstatusbar);
1246 rect.bottom -= rt.bottom;
1247 }
1248
1249 if (IsWindowVisible(_hsidebar)) {
1250 WindowRect rt(_hsidebar);
1251 rect.left += rt.right-rt.left;
1252
1253 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1254 }
1255
1256 MoveWindow(_hmdiclient, rect.left-1, rect.top-1, rect.right-rect.left+1, rect.bottom-rect.top+1, TRUE);
1257 }
1258
1259 bool MDIMainFrame::activate_drive_window(LPCTSTR path)
1260 {
1261 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
1262 HWND child_wnd;
1263
1264 _tsplitpath_s(path, drv1, COUNTOF(drv1), NULL, 0, NULL, 0, NULL, 0);
1265
1266 // search for a already open window for the same drive
1267 for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1268 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1269
1270 if (child) {
1271 _tsplitpath_s(child->get_root()._path, drv2, COUNTOF(drv2), NULL, 0, NULL, 0, NULL, 0);
1272
1273 if (!lstrcmpi(drv2, drv1)) {
1274 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1275
1276 if (IsMinimized(child_wnd))
1277 ShowWindow(child_wnd, SW_SHOWNORMAL);
1278
1279 return true;
1280 }
1281 }
1282 }
1283
1284 return false;
1285 }
1286
1287 bool MDIMainFrame::activate_child_window(LPCTSTR filesys)
1288 {
1289 HWND child_wnd;
1290
1291 // search for a already open window of the given file system name
1292 for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1293 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1294
1295 if (child) {
1296 if (!lstrcmpi(child->get_root()._fs, filesys)) {
1297 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1298
1299 if (IsMinimized(child_wnd))
1300 ShowWindow(child_wnd, SW_SHOWNORMAL);
1301
1302 return true;
1303 }
1304 } else {
1305 ShellBrowser* shell_child = (ShellBrowser*) SendMessage(child_wnd, PM_GET_SHELLBROWSER_PTR, 0, 0);
1306
1307 if (shell_child) {
1308 if (!lstrcmpi(shell_child->get_root()._fs, filesys)) {
1309 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1310
1311 if (IsMinimized(child_wnd))
1312 ShowWindow(child_wnd, SW_SHOWNORMAL);
1313
1314 return true;
1315 }
1316 }
1317 }
1318 }
1319
1320 return false;
1321 }
1322
1323 bool MDIMainFrame::go_to(LPCTSTR url, bool new_window)
1324 {
1325 if (!new_window) {
1326 HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1327
1328 if (hwndClient)
1329 if (SendMessage(hwndClient, PM_JUMP_TO_URL, 0, (LPARAM)url))
1330 return true;
1331 }
1332
1333 if (CreateChild(url))
1334 return true;
1335
1336 return super::go_to(url, new_window);
1337 }
1338
1339 #endif // _NO_MDI
1340
1341
1342 SDIMainFrame::SDIMainFrame(HWND hwnd)
1343 : super(hwnd)
1344 {
1345 _split_pos = DEFAULT_SPLIT_POS;
1346 _last_split = DEFAULT_SPLIT_POS;
1347
1348 /* wait for PM_OPEN_WINDOW message before creating a shell view
1349 update_shell_browser();*/
1350 }
1351
1352 HWND SDIMainFrame::Create()
1353 {
1354 HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_SDIFRAME));
1355
1356 return Window::Create(WINDOW_CREATOR(SDIMainFrame), 0,
1357 (LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW,
1358 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1359 0/*hwndDesktop*/, hMenuFrame);
1360 }
1361
1362 HWND SDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
1363 {
1364 HWND hFrame = Create();
1365 if (!hFrame)
1366 return 0;
1367
1368 ShowWindow(hFrame, SW_SHOW);
1369
1370 SDIMainFrame* pFrame = GET_WINDOW(SDIMainFrame, hFrame);
1371
1372 if (pFrame)
1373 pFrame->jump_to(pidl, mode);
1374
1375 return hFrame;
1376 }
1377
1378 HWND SDIMainFrame::Create(LPCTSTR path, int mode)
1379 {
1380 HWND hFrame = Create();
1381 if (!hFrame)
1382 return 0;
1383
1384 ShowWindow(hFrame, SW_SHOW);
1385
1386 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
1387
1388 if (pMainFrame)
1389 pMainFrame->CreateChild(path, mode);
1390
1391 return hFrame;
1392 }
1393
1394 LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1395 {
1396 switch(nmsg) {
1397 case WM_SIZE:
1398 resize_frame(LOWORD(lparam), HIWORD(lparam));
1399 break;
1400
1401 case WM_PAINT: {
1402 PaintCanvas canvas(_hwnd);
1403
1404 if (_left_hwnd) {
1405 ClientRect rt(_hwnd);
1406 rt.left = _split_pos-SPLIT_WIDTH/2;
1407 rt.right = _split_pos+SPLIT_WIDTH/2+1;
1408
1409 if (_right_hwnd) {
1410 WindowRect right_rect(_right_hwnd);
1411 ScreenToClient(_hwnd, &right_rect);
1412 rt.top = right_rect.top;
1413 rt.bottom = right_rect.bottom;
1414 }
1415
1416 HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
1417 Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
1418 SelectObject(canvas, lastBrush);
1419 }
1420 break;}
1421
1422 case WM_SETCURSOR:
1423 if (_left_hwnd)
1424 if (LOWORD(lparam) == HTCLIENT) {
1425 POINT pt;
1426 GetCursorPos(&pt);
1427 ScreenToClient(_hwnd, &pt);
1428
1429 if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
1430 SetCursor(LoadCursor(0, IDC_SIZEWE));
1431 return TRUE;
1432 }
1433 }
1434 goto def;
1435
1436 case WM_LBUTTONDOWN:
1437 if (_left_hwnd) {
1438 int x = GET_X_LPARAM(lparam);
1439
1440 ClientRect rt(_hwnd);
1441
1442 if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
1443 _last_split = _split_pos;
1444 SetCapture(_hwnd);
1445 }
1446 }
1447 break;
1448
1449 case WM_LBUTTONUP:
1450 if (GetCapture() == _hwnd)
1451 ReleaseCapture();
1452 break;
1453
1454 case WM_KEYDOWN:
1455 if (wparam == VK_ESCAPE)
1456 if (GetCapture() == _hwnd) {
1457 _split_pos = _last_split;
1458 resize_children();
1459 _last_split = -1;
1460 ReleaseCapture();
1461 SetCursor(LoadCursor(0, IDC_ARROW));
1462 }
1463 break;
1464
1465 case WM_MOUSEMOVE:
1466 if (GetCapture() == _hwnd) {
1467 int x = GET_X_LPARAM(lparam);
1468
1469 ClientRect rt(_hwnd);
1470
1471 if (x>=0 && x<rt.right) {
1472 _split_pos = x;
1473 resize_children();
1474 rt.left = x-SPLIT_WIDTH/2;
1475 rt.right = x+SPLIT_WIDTH/2+1;
1476 InvalidateRect(_hwnd, &rt, FALSE);
1477 UpdateWindow(_left_hwnd);
1478 UpdateWindow(_hwnd);
1479 UpdateWindow(_right_hwnd);
1480 }
1481 }
1482 break;
1483
1484 case PM_OPEN_WINDOW: {
1485 CONTEXT("SDIMainFrame PM_OPEN_WINDOW");
1486
1487 TCHAR buffer[MAX_PATH];
1488 LPCTSTR path;
1489 ShellPath shell_path = DesktopFolderPath();
1490
1491 if (lparam) {
1492 if (wparam & OWM_PIDL) {
1493 // take over PIDL from lparam
1494 shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
1495 FileSysShellPath fsp(shell_path);
1496 path = fsp;
1497
1498 if (path) {
1499 LOG(FmtString(TEXT("SDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
1500 lstrcpy(buffer, path);
1501 path = buffer;
1502 }
1503 } else {
1504 // take over path from lparam
1505 path = (LPCTSTR)lparam;
1506 shell_path = path; // create as "rooted" window
1507 }
1508 } else {
1509 ///@todo read paths and window placements from registry
1510 if (!GetCurrentDirectory(MAX_PATH, buffer))
1511 *buffer = '\0';
1512
1513 path = buffer;
1514 shell_path = path;
1515 }
1516
1517 if (wparam & OWM_ROOTED)
1518 _shellpath_info._root_shell_path = shell_path;
1519 else
1520 _shellpath_info._root_shell_path = DesktopFolderPath(); //SpecialFolderPath(CSIDL_DRIVES, _hwnd);
1521
1522 jump_to(shell_path, wparam); ///@todo content of 'path' not used any more
1523 return TRUE;} // success
1524
1525 default: def:
1526 return super::WndProc(nmsg, wparam, lparam);
1527 }
1528
1529 return 0;
1530 }
1531
1532 int SDIMainFrame::Command(int id, int code)
1533 {
1534 switch(id) {
1535 case ID_VIEW_MDI:
1536 MainFrameBase::Create(ExplorerCmd(_url, true));
1537 break;
1538
1539 default:
1540 return super::Command(id, code);
1541 }
1542
1543 return 0;
1544 }
1545
1546 void SDIMainFrame::resize_frame(int cx, int cy)
1547 {
1548 if (cy <= 0)
1549 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1550
1551 RECT rect = {0, 0, cx, cy};
1552
1553 if (_hwndrebar) {
1554 int height = ClientRect(_hwndrebar).bottom;
1555 rect.top += height;
1556 rect.top += 5;
1557 } else {
1558 if (IsWindowVisible(_htoolbar)) {
1559 SendMessage(_htoolbar, WM_SIZE, 0, 0);
1560 WindowRect rt(_htoolbar);
1561 rect.top = rt.bottom;
1562 // rect.bottom -= rt.bottom;
1563 }
1564 }
1565
1566 if (IsWindowVisible(_hstatusbar)) {
1567 int parts[] = {300, 500};
1568
1569 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1570 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1571 ClientRect rt(_hstatusbar);
1572 rect.bottom -= rt.bottom;
1573 }
1574
1575 if (IsWindowVisible(_hsidebar)) {
1576 WindowRect rt(_hsidebar);
1577 rect.left += rt.right-rt.left;
1578
1579 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1580 }
1581
1582 _clnt_rect = rect;
1583
1584 resize_children();
1585 }
1586
1587 void SDIMainFrame::resize_children()
1588 {
1589 HDWP hdwp = BeginDeferWindowPos(2);
1590
1591 int cx = _clnt_rect.left;
1592
1593 if (_left_hwnd) {
1594 cx = _split_pos + SPLIT_WIDTH/2;
1595
1596 hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, _clnt_rect.left, _clnt_rect.top, _split_pos-SPLIT_WIDTH/2-_clnt_rect.left, _clnt_rect.bottom-_clnt_rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
1597 } else {
1598 //_split_pos = -1;
1599 cx = 0;
1600 }
1601
1602 if (_right_hwnd)
1603 hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, _clnt_rect.left+cx+1, _clnt_rect.top, _clnt_rect.right-cx, _clnt_rect.bottom-_clnt_rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
1604
1605 EndDeferWindowPos(hdwp);
1606 }
1607
1608 void SDIMainFrame::update_clnt_rect()
1609 {
1610 ClientRect rect(_hwnd);
1611
1612 resize_frame(rect.right, rect.bottom);
1613 }
1614
1615 void SDIMainFrame::update_shell_browser()
1616 {
1617 int split_pos = DEFAULT_SPLIT_POS;
1618
1619 if (_shellBrowser.get()) {
1620 split_pos = _split_pos;
1621 delete _shellBrowser.release();
1622 }
1623
1624 // create explorer treeview
1625 if (_shellpath_info._open_mode & OWM_EXPLORE) {
1626 if (!_left_hwnd) {
1627 ClientRect rect(_hwnd);
1628
1629 _left_hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1630 WS_CHILD|WS_TABSTOP|WS_VISIBLE|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_NOTOOLTIPS|TVS_SHOWSELALWAYS,
1631 0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
1632 _hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
1633
1634 // display tree window as long as the shell view is not yet visible
1635 resize_frame(rect.right, rect.bottom);
1636 MoveWindow(_left_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
1637 }
1638 } else {
1639 if (_left_hwnd) {
1640 DestroyWindow(_left_hwnd);
1641 _left_hwnd = 0;
1642 }
1643 }
1644
1645 _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _hwnd, _left_hwnd, _right_hwnd,
1646 _shellpath_info, this, _cm_ifs));
1647
1648 if (_left_hwnd)
1649 _shellBrowser->Init();
1650
1651 // update _clnt_rect and set size of new created shell view windows
1652 update_clnt_rect();
1653 }
1654
1655 void SDIMainFrame::entry_selected(Entry* entry)
1656 {
1657 if (_left_hwnd)
1658 _shellBrowser->select_folder(entry, false);
1659
1660 _shellBrowser->UpdateFolderView(entry->get_shell_folder());
1661
1662 // set size of new created shell view windows
1663 resize_children();
1664 }
1665
1666 void SDIMainFrame::set_url(LPCTSTR url)
1667 {
1668 if (_url != url) {
1669 _url = url;
1670 SetWindowText(_haddrcombo, url);
1671 }
1672 }
1673
1674
1675 void SDIMainFrame::jump_to(LPCTSTR path, int mode)
1676 {/*@@todo
1677 if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1678 _shellBrowser->jump_to(path);
1679
1680 _shellpath_info._shell_path = path;
1681 } else */{
1682 _shellpath_info._open_mode = mode;
1683 _shellpath_info._shell_path = path;
1684
1685 update_shell_browser();
1686 }
1687 }
1688
1689 void SDIMainFrame::jump_to(LPCITEMIDLIST path, int mode)
1690 {
1691 if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1692 ShellPath shell_path = path;
1693
1694 _shellBrowser->jump_to(shell_path);
1695
1696 _shellpath_info._shell_path = shell_path;
1697 } else {
1698 _shellpath_info._open_mode = mode;
1699 _shellpath_info._shell_path = path;
1700
1701 update_shell_browser();
1702 }
1703 }