[CMAKE]
[reactos.git] / 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 default:
376 return false;
377 }
378
379 *pres = 0;
380 return true;
381 }
382
383 BOOL MainFrameBase::TranslateMsg(MSG* pmsg)
384 {
385 if (TranslateAccelerator(_hwnd, _hAccel, pmsg))
386 return TRUE;
387
388 return FALSE;
389 }
390
391
392 int MainFrameBase::Command(int id, int code)
393 {
394 CONTEXT("MainFrameBase::Command()");
395
396 switch(id) {
397 case ID_FILE_EXIT:
398 SendMessage(_hwnd, WM_CLOSE, 0, 0);
399 break;
400
401 case ID_VIEW_TOOL_BAR:
402 toggle_child(_hwnd, id, _htoolbar, 0);
403 break;
404
405 case ID_VIEW_STATUSBAR:
406 toggle_child(_hwnd, id, _hstatusbar);
407 break;
408
409 case ID_VIEW_SIDE_BAR:
410 // lazy initialization
411 if (!TreeView_GetCount(_hsidebar))
412 FillBookmarks();
413
414 toggle_child(_hwnd, id, _hsidebar);
415 break;
416
417 case ID_EXECUTE: {
418 ExecuteDialog dlg = {{0}, 0};
419
420 if (DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(IDD_EXECUTE), _hwnd, ExecuteDialog::WndProc, (LPARAM)&dlg) == IDOK) {
421 CONTEXT("ID_EXECUTE - ShellExecute()");
422
423 HINSTANCE hinst = ShellExecute(_hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
424
425 if ((int)hinst <= 32)
426 display_error(_hwnd, GetLastError());
427 }
428 break;}
429
430 case ID_HELP:
431 WinHelp(_hwnd, TEXT("explorer")/*file explorer.hlp*/, HELP_INDEX, 0);
432 break;
433
434 case ID_VIEW_FULLSCREEN:
435 CheckMenuItem(_menu_info._hMenuView, id, toggle_fullscreen()?MF_CHECKED:0);
436 break;
437
438 case ID_TOOLS_OPTIONS:
439 Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), _hwnd);
440 break;
441
442 case ID_ABOUT_WINDOWS:
443 ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0);
444 break;
445
446 case ID_ABOUT_EXPLORER:
447 explorer_about(_hwnd);
448 break;
449
450 case ID_EXPLORER_FAQ:
451 launch_file(_hwnd, TEXT("http://www.sky.franken.de/explorer/"), SW_SHOW);
452 break;
453
454 default:
455 return 1; // no command handlers in Window::Command()
456 }
457
458 return 0;
459 }
460
461 int MainFrameBase::Notify(int id, NMHDR* pnmh)
462 {
463 switch(pnmh->code) {
464 // resize children windows when the rebar size changes
465
466 case RBN_AUTOSIZE:
467 resize_frame_client();
468 break;
469
470 case TVN_GETINFOTIP: {
471 NMTVGETINFOTIP* pnmgit = (NMTVGETINFOTIP*)pnmh;
472
473 if (pnmgit->lParam) {
474 const BookmarkNode& node = *(BookmarkNode*)pnmgit->lParam;
475
476 if (node._type == BookmarkNode::BMNT_FOLDER) {
477 // display tooltips for bookmark folders
478 if (!node._pfolder->_description.empty())
479 lstrcpyn(pnmgit->pszText, node._pfolder->_description.c_str(), pnmgit->cchTextMax);
480 } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
481 // display tooltips for bookmark folders
482 String txt = node._pbookmark->_description;
483
484 if (!node._pbookmark->_url.empty()) {
485 if (!txt.empty())
486 txt += TEXT(" - ");
487
488 txt += node._pbookmark->_url;
489 }
490
491 lstrcpyn(pnmgit->pszText, txt.c_str(), pnmgit->cchTextMax);
492 }
493 }
494 break;}
495
496 case NM_DBLCLK: {
497 HTREEITEM hitem = TreeView_GetSelection(_hsidebar);
498 LPARAM lparam = TreeView_GetItemData(_hsidebar, hitem);
499
500 if (lparam) {
501 const BookmarkNode& node = *(BookmarkNode*)lparam;
502
503 if (node._type == BookmarkNode::BMNT_BOOKMARK) {
504 bool new_window = GetAsyncKeyState(VK_SHIFT)<0;
505
506 go_to(node._pbookmark->_url, new_window);
507 }
508 }
509 break;}
510 }
511
512 return 0;
513 }
514
515
516 void MainFrameBase::resize_frame(int cx, int cy)
517 {
518 if (cy <= 0)
519 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
520
521 RECT rect = {0, 0, cx, cy};
522
523 if (_hwndrebar) {
524 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
525 rect.top += height;
526 rect.top += 5;
527
528 SetWindowPos(_haddrcombo, NULL, 0, 0, cx, height, SWP_NOMOVE);
529 } else {
530 if (IsWindowVisible(_htoolbar)) {
531 SendMessage(_htoolbar, WM_SIZE, 0, 0);
532 WindowRect rt(_htoolbar);
533 rect.top = rt.bottom;
534 // rect.bottom -= rt.bottom;
535 }
536 }
537
538 if (IsWindowVisible(_hstatusbar)) {
539 int parts[] = {300, 500};
540
541 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
542 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
543 ClientRect rt(_hstatusbar);
544 rect.bottom -= rt.bottom;
545 }
546
547 if (IsWindowVisible(_hsidebar)) {
548 WindowRect rt(_hsidebar);
549 rect.left += rt.right-rt.left;
550
551 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
552 }
553 }
554
555 void MainFrameBase::resize_frame_client()
556 {
557 ClientRect rect(_hwnd);
558
559 resize_frame(rect.right, rect.bottom);
560 }
561
562 void MainFrameBase::frame_get_clientspace(PRECT prect)
563 {
564 if (!IsIconic(_hwnd))
565 GetClientRect(_hwnd, prect);
566 else {
567 WINDOWPLACEMENT wp;
568
569 GetWindowPlacement(_hwnd, &wp);
570
571 prect->left = prect->top = 0;
572 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
573 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
574 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
575 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
576 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
577 }
578
579 if (IsWindowVisible(_htoolbar)) {
580 ClientRect rt(_htoolbar);
581 prect->top += rt.bottom+2;
582 }
583
584 if (IsWindowVisible(_hstatusbar)) {
585 ClientRect rt(_hstatusbar);
586 prect->bottom -= rt.bottom;
587 }
588 }
589
590 BOOL MainFrameBase::toggle_fullscreen()
591 {
592 RECT rt;
593
594 if ((_fullscreen._mode=!_fullscreen._mode)) {
595 GetWindowRect(_hwnd, &_fullscreen._orgPos);
596 _fullscreen._wasZoomed = IsZoomed(_hwnd);
597
598 Frame_CalcFrameClient(_hwnd, &rt);
599 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
600 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
601
602 rt.left = _fullscreen._orgPos.left-rt.left;
603 rt.top = _fullscreen._orgPos.top-rt.top;
604 rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right;
605 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom;
606
607 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
608 } else {
609 MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top,
610 _fullscreen._orgPos.right-_fullscreen._orgPos.left,
611 _fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE);
612
613 if (_fullscreen._wasZoomed)
614 ShowWindow(_hwnd, WS_MAXIMIZE);
615 }
616
617 return _fullscreen._mode;
618 }
619
620 void MainFrameBase::fullscreen_move()
621 {
622 RECT rt, pos;
623 GetWindowRect(_hwnd, &pos);
624
625 Frame_CalcFrameClient(_hwnd, &rt);
626 ClientToScreen(_hwnd, (LPPOINT)&rt.left);
627 ClientToScreen(_hwnd, (LPPOINT)&rt.right);
628
629 rt.left = pos.left-rt.left;
630 rt.top = pos.top-rt.top;
631 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
632 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
633
634 MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
635 }
636
637
638 void MainFrameBase::toggle_child(HWND hwnd, UINT cmd, HWND hchild, int band_idx)
639 {
640 BOOL vis = IsWindowVisible(hchild);
641
642 CheckMenuItem(_menu_info._hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
643
644 if (band_idx != -1)
645 SendMessage(_hwndrebar, RB_SHOWBAND, band_idx, !vis);
646 else
647 ShowWindow(hchild, vis? SW_HIDE: SW_SHOW);
648
649 if (_fullscreen._mode)
650 fullscreen_move();
651
652 resize_frame_client();
653 }
654
655 void MainFrameBase::FillBookmarks()
656 {
657 HiddenWindow hide(_hsidebar);
658 WindowCanvas canvas(_hwnd);
659
660 TreeView_DeleteAllItems(_hsidebar);
661
662 g_Globals._icon_cache.get_icon(ICID_FAVORITES).add_to_imagelist(_himl, canvas);
663 g_Globals._icon_cache.get_icon(ICID_BOOKMARK).add_to_imagelist(_himl, canvas);
664 ImageList_AddAlphaIcon(_himl, SmallIcon(IDI_DOT), GetStockBrush(WHITE_BRUSH), canvas);
665 g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
666 g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
667
668 TV_INSERTSTRUCT tvi;
669
670 tvi.hParent = TVI_ROOT;
671 tvi.hInsertAfter = TVI_LAST;
672 tvi.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
673 ResString sFavorites(IDS_FAVORITES);
674 tvi.item.pszText = sFavorites.str();
675 tvi.item.iSelectedImage = tvi.item.iImage = 0;
676
677 HTREEITEM hitem_bookmarks = TreeView_InsertItem(_hsidebar, &tvi);
678
679 g_Globals._favorites.fill_tree(_hsidebar, hitem_bookmarks, _himl, canvas);
680
681 TreeView_Expand(_hsidebar, hitem_bookmarks, TVE_EXPAND);
682 }
683
684
685 bool MainFrameBase::go_to(LPCTSTR url, bool new_window)
686 {
687 ///@todo SDI implementation
688
689 return false;
690 }
691
692
693 #ifndef _NO_MDI
694
695 MDIMainFrame::MDIMainFrame(HWND hwnd)
696 : super(hwnd)
697 {
698 TBBUTTON mdiBtns[] = {
699 {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
700 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
701 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
702 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
703 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}
704 };
705
706 SendMessage(_htoolbar, TB_ADDBUTTONS, sizeof(mdiBtns)/sizeof(TBBUTTON), (LPARAM)&mdiBtns);
707
708 CLIENTCREATESTRUCT ccs;
709
710 ccs.hWindowMenu = _hMenuWindow;
711 ccs.idFirstChild = IDW_FIRST_CHILD;
712
713 _hmdiclient = CreateWindowEx(WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, TEXT("MDICLIENT"), NULL,
714 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
715 0, 0, 0, 0,
716 hwnd, 0, g_Globals._hInstance, &ccs);
717
718 TBBUTTON extraBtns = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
719
720 #ifndef _NO_REBAR
721 _hextrabar = CreateToolbarEx(hwnd,
722 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
723 WS_CHILD|TBSTYLE_FLAT|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
724 IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
725 16, 16, 16, 16, sizeof(TBBUTTON));
726 #else
727 _hextrabar = CreateToolbarEx(hwnd,
728 WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,CCS_NODIVIDER|
729 IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &extraBtns, 1,
730 16, 13, 16, 13, sizeof(TBBUTTON));
731 #endif
732
733 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_EXTRA_BAR, MF_BYCOMMAND|MF_CHECKED);
734
735
736 extraBtns.fsStyle = BTNS_BUTTON;
737
738 #ifdef __WINE__
739 // insert unix file system button
740 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("/\0"));
741 extraBtns.idCommand = ID_DRIVE_UNIX_FS;
742 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
743 #endif
744
745 // insert explorer window button
746 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Explore\0"));
747 extraBtns.idCommand = ID_DRIVE_DESKTOP;
748 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
749
750 // insert shell namespace button
751 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Shell\0"));
752 extraBtns.idCommand = ID_DRIVE_SHELL_NS;
753 extraBtns.iBitmap = 6;
754 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
755
756 // insert web control button
757 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Web\0"));
758 extraBtns.idCommand = ID_WEB_WINDOW;
759 extraBtns.iBitmap = 7;
760 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
761
762 if ((HIWORD(GetVersion())>>14) == W_VER_NT) {
763 // insert NT object namespace button
764 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("NT Obj\0"));
765 extraBtns.idCommand = ID_DRIVE_NTOBJ_NS;
766 extraBtns.iBitmap = 8;
767 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
768 }
769 #ifndef __REACTOS__ // don't insert reg button for ROS. Regedit should be used.
770 // insert Registry button
771 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Reg.\0"));
772 extraBtns.idCommand = ID_DRIVE_REGISTRY;
773 extraBtns.iBitmap = 9;
774 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
775 #endif
776
777 #ifdef _DEBUG
778 // insert FAT direct file system access button
779 extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("FAT\0"));
780 extraBtns.idCommand = ID_DRIVE_FAT;
781 extraBtns.iBitmap = 10;
782 SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
783 #endif
784
785
786 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
787 #ifndef _NO_WIN_FS
788 PTSTR p;
789
790 #ifndef _NO_REBAR
791 _hdrivebar = CreateToolbarEx(hwnd,
792 CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
793 WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|CCS_NOMOVEY|TBSTYLE_LIST,
794 IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
795 16, 16, 16, 16, sizeof(TBBUTTON));
796 #else
797 _hdrivebar = CreateToolbarEx(hwnd,
798 WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST|CCS_NODIVIDER,
799 IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn, 1,
800 16, 13, 16, 13, sizeof(TBBUTTON));
801 #endif
802 #endif
803
804 CheckMenuItem(_menu_info._hMenuView, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_UNCHECKED);
805
806
807 #ifndef _NO_WIN_FS
808 GetLogicalDriveStrings(BUFFER_LEN, _drives);
809
810 // register windows drive root strings
811 SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)_drives);
812
813 drivebarBtn.fsStyle = BTNS_BUTTON;
814 drivebarBtn.idCommand = ID_DRIVE_FIRST;
815
816 for(p=_drives; *p; ) {
817 switch(GetDriveType(p)) {
818 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
819 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
820 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
821 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
822 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
823 }
824
825 SendMessage(_hdrivebar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&drivebarBtn);
826 ++drivebarBtn.idCommand;
827 ++drivebarBtn.iString;
828
829 while(*p++);
830 }
831 #endif
832
833
834 #ifndef _NO_REBAR
835 int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0));
836
837 REBARBANDINFO rbBand;
838
839 rbBand.cbSize = sizeof(REBARBANDINFO);
840 rbBand.fMask = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
841 #ifndef RBBS_HIDETITLE // missing in MinGW headers as of 25.02.2004
842 #define RBBS_HIDETITLE 0x400
843 #endif
844 rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE;
845
846 TCHAR ExtrasBand[] = _T("Extras");
847 rbBand.lpText = ExtrasBand;
848 rbBand.hwndChild = _hextrabar;
849 rbBand.cxMinChild = 0;
850 rbBand.cyMinChild = btn_hgt;
851 rbBand.cx = 284;
852 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)1, (LPARAM)&rbBand);
853
854 #ifndef _NO_WIN_FS
855 rbBand.fStyle |= RBBS_BREAK;
856 TCHAR DrivesBand[] = _T("Drives");
857 rbBand.lpText = DrivesBand;
858 rbBand.hwndChild = _hdrivebar;
859 rbBand.cxMinChild = 0;
860 rbBand.cyMinChild = btn_hgt;
861 rbBand.cx = 400;
862 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)2, (LPARAM)&rbBand);
863
864 // hide the drivebar by default
865 SendMessage(_hwndrebar, RB_SHOWBAND, 2, FALSE);
866 #endif
867 #endif
868 }
869
870
871 HWND MDIMainFrame::Create()
872 {
873 HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_MDIFRAME));
874
875 return Window::Create(WINDOW_CREATOR(MDIMainFrame), 0,
876 (LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW,
877 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
878 0/*hwndDesktop*/, hMenuFrame);
879 }
880
881 HWND MDIMainFrame::Create(LPCTSTR path, int mode)
882 {
883 HWND hFrame = Create();
884 if (!hFrame)
885 return 0;
886
887 ShowWindow(hFrame, SW_SHOW);
888
889 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
890
891 if (pMainFrame)
892 pMainFrame->CreateChild(path, mode);
893
894 return hFrame;
895 }
896
897 HWND MDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
898 {
899 HWND hFrame = Create();
900 if (!hFrame)
901 return 0;
902
903 ShowWindow(hFrame, SW_SHOW);
904
905 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
906
907 if (pMainFrame)
908 pMainFrame->CreateChild(pidl, mode);
909
910 return hFrame;
911 }
912
913
914 ChildWindow* MDIMainFrame::CreateChild(LPCTSTR path, int mode)
915 {
916 return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode, (LPARAM)path));
917 }
918
919 ChildWindow* MDIMainFrame::CreateChild(LPCITEMIDLIST pidl, int mode)
920 {
921 return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode|OWM_PIDL, (LPARAM)pidl));
922 }
923
924
925 BOOL MDIMainFrame::TranslateMsg(MSG* pmsg)
926 {
927 if (_hmdiclient && TranslateMDISysAccel(_hmdiclient, pmsg))
928 return TRUE;
929
930 return super::TranslateMsg(pmsg);
931 }
932
933 LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
934 {
935 switch(nmsg) {
936 case PM_OPEN_WINDOW: {
937 CONTEXT("MDIMainFrame PM_OPEN_WINDOW");
938
939 TCHAR buffer[MAX_PATH];
940 LPCTSTR path;
941 ShellPath shell_path = DesktopFolderPath();
942
943 if (lparam) {
944 if (wparam & OWM_PIDL) {
945 // take over PIDL from lparam
946 shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
947 FileSysShellPath fsp(shell_path);
948 path = fsp;
949
950 if (path) {
951 LOG(FmtString(TEXT("MDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
952 lstrcpy(buffer, path);
953 path = buffer;
954 }
955 } else {
956 // take over path from lparam
957 path = (LPCTSTR)lparam;
958 shell_path = path; // create as "rooted" window
959 }
960 } else {
961 ///@todo read paths and window placements from registry
962 if (!GetCurrentDirectory(MAX_PATH, buffer))
963 *buffer = '\0';
964
965 path = buffer;
966 }
967
968 if (path && _tcsstr(path, TEXT("://"))) { // "http://...", "ftp://", ...
969 OBJ_CONTEXT("create WebChild window", path);
970
971 return (LRESULT)GET_WINDOW(ChildWindow, create_webchildwindow(WebChildWndInfo(_hmdiclient, path)));
972 } else {
973 OBJ_CONTEXT("create ShellChildWndInfo", path);
974
975 // Shell Namespace as default view
976 ShellChildWndInfo create_info(_hmdiclient, path, shell_path);
977
978 if (wparam & OWM_ROOTED)
979 create_info._root_shell_path = shell_path;
980 else
981 create_info._root_shell_path = DesktopFolderPath(); //SpecialFolderPath(CSIDL_DRIVES, _hwnd);
982
983 create_info._pos.showCmd = wparam&OWM_SEPARATE? SW_SHOWNORMAL: SW_SHOWMAXIMIZED;
984 create_info._pos.rcNormalPosition.left = CW_USEDEFAULT;
985 create_info._pos.rcNormalPosition.top = CW_USEDEFAULT;
986 create_info._pos.rcNormalPosition.right = CW_USEDEFAULT;
987 create_info._pos.rcNormalPosition.bottom = CW_USEDEFAULT;
988
989 create_info._open_mode = wparam;
990
991 // FileChildWindow::create(_hmdiclient, create_info);
992 return (LRESULT)MDIShellBrowserChild::create(create_info);
993 }
994 return TRUE;} // success
995
996 default: {
997 LRESULT res;
998
999 if (super::ProcessMessage(nmsg, wparam, lparam, &res))
1000 return res;
1001 else
1002 return DefFrameProc(_hwnd, _hmdiclient, nmsg, wparam, lparam);
1003 }
1004 }
1005
1006 return 0;
1007 }
1008
1009 int MDIMainFrame::Command(int id, int code)
1010 {
1011 CONTEXT("MDIMainFrame::Command()");
1012
1013 HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1014
1015 if (hwndClient)
1016 if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
1017 return 0;
1018
1019 #ifndef _NO_WIN_FS
1020 if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
1021 TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
1022 LPCTSTR root = _drives;
1023
1024 for(int i=id-ID_DRIVE_FIRST; i--; root++)
1025 while(*root)
1026 ++root;
1027
1028 if (activate_drive_window(root))
1029 return 0;
1030
1031 _tsplitpath_s(root, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
1032
1033 if (!SetCurrentDirectory(drv)) {
1034 display_error(_hwnd, GetLastError());
1035 return 0;
1036 }
1037
1038 GetCurrentDirectory(MAX_PATH, path); ///@todo store last directory per drive
1039
1040 FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1041
1042 return 1;
1043 }
1044 #endif
1045
1046 switch(id) {
1047 case ID_WINDOW_NEW: {
1048 TCHAR path[MAX_PATH];
1049
1050 GetCurrentDirectory(MAX_PATH, path);
1051
1052 FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1053 break;}
1054
1055 case ID_WINDOW_CASCADE:
1056 SendMessage(_hmdiclient, WM_MDICASCADE, 0, 0);
1057 break;
1058
1059 case ID_WINDOW_TILE_HORZ:
1060 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
1061 break;
1062
1063 case ID_WINDOW_TILE_VERT:
1064 SendMessage(_hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
1065 break;
1066
1067 case ID_WINDOW_ARRANGE:
1068 SendMessage(_hmdiclient, WM_MDIICONARRANGE, 0, 0);
1069 break;
1070
1071 case ID_VIEW_EXTRA_BAR:
1072 toggle_child(_hwnd, id, _hextrabar, 1);
1073 break;
1074
1075 #ifndef _NO_WIN_FS
1076 case ID_VIEW_DRIVE_BAR:
1077 toggle_child(_hwnd, id, _hdrivebar, 2);
1078 break;
1079 #endif
1080
1081 #ifdef __WINE__
1082 case ID_DRIVE_UNIX_FS: {
1083 TCHAR path[MAX_PATH];
1084 FileChildWindow* child;
1085
1086 getcwd(path, COUNTOF(path));
1087
1088 if (activate_child_window(TEXT("unixfs")))
1089 break;
1090
1091 FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
1092 break;}
1093 #endif
1094
1095 case ID_DRIVE_DESKTOP: {
1096 TCHAR path[MAX_PATH];
1097
1098 if (activate_child_window(TEXT("Desktop")))
1099 break;
1100
1101 GetCurrentDirectory(MAX_PATH, path);
1102
1103 MDIShellBrowserChild::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1104 break;}
1105
1106 case ID_DRIVE_SHELL_NS: {
1107 TCHAR path[MAX_PATH];
1108 GetCurrentDirectory(MAX_PATH, path);
1109
1110 if (activate_child_window(TEXT("Shell")))
1111 break;
1112
1113 FileChildWindow::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1114 break;}
1115
1116 case ID_DRIVE_NTOBJ_NS: {
1117 if (activate_child_window(TEXT("NTOBJ")))
1118 break;
1119
1120 FileChildWindow::create(NtObjChildWndInfo(_hmdiclient, TEXT("\\")));
1121 break;}
1122
1123 case ID_DRIVE_REGISTRY: {
1124 if (activate_child_window(TEXT("Registry")))
1125 break;
1126
1127 FileChildWindow::create(RegistryChildWndInfo(_hmdiclient, TEXT("\\")));
1128 break;}
1129
1130 case ID_DRIVE_FAT: {
1131
1132 ///@todo prompt for image file
1133
1134 if (activate_child_window(TEXT("FAT")))
1135 break;
1136
1137 FileChildWindow::create(FATChildWndInfo(_hmdiclient, TEXT("FAT Image"))); //@@
1138 break;}
1139
1140 case ID_WEB_WINDOW:
1141 #ifdef _DEBUG
1142 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://localhost")));
1143 #else
1144 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.reactos.org")));
1145 #endif
1146 break;
1147
1148 case ID_EXPLORER_FAQ:
1149 create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.sky.franken.de/explorer/")));
1150 break;
1151
1152 case ID_VIEW_SDI:
1153 MainFrameBase::Create(ExplorerCmd());
1154 break;
1155
1156 ///@todo There are even more menu items!
1157
1158 default:
1159 if (super::Command(id, code) == 0)
1160 return 0;
1161 else
1162 return DefFrameProc(_hwnd, _hmdiclient, WM_COMMAND, MAKELONG(id,code), 0);
1163 }
1164
1165 return 0;
1166 }
1167
1168
1169 void MDIMainFrame::frame_get_clientspace(PRECT prect)
1170 {
1171 super::frame_get_clientspace(prect);
1172
1173 #ifndef _NO_WIN_FS
1174 if (IsWindowVisible(_hdrivebar)) {
1175 ClientRect rt(_hdrivebar);
1176 prect->top += rt.bottom+2;
1177 }
1178 #endif
1179 }
1180
1181 void MDIMainFrame::resize_frame(int cx, int cy)
1182 {
1183 if (cy <= 0)
1184 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1185
1186 RECT rect = {0, 0, cx, cy};
1187
1188 if (_hwndrebar) {
1189 int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
1190 rect.top += height;
1191 rect.top += 5;
1192 } else {
1193 if (IsWindowVisible(_htoolbar)) {
1194 SendMessage(_htoolbar, WM_SIZE, 0, 0);
1195 WindowRect rt(_htoolbar);
1196 rect.top = rt.bottom;
1197 // rect.bottom -= rt.bottom;
1198 }
1199
1200 if (IsWindowVisible(_hextrabar)) {
1201 SendMessage(_hextrabar, WM_SIZE, 0, 0);
1202 WindowRect rt(_hextrabar);
1203 int new_top = --rect.top + rt.bottom;
1204 MoveWindow(_hextrabar, 0, rect.top, rt.right, new_top, TRUE);
1205 rect.top = new_top;
1206 // rect.bottom -= rt.bottom;
1207 }
1208
1209 #ifndef _NO_WIN_FS
1210 if (IsWindowVisible(_hdrivebar)) {
1211 SendMessage(_hdrivebar, WM_SIZE, 0, 0);
1212 WindowRect rt(_hdrivebar);
1213 int new_top = --rect.top + rt.bottom;
1214 MoveWindow(_hdrivebar, 0, rect.top, rt.right, new_top, TRUE);
1215 rect.top = new_top;
1216 // rect.bottom -= rt.bottom;
1217 }
1218 #endif
1219 }
1220
1221 if (IsWindowVisible(_hstatusbar)) {
1222 int parts[] = {300, 500};
1223
1224 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1225 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1226 ClientRect rt(_hstatusbar);
1227 rect.bottom -= rt.bottom;
1228 }
1229
1230 if (IsWindowVisible(_hsidebar)) {
1231 WindowRect rt(_hsidebar);
1232 rect.left += rt.right-rt.left;
1233
1234 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1235 }
1236
1237 MoveWindow(_hmdiclient, rect.left-1, rect.top-1, rect.right-rect.left+1, rect.bottom-rect.top+1, TRUE);
1238 }
1239
1240 bool MDIMainFrame::activate_drive_window(LPCTSTR path)
1241 {
1242 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
1243 HWND child_wnd;
1244
1245 _tsplitpath_s(path, drv1, COUNTOF(drv1), NULL, 0, NULL, 0, NULL, 0);
1246
1247 // search for a already open window for the same drive
1248 for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1249 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1250
1251 if (child) {
1252 _tsplitpath_s(child->get_root()._path, drv2, COUNTOF(drv2), NULL, 0, NULL, 0, NULL, 0);
1253
1254 if (!lstrcmpi(drv2, drv1)) {
1255 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1256
1257 if (IsMinimized(child_wnd))
1258 ShowWindow(child_wnd, SW_SHOWNORMAL);
1259
1260 return true;
1261 }
1262 }
1263 }
1264
1265 return false;
1266 }
1267
1268 bool MDIMainFrame::activate_child_window(LPCTSTR filesys)
1269 {
1270 HWND child_wnd;
1271
1272 // search for a already open window of the given file system name
1273 for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1274 FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1275
1276 if (child) {
1277 if (!lstrcmpi(child->get_root()._fs, filesys)) {
1278 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1279
1280 if (IsMinimized(child_wnd))
1281 ShowWindow(child_wnd, SW_SHOWNORMAL);
1282
1283 return true;
1284 }
1285 } else {
1286 ShellBrowser* shell_child = (ShellBrowser*) SendMessage(child_wnd, PM_GET_SHELLBROWSER_PTR, 0, 0);
1287
1288 if (shell_child) {
1289 if (!lstrcmpi(shell_child->get_root()._fs, filesys)) {
1290 SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1291
1292 if (IsMinimized(child_wnd))
1293 ShowWindow(child_wnd, SW_SHOWNORMAL);
1294
1295 return true;
1296 }
1297 }
1298 }
1299 }
1300
1301 return false;
1302 }
1303
1304 bool MDIMainFrame::go_to(LPCTSTR url, bool new_window)
1305 {
1306 if (!new_window) {
1307 HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1308
1309 if (hwndClient)
1310 if (SendMessage(hwndClient, PM_JUMP_TO_URL, 0, (LPARAM)url))
1311 return true;
1312 }
1313
1314 if (CreateChild(url))
1315 return true;
1316
1317 return super::go_to(url, new_window);
1318 }
1319
1320 #endif // _NO_MDI
1321
1322
1323 SDIMainFrame::SDIMainFrame(HWND hwnd)
1324 : super(hwnd)
1325 {
1326 _split_pos = DEFAULT_SPLIT_POS;
1327 _last_split = DEFAULT_SPLIT_POS;
1328
1329 /* wait for PM_OPEN_WINDOW message before creating a shell view
1330 update_shell_browser();*/
1331 }
1332
1333 HWND SDIMainFrame::Create()
1334 {
1335 HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_SDIFRAME));
1336
1337 return Window::Create(WINDOW_CREATOR(SDIMainFrame), 0,
1338 (LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW,
1339 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1340 0/*hwndDesktop*/, hMenuFrame);
1341 }
1342
1343 HWND SDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
1344 {
1345 HWND hFrame = Create();
1346 if (!hFrame)
1347 return 0;
1348
1349 ShowWindow(hFrame, SW_SHOW);
1350
1351 SDIMainFrame* pFrame = GET_WINDOW(SDIMainFrame, hFrame);
1352
1353 if (pFrame)
1354 pFrame->jump_to(pidl, mode);
1355
1356 return hFrame;
1357 }
1358
1359 HWND SDIMainFrame::Create(LPCTSTR path, int mode)
1360 {
1361 HWND hFrame = Create();
1362 if (!hFrame)
1363 return 0;
1364
1365 ShowWindow(hFrame, SW_SHOW);
1366
1367 MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
1368
1369 if (pMainFrame)
1370 pMainFrame->CreateChild(path, mode);
1371
1372 return hFrame;
1373 }
1374
1375 LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1376 {
1377 switch(nmsg) {
1378 case WM_SIZE:
1379 resize_frame(LOWORD(lparam), HIWORD(lparam));
1380 break;
1381
1382 case WM_PAINT: {
1383 PaintCanvas canvas(_hwnd);
1384
1385 if (_left_hwnd) {
1386 ClientRect rt(_hwnd);
1387 rt.left = _split_pos-SPLIT_WIDTH/2;
1388 rt.right = _split_pos+SPLIT_WIDTH/2+1;
1389
1390 if (_right_hwnd) {
1391 WindowRect right_rect(_right_hwnd);
1392 ScreenToClient(_hwnd, &right_rect);
1393 rt.top = right_rect.top;
1394 rt.bottom = right_rect.bottom;
1395 }
1396
1397 HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
1398 Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
1399 SelectObject(canvas, lastBrush);
1400 }
1401 break;}
1402
1403 case WM_SETCURSOR:
1404 if (_left_hwnd)
1405 if (LOWORD(lparam) == HTCLIENT) {
1406 POINT pt;
1407 GetCursorPos(&pt);
1408 ScreenToClient(_hwnd, &pt);
1409
1410 if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
1411 SetCursor(LoadCursor(0, IDC_SIZEWE));
1412 return TRUE;
1413 }
1414 }
1415 goto def;
1416
1417 case WM_LBUTTONDOWN:
1418 if (_left_hwnd) {
1419 int x = GET_X_LPARAM(lparam);
1420
1421 ClientRect rt(_hwnd);
1422
1423 if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
1424 _last_split = _split_pos;
1425 SetCapture(_hwnd);
1426 }
1427 }
1428 break;
1429
1430 case WM_LBUTTONUP:
1431 if (GetCapture() == _hwnd)
1432 ReleaseCapture();
1433 break;
1434
1435 case WM_KEYDOWN:
1436 if (wparam == VK_ESCAPE)
1437 if (GetCapture() == _hwnd) {
1438 _split_pos = _last_split;
1439 resize_children();
1440 _last_split = -1;
1441 ReleaseCapture();
1442 SetCursor(LoadCursor(0, IDC_ARROW));
1443 }
1444 break;
1445
1446 case WM_MOUSEMOVE:
1447 if (GetCapture() == _hwnd) {
1448 int x = GET_X_LPARAM(lparam);
1449
1450 ClientRect rt(_hwnd);
1451
1452 if (x>=0 && x<rt.right) {
1453 _split_pos = x;
1454 resize_children();
1455 rt.left = x-SPLIT_WIDTH/2;
1456 rt.right = x+SPLIT_WIDTH/2+1;
1457 InvalidateRect(_hwnd, &rt, FALSE);
1458 UpdateWindow(_left_hwnd);
1459 UpdateWindow(_hwnd);
1460 UpdateWindow(_right_hwnd);
1461 }
1462 }
1463 break;
1464
1465 case PM_OPEN_WINDOW: {
1466 CONTEXT("SDIMainFrame PM_OPEN_WINDOW");
1467
1468 TCHAR buffer[MAX_PATH];
1469 LPCTSTR path;
1470 ShellPath shell_path = DesktopFolderPath();
1471
1472 if (lparam) {
1473 if (wparam & OWM_PIDL) {
1474 // take over PIDL from lparam
1475 shell_path.assign((LPCITEMIDLIST)lparam); // create as "rooted" window
1476 FileSysShellPath fsp(shell_path);
1477 path = fsp;
1478
1479 if (path) {
1480 LOG(FmtString(TEXT("SDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
1481 lstrcpy(buffer, path);
1482 path = buffer;
1483 }
1484 } else {
1485 // take over path from lparam
1486 path = (LPCTSTR)lparam;
1487 shell_path = path; // create as "rooted" window
1488 }
1489 } else {
1490 ///@todo read paths and window placements from registry
1491 if (!GetCurrentDirectory(MAX_PATH, buffer))
1492 *buffer = '\0';
1493
1494 path = buffer;
1495 shell_path = path;
1496 }
1497
1498 if (wparam & OWM_ROOTED)
1499 _shellpath_info._root_shell_path = shell_path;
1500 else
1501 _shellpath_info._root_shell_path = DesktopFolderPath(); //SpecialFolderPath(CSIDL_DRIVES, _hwnd);
1502
1503 jump_to(shell_path, wparam); ///@todo content of 'path' not used any more
1504 return TRUE;} // success
1505
1506 default: def:
1507 return super::WndProc(nmsg, wparam, lparam);
1508 }
1509
1510 return 0;
1511 }
1512
1513 int SDIMainFrame::Command(int id, int code)
1514 {
1515 switch(id) {
1516 case ID_VIEW_MDI:
1517 MainFrameBase::Create(ExplorerCmd(_url, true));
1518 break;
1519
1520 default:
1521 return super::Command(id, code);
1522 }
1523
1524 return 0;
1525 }
1526
1527 void SDIMainFrame::resize_frame(int cx, int cy)
1528 {
1529 if (cy <= 0)
1530 return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1531
1532 RECT rect = {0, 0, cx, cy};
1533
1534 if (_hwndrebar) {
1535 int height = ClientRect(_hwndrebar).bottom;
1536 rect.top += height;
1537 rect.top += 5;
1538 } else {
1539 if (IsWindowVisible(_htoolbar)) {
1540 SendMessage(_htoolbar, WM_SIZE, 0, 0);
1541 WindowRect rt(_htoolbar);
1542 rect.top = rt.bottom;
1543 // rect.bottom -= rt.bottom;
1544 }
1545 }
1546
1547 if (IsWindowVisible(_hstatusbar)) {
1548 int parts[] = {300, 500};
1549
1550 SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1551 SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1552 ClientRect rt(_hstatusbar);
1553 rect.bottom -= rt.bottom;
1554 }
1555
1556 if (IsWindowVisible(_hsidebar)) {
1557 WindowRect rt(_hsidebar);
1558 rect.left += rt.right-rt.left;
1559
1560 SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1561 }
1562
1563 _clnt_rect = rect;
1564
1565 resize_children();
1566 }
1567
1568 void SDIMainFrame::resize_children()
1569 {
1570 HDWP hdwp = BeginDeferWindowPos(2);
1571
1572 int cx = _clnt_rect.left;
1573
1574 if (_left_hwnd) {
1575 cx = _split_pos + SPLIT_WIDTH/2;
1576
1577 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);
1578 } else {
1579 //_split_pos = -1;
1580 cx = 0;
1581 }
1582
1583 if (_right_hwnd)
1584 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);
1585
1586 EndDeferWindowPos(hdwp);
1587 }
1588
1589 void SDIMainFrame::update_clnt_rect()
1590 {
1591 ClientRect rect(_hwnd);
1592
1593 resize_frame(rect.right, rect.bottom);
1594 }
1595
1596 void SDIMainFrame::update_shell_browser()
1597 {
1598 int split_pos = DEFAULT_SPLIT_POS;
1599
1600 if (_shellBrowser.get()) {
1601 split_pos = _split_pos;
1602 delete _shellBrowser.release();
1603 }
1604
1605 // create explorer treeview
1606 if (_shellpath_info._open_mode & OWM_EXPLORE) {
1607 if (!_left_hwnd) {
1608 ClientRect rect(_hwnd);
1609
1610 _left_hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1611 WS_CHILD|WS_TABSTOP|WS_VISIBLE|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_NOTOOLTIPS|TVS_SHOWSELALWAYS,
1612 0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
1613 _hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
1614
1615 // display tree window as long as the shell view is not yet visible
1616 resize_frame(rect.right, rect.bottom);
1617 MoveWindow(_left_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
1618 }
1619 } else {
1620 if (_left_hwnd) {
1621 DestroyWindow(_left_hwnd);
1622 _left_hwnd = 0;
1623 }
1624 }
1625
1626 _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _hwnd, _left_hwnd, _right_hwnd,
1627 _shellpath_info, this, _cm_ifs));
1628
1629 if (_left_hwnd)
1630 _shellBrowser->Init();
1631
1632 // update _clnt_rect and set size of new created shell view windows
1633 update_clnt_rect();
1634 }
1635
1636 void SDIMainFrame::entry_selected(Entry* entry)
1637 {
1638 if (_left_hwnd)
1639 _shellBrowser->select_folder(entry, false);
1640
1641 _shellBrowser->UpdateFolderView(entry->get_shell_folder());
1642
1643 // set size of new created shell view windows
1644 resize_children();
1645 }
1646
1647 void SDIMainFrame::set_url(LPCTSTR url)
1648 {
1649 if (_url != url) {
1650 _url = url;
1651 SetWindowText(_haddrcombo, url);
1652 }
1653 }
1654
1655
1656 void SDIMainFrame::jump_to(LPCTSTR path, int mode)
1657 {/*@@todo
1658 if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1659 _shellBrowser->jump_to(path);
1660
1661 _shellpath_info._shell_path = path;
1662 } else */{
1663 _shellpath_info._open_mode = mode;
1664 _shellpath_info._shell_path = path;
1665
1666 update_shell_browser();
1667 }
1668 }
1669
1670 void SDIMainFrame::jump_to(LPCITEMIDLIST path, int mode)
1671 {
1672 if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1673 ShellPath shell_path = path;
1674
1675 _shellBrowser->jump_to(shell_path);
1676
1677 _shellpath_info._shell_path = shell_path;
1678 } else {
1679 _shellpath_info._open_mode = mode;
1680 _shellpath_info._shell_path = path;
1681
1682 update_shell_browser();
1683 }
1684 }