[BROWSEUI]
[reactos.git] / reactos / dll / win32 / browseui / explorerband.cpp
1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "precomp.h"
22 #include <commoncontrols.h>
23 #include <undocshell.h>
24
25 #if 1
26 #undef UNIMPLEMENTED
27
28 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
29 #endif
30
31 extern "C"
32 HRESULT WINAPI CExplorerBand_Constructor(REFIID riid, LPVOID *ppv)
33 {
34 return ShellObjectCreator<CExplorerBand>(riid, ppv);
35 }
36
37 CExplorerBand::CExplorerBand() :
38 pSite(NULL), fVisible(FALSE), bNavigating(FALSE), dwBandID(0)
39 {
40 }
41
42 CExplorerBand::~CExplorerBand()
43 {
44 }
45
46 void CExplorerBand::InitializeExplorerBand()
47 {
48 // Init the treeview here
49 HRESULT hr;
50 LPITEMIDLIST pidl;
51 CComPtr<IWebBrowser2> browserService;
52 SHChangeNotifyEntry shcne;
53
54 hr = SHGetDesktopFolder(&pDesktop);
55 if (FAILED_UNEXPECTEDLY(hr))
56 return;
57
58 hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidl);
59 if (FAILED_UNEXPECTEDLY(hr))
60 return;
61
62 IImageList * piml;
63 hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
64 if (FAILED_UNEXPECTEDLY(hr))
65 return;
66
67 TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
68
69 // Insert the root node
70 hRoot = InsertItem(0, pDesktop, pidl, pidl, FALSE);
71 if (!hRoot)
72 {
73 ERR("Failed to create root item\n");
74 return;
75 }
76
77 NodeInfo* pNodeInfo = GetNodeInfo(hRoot);
78
79 // Insert child nodes
80 InsertSubitems(hRoot, pNodeInfo);
81 TreeView_Expand(m_hWnd, hRoot, TVE_EXPAND);
82
83 // Navigate to current folder position
84 NavigateToCurrentFolder();
85
86 // Register shell notification
87 shcne.pidl = pidl;
88 shcne.fRecursive = TRUE;
89 shellRegID = SHChangeNotifyRegister(
90 m_hWnd,
91 SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt,
92 SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR,
93 WM_USER_SHELLEVENT,
94 1,
95 &shcne);
96 if (!shellRegID)
97 {
98 ERR("Something went wrong, error %08x\n", GetLastError());
99 }
100 // Register browser connection endpoint
101 hr = IUnknown_QueryService(pSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &browserService));
102 if (FAILED_UNEXPECTEDLY(hr))
103 return;
104
105 hr = AtlAdvise(browserService, dynamic_cast<IDispatch*>(this), DIID_DWebBrowserEvents, &adviseCookie);
106 if (FAILED_UNEXPECTEDLY(hr))
107 return;
108
109 ILFree(pidl);
110 }
111
112 void CExplorerBand::DestroyExplorerBand()
113 {
114 HRESULT hr;
115 CComPtr <IWebBrowser2> browserService;
116
117 TRACE("Cleaning up explorer band ...\n");
118
119 hr = IUnknown_QueryService(pSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &browserService));
120 if (FAILED_UNEXPECTEDLY(hr))
121 return;
122
123 hr = AtlUnadvise(browserService, DIID_DWebBrowserEvents, adviseCookie);
124 /* Remove all items of the treeview */
125 RevokeDragDrop(m_hWnd);
126 TreeView_DeleteAllItems(m_hWnd);
127 pDesktop = NULL;
128 hRoot = NULL;
129 TRACE("Cleanup done !\n");
130 }
131
132 CExplorerBand::NodeInfo* CExplorerBand::GetNodeInfo(HTREEITEM hItem)
133 {
134 TVITEM tvItem;
135
136 tvItem.mask = TVIF_PARAM;
137 tvItem.hItem = hItem;
138
139 if (!TreeView_GetItem(m_hWnd, &tvItem))
140 return 0;
141
142 return reinterpret_cast<NodeInfo*>(tvItem.lParam);
143 }
144
145 HRESULT CExplorerBand::UpdateBrowser(LPITEMIDLIST pidlGoto)
146 {
147 CComPtr<IShellBrowser> pBrowserService;
148 HRESULT hr;
149
150 hr = IUnknown_QueryService(pSite, SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &pBrowserService));
151 if (FAILED_UNEXPECTEDLY(hr))
152 return hr;
153
154 hr = pBrowserService->BrowseObject(pidlGoto, SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
155 if (FAILED_UNEXPECTEDLY(hr))
156 return hr;
157
158 return hr;
159 }
160
161 // *** notifications handling ***
162 BOOL CExplorerBand::OnTreeItemExpanding(LPNMTREEVIEW pnmtv)
163 {
164 NodeInfo *pNodeInfo;
165
166 if (pnmtv->action == TVE_COLLAPSE) {
167 if (pnmtv->itemNew.hItem == hRoot)
168 {
169 // Prenvent root from collapsing
170 pnmtv->itemNew.mask |= TVIF_STATE;
171 pnmtv->itemNew.stateMask |= TVIS_EXPANDED;
172 pnmtv->itemNew.state &= ~TVIS_EXPANDED;
173 pnmtv->action = TVE_EXPAND;
174 return TRUE;
175 }
176 }
177 if (pnmtv->action == TVE_EXPAND) {
178 // Grab our directory PIDL
179 pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
180 // We have it, let's try
181 if (pNodeInfo && !pNodeInfo->expanded)
182 if (!InsertSubitems(pnmtv->itemNew.hItem, pNodeInfo)) {
183 // remove subitem "+" since we failed to add subitems
184 TV_ITEM tvItem;
185
186 tvItem.mask = TVIF_CHILDREN;
187 tvItem.hItem = pnmtv->itemNew.hItem;
188 tvItem.cChildren = 0;
189
190 TreeView_SetItem(m_hWnd, &tvItem);
191 }
192 }
193 return FALSE;
194 }
195
196 void CExplorerBand::OnSelectionChanged(LPNMTREEVIEW pnmtv)
197 {
198 NodeInfo* pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
199
200 UpdateBrowser(pNodeInfo->absolutePidl);
201
202 /* Prevents navigation if selection is initiated inside the band */
203 if (bNavigating)
204 return;
205
206 SetFocus();
207 // Expand the node
208 //TreeView_Expand(m_hWnd, pnmtv->itemNew.hItem, TVE_EXPAND);
209 }
210
211 // *** Helper functions ***
212 HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort)
213 {
214 TV_INSERTSTRUCT tvInsert;
215 HTREEITEM htiCreated;
216
217 /* Get the attributes of the node */
218 SFGAOF attrs = SFGAO_STREAM | SFGAO_HASSUBFOLDER;
219 HRESULT hr = psfParent->GetAttributesOf(1, &pEltRelative, &attrs);
220 if (FAILED_UNEXPECTEDLY(hr))
221 return NULL;
222
223 /* Ignore streams */
224 if ((attrs & SFGAO_STREAM))
225 {
226 TRACE("Ignoring stream\n");
227 return NULL;
228 }
229
230 /* Get the name of the node */
231 WCHAR wszDisplayName[MAX_PATH];
232 if (!ILGetDisplayNameEx(psfParent, pEltRelative, wszDisplayName, ILGDN_INFOLDER))
233 {
234 ERR("Failed to get node name\n");
235 return NULL;
236 }
237
238 /* Get the icon of the node */
239 INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, NULL);
240
241 NodeInfo* pChildInfo = new NodeInfo;
242 if (!pChildInfo)
243 {
244 ERR("Failed to allocate NodeInfo\n");
245 return FALSE;
246 }
247
248 // Store our node info
249 pChildInfo->absolutePidl = ILClone(pElt);
250 pChildInfo->relativePidl = ILClone(pEltRelative);
251 pChildInfo->expanded = FALSE;
252
253 // Set up our treeview template
254 tvInsert.hParent = hParent;
255 tvInsert.hInsertAfter = TVI_LAST;
256 tvInsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
257 tvInsert.item.cchTextMax = MAX_PATH;
258 tvInsert.item.pszText = wszDisplayName;
259 tvInsert.item.iImage = tvInsert.item.iSelectedImage = iIcon;
260 tvInsert.item.cChildren = (attrs & SFGAO_HASSUBFOLDER) ? 1 : 0;
261 tvInsert.item.lParam = (LPARAM)pChildInfo;
262
263 htiCreated = TreeView_InsertItem(m_hWnd, &tvInsert);
264
265 return htiCreated;
266 }
267
268 /* This is the slow version of the above method */
269 HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort)
270 {
271 CComPtr<IShellFolder> psfFolder;
272 HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), NULL);
273 if (FAILED_UNEXPECTEDLY(hr))
274 return NULL;
275
276 return InsertItem(hParent, psfFolder, pElt, pEltRelative, bSort);
277 }
278
279 BOOL CExplorerBand::InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo)
280 {
281 CComPtr<IEnumIDList> pEnumIDList;
282 LPITEMIDLIST pidlSub;
283 LPITEMIDLIST entry;
284 SHCONTF EnumFlags;
285 HRESULT hr;
286 ULONG fetched;
287 ULONG uItemCount;
288 CComPtr<IShellFolder> pFolder;
289
290 entry = pNodeInfo->absolutePidl;
291 fetched = 1;
292 uItemCount = 0;
293 EnumFlags = SHCONTF_FOLDERS;
294
295 hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidlSub);
296 if (!SUCCEEDED(hr))
297 {
298 ERR("Can't get desktop PIDL !\n");
299 return FALSE;
300 }
301
302 if (!pDesktop->CompareIDs(NULL, pidlSub, entry))
303 {
304 // We are the desktop, so use pDesktop as pFolder
305 pFolder = pDesktop;
306 }
307 else
308 {
309 // Get an IShellFolder of our pidl
310 hr = pDesktop->BindToObject(entry, NULL, IID_PPV_ARG(IShellFolder, &pFolder));
311 if (!SUCCEEDED(hr))
312 {
313 ILFree(pidlSub);
314 ERR("Can't bind folder to desktop !\n");
315 return FALSE;
316 }
317 }
318 ILFree(pidlSub);
319
320 // TODO: handle hidden folders according to settings !
321 EnumFlags |= SHCONTF_INCLUDEHIDDEN;
322
323 // Enum through objects
324 hr = pFolder->EnumObjects(NULL,EnumFlags,&pEnumIDList);
325
326 // avoid broken IShellFolder implementations that return null pointer with success
327 if (!SUCCEEDED(hr) || !pEnumIDList)
328 {
329 ERR("Can't enum the folder !\n");
330 return FALSE;
331 }
332
333 /* Don't redraw while we add stuff into the tree */
334 SendMessage(WM_SETREDRAW, FALSE, 0);
335 while(SUCCEEDED(pEnumIDList->Next(1, &pidlSub, &fetched)) && pidlSub && fetched)
336 {
337 LPITEMIDLIST pidlSubComplete;
338 pidlSubComplete = ILCombine(entry, pidlSub);
339
340 if (InsertItem(hItem, pFolder, pidlSubComplete, pidlSub, FALSE))
341 uItemCount++;
342 ILFree(pidlSubComplete);
343 ILFree(pidlSub);
344 }
345 pNodeInfo->expanded = TRUE;
346
347 /* Now we can redraw */
348 SendMessage(WM_SETREDRAW, TRUE, 0);
349
350 return (uItemCount > 0) ? TRUE : FALSE;
351 }
352
353 /**
354 * Navigate to a given PIDL in the treeview, and return matching tree item handle
355 * - dest: The absolute PIDL we should navigate in the treeview
356 * - item: Handle of the tree item matching the PIDL
357 * - bExpand: expand collapsed nodes in order to find the right element
358 * - bInsert: insert the element at the right place if we don't find it
359 * - bSelect: select the item after we found it
360 */
361 BOOL CExplorerBand::NavigateToPIDL(LPITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert,
362 BOOL bSelect)
363 {
364 HTREEITEM current;
365 HTREEITEM tmp;
366 HTREEITEM parent;
367 BOOL found;
368 NodeInfo *nodeData;
369 LPITEMIDLIST relativeChild;
370 TVITEM tvItem;
371
372 if (!item)
373 return FALSE;
374
375 found = FALSE;
376 current = hRoot;
377 parent = NULL;
378 while(!found)
379 {
380 nodeData = GetNodeInfo(current);
381 if (!nodeData)
382 {
383 ERR("Something has gone wrong, no data associated to node !\n");
384 *item = NULL;
385 return FALSE;
386 }
387 // If we found our node, give it back
388 if (!pDesktop->CompareIDs(0, nodeData->absolutePidl, dest))
389 {
390 if (bSelect)
391 TreeView_SelectItem(m_hWnd, current);
392 *item = current;
393 return TRUE;
394 }
395
396 // Check if we are a parent of the requested item
397 relativeChild = ILFindChild(nodeData->absolutePidl, dest);
398 if (relativeChild != 0)
399 {
400 // Notify treeview we have children
401 tvItem.mask = TVIF_CHILDREN;
402 tvItem.hItem = current;
403 tvItem.cChildren = 1;
404 TreeView_SetItem(m_hWnd, &tvItem);
405
406 // If we can expand and the node isn't expanded yet, do it
407 if (bExpand)
408 {
409 if (!nodeData->expanded)
410 InsertSubitems(current, nodeData);
411 TreeView_Expand(m_hWnd, current, TVE_EXPAND);
412 }
413
414 // Try to get a child
415 tmp = TreeView_GetChild(m_hWnd, current);
416 if (tmp)
417 {
418 // We have a child, let's continue with it
419 parent = current;
420 current = tmp;
421 continue;
422 }
423
424 if (bInsert && nodeData->expanded)
425 {
426 // Happens when we have to create a subchild inside a child
427 current = InsertItem(current, dest, relativeChild, TRUE);
428 }
429 // We end up here, without any children, so we found nothing
430 // Tell the parent node it has children
431 ZeroMemory(&tvItem, sizeof(tvItem));
432 *item = NULL;
433 return FALSE;
434 }
435
436 // Find sibling
437 tmp = TreeView_GetNextSibling(m_hWnd, current);
438 if (tmp)
439 {
440 current = tmp;
441 continue;
442 }
443 if (bInsert)
444 {
445 current = InsertItem(parent, dest, ILFindLastID(dest), TRUE);
446 *item = current;
447 return TRUE;
448 }
449 *item = NULL;
450 return FALSE;
451 }
452 return FALSE;
453 }
454
455 BOOL CExplorerBand::NavigateToCurrentFolder()
456 {
457 LPITEMIDLIST explorerPidl;
458 CComPtr<IBrowserService> pBrowserService;
459 HRESULT hr;
460 HTREEITEM dummy;
461 BOOL result;
462 explorerPidl = NULL;
463
464 hr = IUnknown_QueryService(pSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &pBrowserService));
465 if (!SUCCEEDED(hr))
466 {
467 ERR("Can't get IBrowserService !\n");
468 return FALSE;
469 }
470
471 hr = pBrowserService->GetPidl(&explorerPidl);
472 if (!SUCCEEDED(hr) || !explorerPidl)
473 {
474 ERR("Unable to get browser PIDL !\n");
475 return FALSE;
476 }
477 bNavigating = TRUE;
478 /* find PIDL into our explorer */
479 result = NavigateToPIDL(explorerPidl, &dummy, TRUE, FALSE, TRUE);
480 bNavigating = FALSE;
481 return result;
482 }
483
484 // *** IOleWindow methods ***
485 HRESULT STDMETHODCALLTYPE CExplorerBand::GetWindow(HWND *lphwnd)
486 {
487 if (!lphwnd)
488 return E_INVALIDARG;
489 *lphwnd = m_hWnd;
490 return S_OK;
491 }
492
493 HRESULT STDMETHODCALLTYPE CExplorerBand::ContextSensitiveHelp(BOOL fEnterMode)
494 {
495 UNIMPLEMENTED;
496 return E_NOTIMPL;
497 }
498
499
500 // *** IDockingWindow methods ***
501 HRESULT STDMETHODCALLTYPE CExplorerBand::CloseDW(DWORD dwReserved)
502 {
503 // We do nothing, we don't have anything to save yet
504 TRACE("CloseDW called\n");
505 return S_OK;
506 }
507
508 HRESULT STDMETHODCALLTYPE CExplorerBand::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
509 {
510 /* Must return E_NOTIMPL according to MSDN */
511 return E_NOTIMPL;
512 }
513
514 HRESULT STDMETHODCALLTYPE CExplorerBand::ShowDW(BOOL fShow)
515 {
516 fVisible = fShow;
517 ShowWindow(fShow);
518 return S_OK;
519 }
520
521
522 // *** IDeskBand methods ***
523 HRESULT STDMETHODCALLTYPE CExplorerBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
524 {
525 if (!pdbi)
526 {
527 return E_INVALIDARG;
528 }
529 this->dwBandID = dwBandID;
530
531 if (pdbi->dwMask & DBIM_MINSIZE)
532 {
533 pdbi->ptMinSize.x = 200;
534 pdbi->ptMinSize.y = 30;
535 }
536
537 if (pdbi->dwMask & DBIM_MAXSIZE)
538 {
539 pdbi->ptMaxSize.y = -1;
540 }
541
542 if (pdbi->dwMask & DBIM_INTEGRAL)
543 {
544 pdbi->ptIntegral.y = 1;
545 }
546
547 if (pdbi->dwMask & DBIM_ACTUAL)
548 {
549 pdbi->ptActual.x = 200;
550 pdbi->ptActual.y = 30;
551 }
552
553 if (pdbi->dwMask & DBIM_TITLE)
554 {
555 lstrcpyW(pdbi->wszTitle, L"Explorer");
556 }
557
558 if (pdbi->dwMask & DBIM_MODEFLAGS)
559 {
560 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
561 }
562
563 if (pdbi->dwMask & DBIM_BKCOLOR)
564 {
565 pdbi->dwMask &= ~DBIM_BKCOLOR;
566 }
567 return S_OK;
568 }
569
570
571 // *** IObjectWithSite methods ***
572 HRESULT STDMETHODCALLTYPE CExplorerBand::SetSite(IUnknown *pUnkSite)
573 {
574 HRESULT hr;
575 HWND parentWnd;
576
577 if (pUnkSite == pSite)
578 return S_OK;
579
580 TRACE("SetSite called \n");
581 if (!pUnkSite)
582 {
583 DestroyExplorerBand();
584 DestroyWindow();
585 m_hWnd = NULL;
586 }
587
588 if (pUnkSite != pSite)
589 {
590 pSite = NULL;
591 }
592
593 if(!pUnkSite)
594 return S_OK;
595
596 hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
597 if (!SUCCEEDED(hr))
598 {
599 ERR("Could not get parent's window ! Status: %08lx\n", hr);
600 return E_INVALIDARG;
601 }
602
603 pSite = pUnkSite;
604
605 if (m_hWnd)
606 {
607 // Change its parent
608 SetParent(parentWnd);
609 }
610 else
611 {
612 HWND wnd = CreateWindow(WC_TREEVIEW, NULL,
613 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TVS_HASLINES | TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_EDITLABELS /* | TVS_SINGLEEXPAND*/ , // remove TVS_SINGLEEXPAND for now since it has strange behaviour
614 0, 0, 0, 0, parentWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
615
616 // Subclass the window
617 SubclassWindow(wnd);
618
619 // Initialize our treeview now
620 InitializeExplorerBand();
621 RegisterDragDrop(m_hWnd, dynamic_cast<IDropTarget*>(this));
622 }
623 return S_OK;
624 }
625
626 HRESULT STDMETHODCALLTYPE CExplorerBand::GetSite(REFIID riid, void **ppvSite)
627 {
628 if (!ppvSite)
629 return E_POINTER;
630 *ppvSite = pSite;
631 return S_OK;
632 }
633
634
635 // *** IOleCommandTarget methods ***
636 HRESULT STDMETHODCALLTYPE CExplorerBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
637 {
638 UNIMPLEMENTED;
639 return E_NOTIMPL;
640 }
641
642 HRESULT STDMETHODCALLTYPE CExplorerBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
643 {
644 UNIMPLEMENTED;
645 return E_NOTIMPL;
646 }
647
648
649 // *** IServiceProvider methods ***
650 HRESULT STDMETHODCALLTYPE CExplorerBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
651 {
652 UNIMPLEMENTED;
653 return E_NOTIMPL;
654 }
655
656
657 // *** IInputObject methods ***
658 HRESULT STDMETHODCALLTYPE CExplorerBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
659 {
660 if (fActivate)
661 {
662 //SetFocus();
663 SetActiveWindow();
664 }
665 // TODO: handle message
666 if(lpMsg)
667 {
668 TranslateMessage(lpMsg);
669 DispatchMessage(lpMsg);
670 }
671 return S_OK;
672 }
673
674 HRESULT STDMETHODCALLTYPE CExplorerBand::HasFocusIO()
675 {
676 return bFocused ? S_OK : S_FALSE;
677 }
678
679 HRESULT STDMETHODCALLTYPE CExplorerBand::TranslateAcceleratorIO(LPMSG lpMsg)
680 {
681 TranslateMessage(lpMsg);
682 DispatchMessage(lpMsg);
683 return S_OK;
684 }
685
686
687 // *** IPersist methods ***
688 HRESULT STDMETHODCALLTYPE CExplorerBand::GetClassID(CLSID *pClassID)
689 {
690 if (!pClassID)
691 return E_POINTER;
692 memcpy(pClassID, &CLSID_ExplorerBand, sizeof(CLSID));
693 return S_OK;
694 }
695
696
697 // *** IPersistStream methods ***
698 HRESULT STDMETHODCALLTYPE CExplorerBand::IsDirty()
699 {
700 UNIMPLEMENTED;
701 return E_NOTIMPL;
702 }
703
704 HRESULT STDMETHODCALLTYPE CExplorerBand::Load(IStream *pStm)
705 {
706 UNIMPLEMENTED;
707 return E_NOTIMPL;
708 }
709
710 HRESULT STDMETHODCALLTYPE CExplorerBand::Save(IStream *pStm, BOOL fClearDirty)
711 {
712 UNIMPLEMENTED;
713 return E_NOTIMPL;
714 }
715
716 HRESULT STDMETHODCALLTYPE CExplorerBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
717 {
718 UNIMPLEMENTED;
719 return E_NOTIMPL;
720 }
721
722
723 // *** IWinEventHandler methods ***
724 HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
725 {
726 if (uMsg == WM_NOTIFY)
727 {
728 NMHDR *pNotifyHeader = (NMHDR*)lParam;
729 switch (pNotifyHeader->code)
730 {
731 case TVN_ITEMEXPANDING:
732 *theResult = OnTreeItemExpanding((LPNMTREEVIEW)lParam);
733 break;
734 case TVN_SELCHANGED:
735 OnSelectionChanged((LPNMTREEVIEW)lParam);
736 break;
737 default:
738 break;
739 }
740 }
741 return S_OK;
742 }
743
744 HRESULT STDMETHODCALLTYPE CExplorerBand::IsWindowOwner(HWND hWnd)
745 {
746 return (hWnd == m_hWnd) ? S_OK : S_FALSE;
747 }
748
749 // *** IBandNavigate methods ***
750 HRESULT STDMETHODCALLTYPE CExplorerBand::Select(long paramC)
751 {
752 UNIMPLEMENTED;
753 return E_NOTIMPL;
754 }
755
756 // *** INamespaceProxy ***
757 HRESULT STDMETHODCALLTYPE CExplorerBand::GetNavigateTarget(long paramC, long param10, long param14)
758 {
759 UNIMPLEMENTED;
760 return E_NOTIMPL;
761 }
762
763 HRESULT STDMETHODCALLTYPE CExplorerBand::Invoke(long paramC)
764 {
765 UNIMPLEMENTED;
766 return E_NOTIMPL;
767 }
768
769 HRESULT STDMETHODCALLTYPE CExplorerBand::OnSelectionChanged(long paramC)
770 {
771 UNIMPLEMENTED;
772 return E_NOTIMPL;
773 }
774
775 HRESULT STDMETHODCALLTYPE CExplorerBand::RefreshFlags(long paramC, long param10, long param14)
776 {
777 UNIMPLEMENTED;
778 return E_NOTIMPL;
779 }
780
781 HRESULT STDMETHODCALLTYPE CExplorerBand::CacheItem(long paramC)
782 {
783 UNIMPLEMENTED;
784 return E_NOTIMPL;
785 }
786
787 // *** IDispatch methods ***
788 HRESULT STDMETHODCALLTYPE CExplorerBand::GetTypeInfoCount(UINT *pctinfo)
789 {
790 UNIMPLEMENTED;
791 return E_NOTIMPL;
792 }
793
794 HRESULT STDMETHODCALLTYPE CExplorerBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
795 {
796 UNIMPLEMENTED;
797 return E_NOTIMPL;
798 }
799
800 HRESULT STDMETHODCALLTYPE CExplorerBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
801 {
802 UNIMPLEMENTED;
803 return E_NOTIMPL;
804 }
805
806 HRESULT STDMETHODCALLTYPE CExplorerBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
807 {
808 switch (dispIdMember)
809 {
810 case DISPID_DOWNLOADCOMPLETE:
811 case DISPID_NAVIGATECOMPLETE2:
812 TRACE("DISPID_NAVIGATECOMPLETE2 received\n");
813 NavigateToCurrentFolder();
814 return S_OK;
815 }
816 TRACE("Unknown dispid requested: %08x\n", dispIdMember);
817 return E_INVALIDARG;
818 }
819
820 // *** IDropTarget methods ***
821 HRESULT STDMETHODCALLTYPE CExplorerBand::DragEnter(IDataObject *pObj, DWORD glfKeyState, POINTL pt, DWORD *pdwEffect)
822 {
823 UNIMPLEMENTED;
824 return E_NOTIMPL;
825 }
826
827 HRESULT STDMETHODCALLTYPE CExplorerBand::DragOver(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect)
828 {
829 UNIMPLEMENTED;
830 return E_NOTIMPL;
831 }
832
833 HRESULT STDMETHODCALLTYPE CExplorerBand::DragLeave()
834 {
835 UNIMPLEMENTED;
836 return E_NOTIMPL;
837 }
838
839 HRESULT STDMETHODCALLTYPE CExplorerBand::Drop(IDataObject *pObj, DWORD glfKeyState, POINTL pt, DWORD *pdwEffect)
840 {
841 UNIMPLEMENTED;
842 return E_NOTIMPL;
843 }
844
845 // *** IDropSource methods ***
846 HRESULT STDMETHODCALLTYPE CExplorerBand::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
847 {
848 UNIMPLEMENTED;
849 return E_NOTIMPL;
850 }
851
852 HRESULT STDMETHODCALLTYPE CExplorerBand::GiveFeedback(DWORD dwEffect)
853 {
854 UNIMPLEMENTED;
855 return E_NOTIMPL;
856 }