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