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