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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 635 void ShellBrowser::refresh() 636 { 637 ///@todo 638 } 639 640 641 #ifndef _NO_MDI 642 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 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 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 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 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 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 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