1 /*
2 * Copyright 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // shellbrowser.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 #include <precomp.h>
30
31 // work around GCC's wide string constant bug
32 #ifdef __GNUC__
33 const LPCTSTR C_DRIVE = C_DRIVE_STR;
34 #endif
35
ShellBrowser(HWND hwnd,HWND hwndFrame,HWND left_hwnd,WindowHandle & right_hwnd,ShellPathInfo & create_info,BrowserCallback * cb,CtxMenuInterfaces & cm_ifs)36 ShellBrowser::ShellBrowser(HWND hwnd, HWND hwndFrame, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info,
37 BrowserCallback* cb, CtxMenuInterfaces& cm_ifs)
38 : super(IID_IShellFolderViewCB),
39 _hwnd(hwnd),
40 _hwndFrame(hwndFrame),
41 _left_hwnd(left_hwnd),
42 _right_hwnd(right_hwnd),
43 _create_info(create_info),
44 _callback(cb),
45 _cm_ifs(cm_ifs)
46 {
47 _pShellView = NULL;
48 _pDropTarget = NULL;
49 _last_sel = 0;
50
51 _cur_dir = NULL;
52
53 HDC hDC = GetDC(NULL);
54 if (hDC)
55 {
56 INT bpp = GetDeviceCaps(hDC, BITSPIXEL);
57 ReleaseDC(NULL, hDC);
58
59 DWORD ilMask;
60 if (bpp <= 4)
61 ilMask = ILC_COLOR4;
62 else if (bpp <= 8)
63 ilMask = ILC_COLOR8;
64 else if (bpp <= 16)
65 ilMask = ILC_COLOR16;
66 else if (bpp <= 24)
67 ilMask = ILC_COLOR24;
68 else if (bpp <= 32)
69 ilMask = ILC_COLOR32;
70 else
71 ilMask = ILC_COLOR;
72
73 ilMask |= ILC_MASK;
74
75 _himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ilMask, 2, 0);
76 ImageList_SetBkColor(_himl, GetSysColor(COLOR_WINDOW));
77 }
78 }
79
~ShellBrowser()80 ShellBrowser::~ShellBrowser()
81 {
82 (void)TreeView_SetImageList(_left_hwnd, _himl_old, TVSIL_NORMAL);
83 ImageList_Destroy(_himl);
84
85 if (_pShellView)
86 _pShellView->Release();
87
88 if (_pDropTarget) {
89 _pDropTarget->Release();
90 _pDropTarget = NULL;
91 }
92
93 if (_right_hwnd) {
94 DestroyWindow(_right_hwnd);
95 _right_hwnd = 0;
96 }
97 }
98
99
Init()100 void ShellBrowser::Init()
101 {
102 CONTEXT("ShellBrowser::Init()");
103
104 const String& root_name = GetDesktopFolder().get_name(_create_info._root_shell_path, SHGDN_FORADDRESSBAR);
105
106 _root._drive_type = DRIVE_UNKNOWN;
107 lstrcpy(_root._volname, root_name);
108 _root._fs_flags = 0;
109 lstrcpy(_root._fs, TEXT("Desktop"));
110
111 _root._entry = new ShellDirectory(GetDesktopFolder(), _create_info._root_shell_path, _hwnd);
112
113 _root._entry->read_directory(SCAN_DONT_ACCESS|SCAN_NO_FILESYSTEM); // avoid to handle desktop root folder as file system directory
114
115 if (_left_hwnd) {
116 InitializeTree();
117 InitDragDrop();
118 }
119
120 jump_to(_create_info._shell_path);
121
122 /* already filled by ShellDirectory constructor
123 lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); */
124 }
125
jump_to(LPCITEMIDLIST pidl)126 void ShellBrowser::jump_to(LPCITEMIDLIST pidl)
127 {
128 Entry* entry = NULL;
129
130 if (!_cur_dir)
131 _cur_dir = static_cast<ShellDirectory*>(_root._entry);
132
133 //LOG(FmtString(TEXT("ShellBrowser::jump_to(): pidl=%s"), (LPCTSTR)FileSysShellPath(pidl)));
134
135 // We could call read_tree() here to iterate through the hierarchy and open all folders
136 // from _create_info._root_shell_path (_cur_dir) to _create_info._shell_path (pidl).
137 // To make it easier we just use ILFindChild() instead.
138 if (_cur_dir) {
139 static DynamicFct<LPITEMIDLIST(WINAPI*)(LPCITEMIDLIST, LPCITEMIDLIST)> ILFindChild(TEXT("SHELL32"), 24);
140
141 if (ILFindChild) {
142 for(;;) {
143 LPCITEMIDLIST child_pidl = (*ILFindChild)(_cur_dir->create_absolute_pidl(), pidl);
144 if (!child_pidl || !child_pidl->mkid.cb)
145 break;
146
147 _cur_dir->smart_scan(SORT_NAME, SCAN_DONT_ACCESS);
148
149 entry = _cur_dir->find_entry(child_pidl);
150 if (!entry)
151 break;
152
153 _cur_dir = static_cast<ShellDirectory*>(entry);
154 _callback->entry_selected(entry);
155 }
156 } else {
157 _cur_dir->smart_scan(SORT_NAME, SCAN_DONT_ACCESS);
158
159 entry = _cur_dir->find_entry(pidl); // This is not correct in the common case, but works on the desktop level.
160
161 if (entry) {
162 _cur_dir = static_cast<ShellDirectory*>(entry);
163 _callback->entry_selected(entry);
164 }
165 }
166 }
167
168 // If not already called, now directly call UpdateFolderView() using pidl
169 if (!entry)
170 UpdateFolderView(ShellFolder(pidl));
171 }
172
173
InitializeTree()174 void ShellBrowser::InitializeTree()
175 {
176 CONTEXT("ShellBrowserChild::InitializeTree()");
177
178 _himl_old = TreeView_SetImageList(_left_hwnd, _himl, TVSIL_NORMAL);
179 TreeView_SetScrollTime(_left_hwnd, 100);
180
181 TV_INSERTSTRUCT tvInsert;
182 TV_ITEM& tvItem = tvInsert.item;
183
184 tvInsert.hParent = 0;
185 tvInsert.hInsertAfter = TVI_LAST;
186
187 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
188 tvItem.lParam = (LPARAM)_root._entry;
189 tvItem.pszText = _root._volname; //LPSTR_TEXTCALLBACK;
190 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
191 tvItem.cChildren = 1;
192
193 HTREEITEM hItem = TreeView_InsertItem(_left_hwnd, &tvInsert);
194 TreeView_SelectItem(_left_hwnd, hItem);
195 TreeView_Expand(_left_hwnd, hItem, TVE_EXPAND);
196 }
197
InitDragDrop()198 bool ShellBrowser::InitDragDrop()
199 {
200 CONTEXT("ShellBrowser::InitDragDrop()");
201
202 _pDropTarget = new TreeDropTarget(_left_hwnd);
203
204 if (!_pDropTarget)
205 return false;
206
207 _pDropTarget->AddRef();
208
209 if (FAILED(RegisterDragDrop(_left_hwnd, _pDropTarget))) {//calls addref
210 _pDropTarget->Release(); // free TreeDropTarget
211 _pDropTarget = NULL;
212 return false;
213 } else
214 _pDropTarget->Release();
215
216 FORMATETC ftetc;
217
218 ftetc.dwAspect = DVASPECT_CONTENT;
219 ftetc.lindex = -1;
220 ftetc.tymed = TYMED_HGLOBAL;
221 ftetc.cfFormat = CF_HDROP;
222
223 _pDropTarget->AddSuportedFormat(ftetc);
224
225 return true;
226 }
227
228
OnTreeGetDispInfo(int idCtrl,LPNMHDR pnmh)229 void ShellBrowser::OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh)
230 {
231 CONTEXT("ShellBrowser::OnTreeGetDispInfo()");
232
233 LPNMTVDISPINFO lpdi = (LPNMTVDISPINFO)pnmh;
234 ShellEntry* entry = (ShellEntry*)lpdi->item.lParam;
235
236 if (entry) {
237 if (lpdi->item.mask & TVIF_TEXT)
238 lpdi->item.pszText = entry->_display_name;
239
240 if (lpdi->item.mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
241 if (lpdi->item.mask & TVIF_IMAGE)
242 lpdi->item.iImage = get_image_idx(
243 entry->safe_extract_icon((ICONCACHE_FLAGS)(ICF_HICON|ICF_OVERLAYS)));
244
245 if (lpdi->item.mask & TVIF_SELECTEDIMAGE)
246 lpdi->item.iSelectedImage = get_image_idx(
247 entry->safe_extract_icon((ICONCACHE_FLAGS)(ICF_HICON|ICF_OVERLAYS|ICF_OPEN)));
248 }
249 }
250 }
251
get_image_idx(int icon_id)252 int ShellBrowser::get_image_idx(int icon_id)
253 {
254 if (icon_id != ICID_NONE) {
255 map<int,int>::const_iterator found = _image_map.find(icon_id);
256
257 if (found != _image_map.end())
258 return found->second;
259
260 int idx = ImageList_AddIcon(_himl, g_Globals._icon_cache.get_icon(icon_id).get_hicon());
261
262 _image_map[icon_id] = idx;
263
264 return idx;
265 } else
266 return -1;
267 }
268
invalidate_cache()269 void ShellBrowser::invalidate_cache()
270 {
271 (void)TreeView_SetImageList(_left_hwnd, _himl_old, TVSIL_NORMAL);
272 ImageList_Destroy(_himl);
273
274 _himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK|ILC_COLOR24, 2, 0);
275 ImageList_SetBkColor(_himl, GetSysColor(COLOR_WINDOW));
276
277 _himl_old = TreeView_SetImageList(_left_hwnd, _himl, TVSIL_NORMAL);
278
279 for(map<int,int>::const_iterator it=_image_map.begin(); it!=_image_map.end(); ++it)
280 g_Globals._icon_cache.free_icon(it->first);
281
282 _image_map.clear();
283 }
284
285
OnTreeItemExpanding(int idCtrl,LPNMTREEVIEW pnmtv)286 void ShellBrowser::OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv)
287 {
288 CONTEXT("ShellBrowser::OnTreeItemExpanding()");
289
290 if (pnmtv->action == TVE_COLLAPSE)
291 TreeView_Expand(_left_hwnd, pnmtv->itemNew.hItem, TVE_COLLAPSE|TVE_COLLAPSERESET);
292 else if (pnmtv->action == TVE_EXPAND) {
293 ShellDirectory* entry = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, pnmtv->itemNew.hItem);
294
295 if (entry)
296 if (!InsertSubitems(pnmtv->itemNew.hItem, entry, entry->_folder)) {
297 entry->_shell_attribs &= ~SFGAO_HASSUBFOLDER;
298
299 // remove subitem "+"
300 TV_ITEM tvItem;
301
302 tvItem.mask = TVIF_CHILDREN;
303 tvItem.hItem = pnmtv->itemNew.hItem;
304 tvItem.cChildren = 0;
305
306 TreeView_SetItem(_left_hwnd, &tvItem);
307 }
308 }
309 }
310
InsertSubitems(HTREEITEM hParentItem,Entry * entry,IShellFolder * pParentFolder)311 int ShellBrowser::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder)
312 {
313 CONTEXT("ShellBrowser::InsertSubitems()");
314
315 WaitCursor wait;
316
317 int cnt = 0;
318
319 SendMessage(_left_hwnd, WM_SETREDRAW, FALSE, 0);
320
321 try {
322 entry->smart_scan(SORT_NAME, SCAN_DONT_ACCESS);
323 } catch(COMException& e) {
324 HandleException(e, g_Globals._hMainWnd);
325 }
326
327 // remove old children items
328 HTREEITEM hchild, hnext;
329
330 hnext = TreeView_GetChild(_left_hwnd, hParentItem);
331
332 while((hchild=hnext) != 0) {
333 hnext = TreeView_GetNextSibling(_left_hwnd, hchild);
334 TreeView_DeleteItem(_left_hwnd, hchild);
335 }
336
337 TV_ITEM tvItem;
338 TV_INSERTSTRUCT tvInsert;
339
340 for(entry=entry->_down; entry; entry=entry->_next) {
341 #ifndef _LEFT_FILES
342 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
343 #endif
344 {
345 // ignore hidden directories
346 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
347 continue;
348
349 // ignore directory entries "." and ".."
350 if (entry->_data.cFileName[0]==TEXT('.') &&
351 (entry->_data.cFileName[1]==TEXT('\0') ||
352 (entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0'))))
353 continue;
354
355 ZeroMemory(&tvItem, sizeof(tvItem));
356
357 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
358 tvItem.pszText = LPSTR_TEXTCALLBACK;
359 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
360 tvItem.lParam = (LPARAM)entry;
361 tvItem.cChildren = entry->_shell_attribs & SFGAO_HASSUBFOLDER? 1: 0;
362
363 if (entry->_shell_attribs & SFGAO_SHARE) {
364 tvItem.mask |= TVIF_STATE;
365 tvItem.stateMask |= TVIS_OVERLAYMASK;
366 tvItem.state |= INDEXTOOVERLAYMASK(1);
367 }
368
369 tvInsert.item = tvItem;
370 tvInsert.hInsertAfter = TVI_LAST;
371 tvInsert.hParent = hParentItem;
372
373 (void)TreeView_InsertItem(_left_hwnd, &tvInsert);
374
375 ++cnt;
376 }
377 }
378
379 SendMessage(_left_hwnd, WM_SETREDRAW, TRUE, 0);
380
381 return cnt;
382 }
383
384
OnTreeItemSelected(int idCtrl,LPNMTREEVIEW pnmtv)385 void ShellBrowser::OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv)
386 {
387 CONTEXT("ShellBrowser::OnTreeItemSelected()");
388
389 Entry* entry = (Entry*)pnmtv->itemNew.lParam;
390
391 _last_sel = pnmtv->itemNew.hItem;
392
393 if (entry)
394 _callback->entry_selected(entry);
395 }
396
397
OnTreeItemRClick(int idCtrl,LPNMHDR pnmh)398 void ShellBrowser::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh)
399 {
400 CONTEXT("ShellBrowser::OnTreeItemRClick()");
401
402 TVHITTESTINFO tvhti;
403
404 GetCursorPos(&tvhti.pt);
405 ScreenToClient(_left_hwnd, &tvhti.pt);
406
407 tvhti.flags = LVHT_NOWHERE;
408 (void)TreeView_HitTest(_left_hwnd, &tvhti);
409
410 if (TVHT_ONITEM & tvhti.flags) {
411 LPARAM itemData = TreeView_GetItemData(_left_hwnd, tvhti.hItem);
412
413 if (itemData) {
414 Entry* entry = (Entry*)itemData;
415 ClientToScreen(_left_hwnd, &tvhti.pt);
416
417 HRESULT hr = entry->do_context_menu(_hwnd, tvhti.pt, _cm_ifs);
418
419 if (SUCCEEDED(hr))
420 refresh();
421 else
422 CHECKERROR(hr);
423 }
424 }
425 }
426
427
UpdateFolderView(IShellFolder * folder)428 void ShellBrowser::UpdateFolderView(IShellFolder* folder)
429 {
430 CONTEXT("ShellBrowser::UpdateFolderView()");
431
432 FOLDERSETTINGS fs;
433 IShellView* pLastShellView = _pShellView;
434
435 _folder = folder;
436
437 if (pLastShellView)
438 pLastShellView->GetCurrentInfo(&fs);
439 else {
440 fs.ViewMode = _create_info._open_mode&OWM_DETAILS? FVM_DETAILS: FVM_ICON;
441 fs.fFlags = FWF_NOCLIENTEDGE|FWF_BESTFITWINDOW;
442 }
443
444 SFV_CREATE sfv_create;
445
446 sfv_create.cbSize = sizeof(SFV_CREATE);
447 sfv_create.pshf = folder;
448 sfv_create.psvOuter = NULL;
449 sfv_create.psfvcb = this;
450
451 HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
452
453 if (FAILED(hr)) {
454 _pShellView = NULL;
455 return;
456 }
457
458 RECT rect = {CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT};
459 hr = _pShellView->CreateViewWindow(pLastShellView, &fs, static_cast<IShellBrowser*>(this), &rect, &_right_hwnd/*&m_hWndListView*/);
460
461 if (pLastShellView) {
462 pLastShellView->GetCurrentInfo(&fs);
463 pLastShellView->UIActivate(SVUIA_DEACTIVATE);
464 pLastShellView->DestroyViewWindow();
465 pLastShellView->Release();
466 }
467
468 _pShellView->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
469 }
470
471 /// shell view callback
MessageSFVCB(UINT uMsg,WPARAM wParam,LPARAM lParam)472 HRESULT STDMETHODCALLTYPE ShellBrowser::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
473 {
474 if (uMsg == SFVM_INITMENUPOPUP) {
475 ///@todo never reached
476 InsertMenu((HMENU)lParam, 0, MF_BYPOSITION, 12345, TEXT("TEST ENTRY"));
477 return S_OK;
478 }
479
480 return E_NOTIMPL;
481 }
482
483
OnDefaultCommand(LPIDA pida)484 HRESULT ShellBrowser::OnDefaultCommand(LPIDA pida)
485 {
486 CONTEXT("ShellBrowser::OnDefaultCommand()");
487
488 if (pida->cidl >= 1) {
489 if (_left_hwnd) { // explorer mode
490 if (_last_sel) {
491 ShellDirectory* parent = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, _last_sel);
492
493 if (parent) {
494 try {
495 parent->smart_scan(SORT_NAME, SCAN_DONT_ACCESS);
496 } catch(COMException& e) {
497 return e.Error();
498 }
499
500 UINT firstOffset = pida->aoffset[1];
501 LPITEMIDLIST pidl = (LPITEMIDLIST)((LPBYTE)pida+firstOffset);
502
503 Entry* entry = parent->find_entry(pidl);
504
505 if (entry && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
506 if (entry->_etype == ET_SHELL)
507 if (_last_sel && select_entry(_last_sel, entry))
508 return S_OK;
509
510 ///@todo look for hidden or new subfolders and refresh/add new entry instead of opening a new window
511 return E_NOTIMPL;
512 }
513 }
514 } else { // no tree control
515 if (MainFrameBase::OpenShellFolders(pida, _hwndFrame))
516 return S_OK;
517
518 /* create new Frame Window
519 if (MainFrame::OpenShellFolders(pida, 0))
520 return S_OK;
521 */
522 }
523 }
524
525 return E_NOTIMPL;
526 }
527
528
select_entry(HTREEITEM hitem,Entry * entry,bool expand)529 HTREEITEM ShellBrowser::select_entry(HTREEITEM hitem, Entry* entry, bool expand)
530 {
531 CONTEXT("ShellBrowser::select_entry()");
532
533 if (expand && !TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND))
534 return 0;
535
536 for(hitem=TreeView_GetChild(_left_hwnd,hitem); hitem; hitem=TreeView_GetNextSibling(_left_hwnd,hitem)) {
537 if ((Entry*)TreeView_GetItemData(_left_hwnd,hitem) == entry) {
538 if (TreeView_SelectItem(_left_hwnd, hitem)) {
539 if (expand)
540 TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND);
541
542 return hitem;
543 }
544
545 break;
546 }
547 }
548
549 return 0;
550 }
551
552
jump_to_pidl(LPCITEMIDLIST pidl)553 bool ShellBrowser::jump_to_pidl(LPCITEMIDLIST pidl)
554 {
555 if (!_root._entry)
556 return false;
557
558 // iterate through the hierarchy and open all folders to reach pidl
559 WaitCursor wait;
560
561 HTREEITEM hitem = TreeView_GetRoot(_left_hwnd);
562 Entry* entry = _root._entry;
563
564 for(const void*p=pidl;;) {
565 if (!p)
566 return true;
567
568 if (!entry || !hitem)
569 break;
570
571 entry->smart_scan(SORT_NAME, SCAN_DONT_ACCESS);
572
573 Entry* found = entry->find_entry(p);
574 p = entry->get_next_path_component(p);
575
576 if (found)
577 hitem = select_entry(hitem, found);
578
579 entry = found;
580 }
581
582 return false;
583 }
584
TranslateAccelerator(LPMSG lpmsg)585 bool ShellBrowser::TranslateAccelerator(LPMSG lpmsg)
586 {
587 HWND hwnd;
588
589 /* TranslateAccelerator is called for all explorer windows that are open
590 so we have to decide if this is the correct recipient */
591 hwnd = lpmsg->hwnd;
592
593 while(hwnd)
594 {
595 if(hwnd == _hwnd)
596 break;
597
598 hwnd = GetParent(hwnd);
599 }
600
601 if (hwnd)
602 return _pShellView->TranslateAccelerator(lpmsg) == S_OK;
603
604 return false;
605 }
606
select_folder(Entry * entry,bool expand)607 bool ShellBrowser::select_folder(Entry* entry, bool expand)
608 {
609 CONTEXT("ShellBrowser::expand_folder()");
610
611 if (!_last_sel)
612 return false;
613
614 if (!TreeView_Expand(_left_hwnd, _last_sel, TVE_EXPAND))
615 return false;
616
617 for(HTREEITEM hitem=TreeView_GetChild(_left_hwnd,_last_sel); hitem; hitem=TreeView_GetNextSibling(_left_hwnd,hitem)) {
618 if ((ShellDirectory*)TreeView_GetItemData(_left_hwnd,hitem) == entry) {
619 if (TreeView_SelectItem(_left_hwnd, hitem)) {
620 if (expand)
621 if (!TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND))
622 return false;
623
624 return true;
625 }
626
627 break;
628 }
629 }
630
631 return false;
632 }
633
634
refresh()635 void ShellBrowser::refresh()
636 {
637 ///@todo
638 }
639
640
641 #ifndef _NO_MDI
642
MDIShellBrowserChild(HWND hwnd,const ShellChildWndInfo & info)643 MDIShellBrowserChild::MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info)
644 : super(hwnd, info),
645 _create_info(info),
646 _shellpath_info(info) //@@ copies info -> no reference to _create_info !
647 {
648 /**todo Conversion of shell path into path string -> store into URL history
649 const String& path = GetDesktopFolder().get_name(info._shell_path, SHGDN_FORADDRESSBAR);
650 const String& parsingpath = GetDesktopFolder().get_name(info._shell_path, SHGDN_FORPARSING);
651
652 // store path into history
653 if (info._path && *info._path)
654 _url_history.push(info._path);
655 */
656 }
657
658
create(const ShellChildWndInfo & info)659 MDIShellBrowserChild* MDIShellBrowserChild::create(const ShellChildWndInfo& info)
660 {
661 ChildWindow* child = ChildWindow::create(info,
662 info._pos.rcNormalPosition,
663 WINDOW_CREATOR_INFO(MDIShellBrowserChild,ShellChildWndInfo),
664 CLASSNAME_CHILDWND,
665 NULL,
666 WS_CLIPCHILDREN | (info._pos.showCmd==SW_SHOWMAXIMIZED? WS_MAXIMIZE: 0));
667
668 return static_cast<MDIShellBrowserChild*>(child);
669 }
670
671
Init(LPCREATESTRUCT pcs)672 LRESULT MDIShellBrowserChild::Init(LPCREATESTRUCT pcs)
673 {
674 CONTEXT("MDIShellBrowserChild::Init()");
675
676 if (super::Init(pcs))
677 return 1;
678
679 update_shell_browser();
680
681 return 0;
682 }
683
684
WndProc(UINT nmsg,WPARAM wparam,LPARAM lparam)685 LRESULT MDIShellBrowserChild::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
686 {
687 switch(nmsg) {
688 case PM_DISPATCH_COMMAND: {
689 switch(LOWORD(wparam)) {
690 case ID_WINDOW_NEW: {CONTEXT("MDIShellBrowserChild PM_DISPATCH_COMMAND ID_WINDOW_NEW");
691 MDIShellBrowserChild::create(_create_info);
692 break;}
693
694 case ID_REFRESH:
695 ///@todo refresh shell child
696 _shellBrowser->invalidate_cache();
697 break;
698
699 case ID_VIEW_SDI:
700 MainFrameBase::Create(ExplorerCmd(_url, false));
701 break;
702
703 default:
704 return super::WndProc(nmsg, wparam, lparam);
705 }
706 return TRUE;}
707
708 case WM_SYSCOLORCHANGE:
709 /* Forward WM_SYSCOLORCHANGE to common controls */
710 SendMessage(_left_hwnd, WM_SYSCOLORCHANGE, 0, 0);
711 SendMessage(_right_hwnd, WM_SYSCOLORCHANGE, 0, 0);
712 break;
713
714 case PM_TRANSLATE_MSG:
715 return _shellBrowser->TranslateAccelerator((MSG*)lparam);
716
717 default:
718 return super::WndProc(nmsg, wparam, lparam);
719 }
720
721 return 0;
722 }
723
update_shell_browser()724 void MDIShellBrowserChild::update_shell_browser()
725 {
726 int split_pos = DEFAULT_SPLIT_POS;
727
728 if (_shellBrowser.get()) {
729 split_pos = _split_pos;
730 delete _shellBrowser.release();
731 }
732
733 // create explorer treeview
734 if (_create_info._open_mode & OWM_EXPLORE) {
735 if (!_left_hwnd) {
736 ClientRect rect(_hwnd);
737
738 _left_hwnd = CreateWindowEx(0, WC_TREEVIEW, NULL,
739 WS_CHILD|WS_TABSTOP|WS_VISIBLE|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS,//|TVS_NOTOOLTIPS
740 0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
741 _hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
742 }
743 } else {
744 if (_left_hwnd) {
745 DestroyWindow(_left_hwnd);
746 _left_hwnd = 0;
747 }
748 }
749
750 _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _hwndFrame, _left_hwnd, _right_hwnd,
751 _shellpath_info, this, _cm_ifs));
752
753 _shellBrowser->Init();
754 }
755
756
jump_to_int(LPCTSTR url)757 String MDIShellBrowserChild::jump_to_int(LPCTSTR url)
758 {
759 String dir, fname;
760
761 if (!_tcsnicmp(url, TEXT("shell://"), 8)) {
762 if (_shellBrowser->jump_to_pidl(ShellPath(url+8)))
763 return url;
764 }
765
766 if (SplitFileSysURL(url, dir, fname)) {
767
768 ///@todo use fname
769
770 if (_shellBrowser->jump_to_pidl(ShellPath(dir)))
771 return FmtString(TEXT("file://%s"), (LPCTSTR)dir);
772 }
773
774 return String();
775 }
776
777
entry_selected(Entry * entry)778 void MDIShellBrowserChild::entry_selected(Entry* entry)
779 {
780 if (_left_hwnd)
781 _shellBrowser->select_folder(entry, false);
782
783 _shellBrowser->UpdateFolderView(entry->get_shell_folder());
784
785 // set size of new created shell view windows
786 ClientRect rt(_hwnd);
787 resize_children(rt.right, rt.bottom);
788
789 // set new URL
790 TCHAR path[MAX_PATH];
791
792 if (entry->get_path(path, COUNTOF(path))) {
793 String url;
794
795 if (path[0] == ':')
796 url.printf(TEXT("shell://%s"), path);
797 else
798 url.printf(TEXT("file://%s"), path);
799
800 set_url(url);
801 }
802 }
803
804 #endif
805