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