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