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