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