4 * Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
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.
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.
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
22 #include <commoncontrols.h>
23 #include <undocshell.h>
28 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
32 HRESULT WINAPI
CExplorerBand_Constructor(REFIID riid
, LPVOID
*ppv
)
34 return ShellObjectCreator
<CExplorerBand
>(riid
, ppv
);
37 CExplorerBand::CExplorerBand() :
38 pSite(NULL
), fVisible(FALSE
), bNavigating(FALSE
), dwBandID(0)
42 CExplorerBand::~CExplorerBand()
46 void CExplorerBand::InitializeExplorerBand()
48 // Init the treeview here
51 CComPtr
<IWebBrowser2
> browserService
;
52 SHChangeNotifyEntry shcne
;
54 hr
= SHGetDesktopFolder(&pDesktop
);
55 if (FAILED_UNEXPECTEDLY(hr
))
58 hr
= SHGetFolderLocation(m_hWnd
, CSIDL_DESKTOP
, NULL
, 0, &pidl
);
59 if (FAILED_UNEXPECTEDLY(hr
))
63 hr
= SHGetImageList(SHIL_SMALL
, IID_PPV_ARG(IImageList
, &piml
));
64 if (FAILED_UNEXPECTEDLY(hr
))
67 TreeView_SetImageList(m_hWnd
, (HIMAGELIST
)piml
, TVSIL_NORMAL
);
69 // Insert the root node
70 hRoot
= InsertItem(0, pDesktop
, pidl
, pidl
, FALSE
);
73 ERR("Failed to create root item\n");
77 NodeInfo
* pNodeInfo
= GetNodeInfo(hRoot
);
80 InsertSubitems(hRoot
, pNodeInfo
);
81 TreeView_Expand(m_hWnd
, hRoot
, TVE_EXPAND
);
83 // Navigate to current folder position
84 NavigateToCurrentFolder();
86 // Register shell notification
88 shcne
.fRecursive
= TRUE
;
89 shellRegID
= SHChangeNotifyRegister(
91 SHCNRF_ShellLevel
| SHCNRF_InterruptLevel
| SHCNRF_RecursiveInterrupt
,
92 SHCNE_DISKEVENTS
| SHCNE_RENAMEFOLDER
| SHCNE_RMDIR
| SHCNE_MKDIR
,
98 ERR("Something went wrong, error %08x\n", GetLastError());
100 // Register browser connection endpoint
101 hr
= IUnknown_QueryService(pSite
, SID_SWebBrowserApp
, IID_PPV_ARG(IWebBrowser2
, &browserService
));
102 if (FAILED_UNEXPECTEDLY(hr
))
105 hr
= AtlAdvise(browserService
, dynamic_cast<IDispatch
*>(this), DIID_DWebBrowserEvents
, &adviseCookie
);
106 if (FAILED_UNEXPECTEDLY(hr
))
112 void CExplorerBand::DestroyExplorerBand()
115 CComPtr
<IWebBrowser2
> browserService
;
117 TRACE("Cleaning up explorer band ...\n");
119 hr
= IUnknown_QueryService(pSite
, SID_SWebBrowserApp
, IID_PPV_ARG(IWebBrowser2
, &browserService
));
120 if (FAILED_UNEXPECTEDLY(hr
))
123 hr
= AtlUnadvise(browserService
, DIID_DWebBrowserEvents
, adviseCookie
);
124 /* Remove all items of the treeview */
125 RevokeDragDrop(m_hWnd
);
126 TreeView_DeleteAllItems(m_hWnd
);
129 TRACE("Cleanup done !\n");
132 CExplorerBand::NodeInfo
* CExplorerBand::GetNodeInfo(HTREEITEM hItem
)
136 tvItem
.mask
= TVIF_PARAM
;
137 tvItem
.hItem
= hItem
;
139 if (!TreeView_GetItem(m_hWnd
, &tvItem
))
142 return reinterpret_cast<NodeInfo
*>(tvItem
.lParam
);
145 HRESULT
CExplorerBand::ExecuteCommand(CComPtr
<IContextMenu
>& menu
, UINT nCmd
)
147 CComPtr
<IOleWindow
> pBrowserOleWnd
;
148 CMINVOKECOMMANDINFO cmi
;
152 hr
= IUnknown_QueryService(pSite
, SID_SShellBrowser
, IID_PPV_ARG(IOleWindow
, &pBrowserOleWnd
));
153 if (FAILED_UNEXPECTEDLY(hr
))
156 hr
= pBrowserOleWnd
->GetWindow(&browserWnd
);
157 if (FAILED_UNEXPECTEDLY(hr
))
160 ZeroMemory(&cmi
, sizeof(cmi
));
161 cmi
.cbSize
= sizeof(cmi
);
162 cmi
.lpVerb
= MAKEINTRESOURCEA(nCmd
);
163 cmi
.hwnd
= browserWnd
;
164 if (GetKeyState(VK_SHIFT
) & 0x8000)
165 cmi
.fMask
|= CMIC_MASK_SHIFT_DOWN
;
166 if (GetKeyState(VK_CONTROL
) & 0x8000)
167 cmi
.fMask
|= CMIC_MASK_CONTROL_DOWN
;
169 return menu
->InvokeCommand(&cmi
);
172 HRESULT
CExplorerBand::UpdateBrowser(LPITEMIDLIST pidlGoto
)
174 CComPtr
<IShellBrowser
> pBrowserService
;
177 hr
= IUnknown_QueryService(pSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IShellBrowser
, &pBrowserService
));
178 if (FAILED_UNEXPECTEDLY(hr
))
181 hr
= pBrowserService
->BrowseObject(pidlGoto
, SBSP_SAMEBROWSER
| SBSP_ABSOLUTE
);
182 if (FAILED_UNEXPECTEDLY(hr
))
188 // *** notifications handling ***
189 BOOL
CExplorerBand::OnTreeItemExpanding(LPNMTREEVIEW pnmtv
)
193 if (pnmtv
->action
== TVE_COLLAPSE
) {
194 if (pnmtv
->itemNew
.hItem
== hRoot
)
196 // Prenvent root from collapsing
197 pnmtv
->itemNew
.mask
|= TVIF_STATE
;
198 pnmtv
->itemNew
.stateMask
|= TVIS_EXPANDED
;
199 pnmtv
->itemNew
.state
&= ~TVIS_EXPANDED
;
200 pnmtv
->action
= TVE_EXPAND
;
204 if (pnmtv
->action
== TVE_EXPAND
) {
205 // Grab our directory PIDL
206 pNodeInfo
= GetNodeInfo(pnmtv
->itemNew
.hItem
);
207 // We have it, let's try
208 if (pNodeInfo
&& !pNodeInfo
->expanded
)
209 if (!InsertSubitems(pnmtv
->itemNew
.hItem
, pNodeInfo
)) {
210 // remove subitem "+" since we failed to add subitems
213 tvItem
.mask
= TVIF_CHILDREN
;
214 tvItem
.hItem
= pnmtv
->itemNew
.hItem
;
215 tvItem
.cChildren
= 0;
217 TreeView_SetItem(m_hWnd
, &tvItem
);
223 void CExplorerBand::OnSelectionChanged(LPNMTREEVIEW pnmtv
)
225 NodeInfo
* pNodeInfo
= GetNodeInfo(pnmtv
->itemNew
.hItem
);
227 /* Prevents navigation if selection is initiated inside the band */
231 UpdateBrowser(pNodeInfo
->absolutePidl
);
235 //TreeView_Expand(m_hWnd, pnmtv->itemNew.hItem, TVE_EXPAND);
239 // *** ATL event handlers ***
240 LRESULT
CExplorerBand::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
247 CComPtr
<IShellFolder
> pFolder
;
248 CComPtr
<IContextMenu
> contextMenu
;
251 LPITEMIDLIST pidlChild
;
254 item
= TreeView_GetSelection(m_hWnd
);
263 if (x
== -1 && y
== -1)
265 // TODO: grab position of tree item and position it correctly
268 info
= GetNodeInfo(item
);
271 ERR("No node data, something has gone wrong !\n");
274 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pFolder
),
275 (LPCITEMIDLIST
*)&pidlChild
);
278 ERR("Can't bind to folder!\n");
281 hr
= pFolder
->GetUIObjectOf(m_hWnd
, 1, (LPCITEMIDLIST
*)&pidlChild
, IID_IContextMenu
,
282 NULL
, reinterpret_cast<void**>(&contextMenu
));
285 ERR("Can't get IContextMenu interface\n");
288 treeMenu
= CreatePopupMenu();
289 hr
= contextMenu
->QueryContextMenu(treeMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
,
293 WARN("Can't get context menu for item\n");
294 DestroyMenu(treeMenu
);
297 uCommand
= TrackPopupMenu(treeMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
| TPM_LEFTBUTTON
| TPM_RIGHTBUTTON
,
298 x
, y
, 0, m_hWnd
, NULL
);
300 ExecuteCommand(contextMenu
, uCommand
);
303 DestroyMenu(treeMenu
);
305 TreeView_SelectItem(m_hWnd
, oldSelected
);
310 LRESULT
CExplorerBand::ContextMenuHack(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
313 if (uMsg
== WM_RBUTTONDOWN
)
316 info
.pt
.x
= LOWORD(lParam
);
317 info
.pt
.y
= HIWORD(lParam
);
318 info
.flags
= TVHT_ONITEM
;
321 // Save the current location
322 oldSelected
= TreeView_GetSelection(m_hWnd
);
324 // Move to the item selected by the treeview (don't change right pane)
325 TreeView_HitTest(m_hWnd
, &info
);
327 TreeView_SelectItem(m_hWnd
, info
.hItem
);
330 return FALSE
; /* let the wndproc process the message */
332 // *** Helper functions ***
333 HTREEITEM
CExplorerBand::InsertItem(HTREEITEM hParent
, IShellFolder
*psfParent
, LPITEMIDLIST pElt
, LPITEMIDLIST pEltRelative
, BOOL bSort
)
335 TV_INSERTSTRUCT tvInsert
;
336 HTREEITEM htiCreated
;
338 /* Get the attributes of the node */
339 SFGAOF attrs
= SFGAO_STREAM
| SFGAO_HASSUBFOLDER
;
340 HRESULT hr
= psfParent
->GetAttributesOf(1, &pEltRelative
, &attrs
);
341 if (FAILED_UNEXPECTEDLY(hr
))
345 if ((attrs
& SFGAO_STREAM
))
347 TRACE("Ignoring stream\n");
351 /* Get the name of the node */
352 WCHAR wszDisplayName
[MAX_PATH
];
353 if (!ILGetDisplayNameEx(psfParent
, pEltRelative
, wszDisplayName
, ILGDN_INFOLDER
))
355 ERR("Failed to get node name\n");
359 /* Get the icon of the node */
360 INT iIcon
= SHMapPIDLToSystemImageListIndex(psfParent
, pEltRelative
, NULL
);
362 NodeInfo
* pChildInfo
= new NodeInfo
;
365 ERR("Failed to allocate NodeInfo\n");
369 // Store our node info
370 pChildInfo
->absolutePidl
= ILClone(pElt
);
371 pChildInfo
->relativePidl
= ILClone(pEltRelative
);
372 pChildInfo
->expanded
= FALSE
;
374 // Set up our treeview template
375 tvInsert
.hParent
= hParent
;
376 tvInsert
.hInsertAfter
= TVI_LAST
;
377 tvInsert
.item
.mask
= TVIF_PARAM
| TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_CHILDREN
;
378 tvInsert
.item
.cchTextMax
= MAX_PATH
;
379 tvInsert
.item
.pszText
= wszDisplayName
;
380 tvInsert
.item
.iImage
= tvInsert
.item
.iSelectedImage
= iIcon
;
381 tvInsert
.item
.cChildren
= (attrs
& SFGAO_HASSUBFOLDER
) ? 1 : 0;
382 tvInsert
.item
.lParam
= (LPARAM
)pChildInfo
;
384 htiCreated
= TreeView_InsertItem(m_hWnd
, &tvInsert
);
389 /* This is the slow version of the above method */
390 HTREEITEM
CExplorerBand::InsertItem(HTREEITEM hParent
, LPITEMIDLIST pElt
, LPITEMIDLIST pEltRelative
, BOOL bSort
)
392 CComPtr
<IShellFolder
> psfFolder
;
393 HRESULT hr
= SHBindToParent(pElt
, IID_PPV_ARG(IShellFolder
, &psfFolder
), NULL
);
394 if (FAILED_UNEXPECTEDLY(hr
))
397 return InsertItem(hParent
, psfFolder
, pElt
, pEltRelative
, bSort
);
400 BOOL
CExplorerBand::InsertSubitems(HTREEITEM hItem
, NodeInfo
*pNodeInfo
)
402 CComPtr
<IEnumIDList
> pEnumIDList
;
403 LPITEMIDLIST pidlSub
;
409 CComPtr
<IShellFolder
> pFolder
;
411 entry
= pNodeInfo
->absolutePidl
;
414 EnumFlags
= SHCONTF_FOLDERS
;
416 hr
= SHGetFolderLocation(m_hWnd
, CSIDL_DESKTOP
, NULL
, 0, &pidlSub
);
419 ERR("Can't get desktop PIDL !\n");
423 if (!pDesktop
->CompareIDs(NULL
, pidlSub
, entry
))
425 // We are the desktop, so use pDesktop as pFolder
430 // Get an IShellFolder of our pidl
431 hr
= pDesktop
->BindToObject(entry
, NULL
, IID_PPV_ARG(IShellFolder
, &pFolder
));
435 ERR("Can't bind folder to desktop !\n");
441 // TODO: handle hidden folders according to settings !
442 EnumFlags
|= SHCONTF_INCLUDEHIDDEN
;
444 // Enum through objects
445 hr
= pFolder
->EnumObjects(NULL
,EnumFlags
,&pEnumIDList
);
447 // avoid broken IShellFolder implementations that return null pointer with success
448 if (!SUCCEEDED(hr
) || !pEnumIDList
)
450 ERR("Can't enum the folder !\n");
454 /* Don't redraw while we add stuff into the tree */
455 SendMessage(WM_SETREDRAW
, FALSE
, 0);
456 while(SUCCEEDED(pEnumIDList
->Next(1, &pidlSub
, &fetched
)) && pidlSub
&& fetched
)
458 LPITEMIDLIST pidlSubComplete
;
459 pidlSubComplete
= ILCombine(entry
, pidlSub
);
461 if (InsertItem(hItem
, pFolder
, pidlSubComplete
, pidlSub
, FALSE
))
463 ILFree(pidlSubComplete
);
466 pNodeInfo
->expanded
= TRUE
;
468 /* Now we can redraw */
469 SendMessage(WM_SETREDRAW
, TRUE
, 0);
471 return (uItemCount
> 0) ? TRUE
: FALSE
;
475 * Navigate to a given PIDL in the treeview, and return matching tree item handle
476 * - dest: The absolute PIDL we should navigate in the treeview
477 * - item: Handle of the tree item matching the PIDL
478 * - bExpand: expand collapsed nodes in order to find the right element
479 * - bInsert: insert the element at the right place if we don't find it
480 * - bSelect: select the item after we found it
482 BOOL
CExplorerBand::NavigateToPIDL(LPITEMIDLIST dest
, HTREEITEM
*item
, BOOL bExpand
, BOOL bInsert
,
490 LPITEMIDLIST relativeChild
;
501 nodeData
= GetNodeInfo(current
);
504 ERR("Something has gone wrong, no data associated to node !\n");
508 // If we found our node, give it back
509 if (!pDesktop
->CompareIDs(0, nodeData
->absolutePidl
, dest
))
512 TreeView_SelectItem(m_hWnd
, current
);
517 // Check if we are a parent of the requested item
518 relativeChild
= ILFindChild(nodeData
->absolutePidl
, dest
);
519 if (relativeChild
!= 0)
521 // Notify treeview we have children
522 tvItem
.mask
= TVIF_CHILDREN
;
523 tvItem
.hItem
= current
;
524 tvItem
.cChildren
= 1;
525 TreeView_SetItem(m_hWnd
, &tvItem
);
527 // If we can expand and the node isn't expanded yet, do it
530 if (!nodeData
->expanded
)
531 InsertSubitems(current
, nodeData
);
532 TreeView_Expand(m_hWnd
, current
, TVE_EXPAND
);
535 // Try to get a child
536 tmp
= TreeView_GetChild(m_hWnd
, current
);
539 // We have a child, let's continue with it
545 if (bInsert
&& nodeData
->expanded
)
547 // Happens when we have to create a subchild inside a child
548 current
= InsertItem(current
, dest
, relativeChild
, TRUE
);
550 // We end up here, without any children, so we found nothing
551 // Tell the parent node it has children
552 ZeroMemory(&tvItem
, sizeof(tvItem
));
558 tmp
= TreeView_GetNextSibling(m_hWnd
, current
);
566 current
= InsertItem(parent
, dest
, ILFindLastID(dest
), TRUE
);
576 BOOL
CExplorerBand::NavigateToCurrentFolder()
578 LPITEMIDLIST explorerPidl
;
579 CComPtr
<IBrowserService
> pBrowserService
;
585 hr
= IUnknown_QueryService(pSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IBrowserService
, &pBrowserService
));
588 ERR("Can't get IBrowserService !\n");
592 hr
= pBrowserService
->GetPidl(&explorerPidl
);
593 if (!SUCCEEDED(hr
) || !explorerPidl
)
595 ERR("Unable to get browser PIDL !\n");
599 /* find PIDL into our explorer */
600 result
= NavigateToPIDL(explorerPidl
, &dummy
, TRUE
, FALSE
, TRUE
);
605 // *** IOleWindow methods ***
606 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetWindow(HWND
*lphwnd
)
614 HRESULT STDMETHODCALLTYPE
CExplorerBand::ContextSensitiveHelp(BOOL fEnterMode
)
621 // *** IDockingWindow methods ***
622 HRESULT STDMETHODCALLTYPE
CExplorerBand::CloseDW(DWORD dwReserved
)
624 // We do nothing, we don't have anything to save yet
625 TRACE("CloseDW called\n");
629 HRESULT STDMETHODCALLTYPE
CExplorerBand::ResizeBorderDW(const RECT
*prcBorder
, IUnknown
*punkToolbarSite
, BOOL fReserved
)
631 /* Must return E_NOTIMPL according to MSDN */
635 HRESULT STDMETHODCALLTYPE
CExplorerBand::ShowDW(BOOL fShow
)
643 // *** IDeskBand methods ***
644 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetBandInfo(DWORD dwBandID
, DWORD dwViewMode
, DESKBANDINFO
*pdbi
)
650 this->dwBandID
= dwBandID
;
652 if (pdbi
->dwMask
& DBIM_MINSIZE
)
654 pdbi
->ptMinSize
.x
= 200;
655 pdbi
->ptMinSize
.y
= 30;
658 if (pdbi
->dwMask
& DBIM_MAXSIZE
)
660 pdbi
->ptMaxSize
.y
= -1;
663 if (pdbi
->dwMask
& DBIM_INTEGRAL
)
665 pdbi
->ptIntegral
.y
= 1;
668 if (pdbi
->dwMask
& DBIM_ACTUAL
)
670 pdbi
->ptActual
.x
= 200;
671 pdbi
->ptActual
.y
= 30;
674 if (pdbi
->dwMask
& DBIM_TITLE
)
676 lstrcpyW(pdbi
->wszTitle
, L
"Explorer");
679 if (pdbi
->dwMask
& DBIM_MODEFLAGS
)
681 pdbi
->dwModeFlags
= DBIMF_NORMAL
| DBIMF_VARIABLEHEIGHT
;
684 if (pdbi
->dwMask
& DBIM_BKCOLOR
)
686 pdbi
->dwMask
&= ~DBIM_BKCOLOR
;
692 // *** IObjectWithSite methods ***
693 HRESULT STDMETHODCALLTYPE
CExplorerBand::SetSite(IUnknown
*pUnkSite
)
698 if (pUnkSite
== pSite
)
701 TRACE("SetSite called \n");
704 DestroyExplorerBand();
709 if (pUnkSite
!= pSite
)
717 hr
= IUnknown_GetWindow(pUnkSite
, &parentWnd
);
720 ERR("Could not get parent's window ! Status: %08lx\n", hr
);
729 SetParent(parentWnd
);
733 HWND wnd
= CreateWindow(WC_TREEVIEW
, NULL
,
734 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
735 0, 0, 0, 0, parentWnd
, NULL
, _AtlBaseModule
.GetModuleInstance(), NULL
);
737 // Subclass the window
740 // Initialize our treeview now
741 InitializeExplorerBand();
742 RegisterDragDrop(m_hWnd
, dynamic_cast<IDropTarget
*>(this));
747 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetSite(REFIID riid
, void **ppvSite
)
756 // *** IOleCommandTarget methods ***
757 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
763 HRESULT STDMETHODCALLTYPE
CExplorerBand::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
770 // *** IServiceProvider methods ***
771 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
778 // *** IInputObject methods ***
779 HRESULT STDMETHODCALLTYPE
CExplorerBand::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
786 // TODO: handle message
789 TranslateMessage(lpMsg
);
790 DispatchMessage(lpMsg
);
795 HRESULT STDMETHODCALLTYPE
CExplorerBand::HasFocusIO()
797 return bFocused
? S_OK
: S_FALSE
;
800 HRESULT STDMETHODCALLTYPE
CExplorerBand::TranslateAcceleratorIO(LPMSG lpMsg
)
802 TranslateMessage(lpMsg
);
803 DispatchMessage(lpMsg
);
808 // *** IPersist methods ***
809 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetClassID(CLSID
*pClassID
)
813 memcpy(pClassID
, &CLSID_ExplorerBand
, sizeof(CLSID
));
818 // *** IPersistStream methods ***
819 HRESULT STDMETHODCALLTYPE
CExplorerBand::IsDirty()
825 HRESULT STDMETHODCALLTYPE
CExplorerBand::Load(IStream
*pStm
)
831 HRESULT STDMETHODCALLTYPE
CExplorerBand::Save(IStream
*pStm
, BOOL fClearDirty
)
837 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetSizeMax(ULARGE_INTEGER
*pcbSize
)
844 // *** IWinEventHandler methods ***
845 HRESULT STDMETHODCALLTYPE
CExplorerBand::OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
848 if (uMsg
== WM_NOTIFY
)
850 NMHDR
*pNotifyHeader
= (NMHDR
*)lParam
;
851 switch (pNotifyHeader
->code
)
853 case TVN_ITEMEXPANDING
:
854 *theResult
= OnTreeItemExpanding((LPNMTREEVIEW
)lParam
);
857 OnSelectionChanged((LPNMTREEVIEW
)lParam
);
860 OnContextMenu(WM_CONTEXTMENU
, (WPARAM
)m_hWnd
, GetMessagePos(), bHandled
);
863 case TVN_BEGINLABELEDITW
:
865 // TODO: put this in a function ? (mostly copypasta from CDefView)
866 DWORD dwAttr
= SFGAO_CANRENAME
;
867 LPNMTVDISPINFO dispInfo
= (LPNMTVDISPINFO
)lParam
;
868 CComPtr
<IShellFolder
> pParent
;
869 LPCITEMIDLIST pChild
;
873 NodeInfo
*info
= GetNodeInfo(dispInfo
->item
.hItem
);
876 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pParent
), &pChild
);
877 if (!SUCCEEDED(hr
) || !pParent
.p
)
880 hr
= pParent
->GetAttributesOf(1, &pChild
, &dwAttr
);
881 if (SUCCEEDED(hr
) && (dwAttr
& SFGAO_CANRENAME
))
885 case TVN_ENDLABELEDITW
:
887 LPNMTVDISPINFO dispInfo
= (LPNMTVDISPINFO
)lParam
;
888 NodeInfo
*info
= GetNodeInfo(dispInfo
->item
.hItem
);
892 if (dispInfo
->item
.pszText
)
894 LPITEMIDLIST pidlNew
;
895 CComPtr
<IShellFolder
> pParent
;
896 LPCITEMIDLIST pidlChild
;
898 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pParent
), &pidlChild
);
899 if (!SUCCEEDED(hr
) || !pParent
.p
)
902 hr
= pParent
->SetNameOf(0, pidlChild
, dispInfo
->item
.pszText
, SHGDN_INFOLDER
, &pidlNew
);
903 if(SUCCEEDED(hr
) && pidlNew
)
905 CComPtr
<IPersistFolder2
> pPersist
;
906 LPITEMIDLIST pidlParent
, pidlNewAbs
;
908 hr
= pParent
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &pPersist
));
912 hr
= pPersist
->GetCurFolder(&pidlParent
);
915 pidlNewAbs
= ILCombine(pidlParent
, pidlNew
);
917 // Navigate to our new location
918 UpdateBrowser(pidlNewAbs
);
934 HRESULT STDMETHODCALLTYPE
CExplorerBand::IsWindowOwner(HWND hWnd
)
936 return (hWnd
== m_hWnd
) ? S_OK
: S_FALSE
;
939 // *** IBandNavigate methods ***
940 HRESULT STDMETHODCALLTYPE
CExplorerBand::Select(long paramC
)
946 // *** INamespaceProxy ***
947 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetNavigateTarget(long paramC
, long param10
, long param14
)
953 HRESULT STDMETHODCALLTYPE
CExplorerBand::Invoke(long paramC
)
959 HRESULT STDMETHODCALLTYPE
CExplorerBand::OnSelectionChanged(long paramC
)
965 HRESULT STDMETHODCALLTYPE
CExplorerBand::RefreshFlags(long paramC
, long param10
, long param14
)
971 HRESULT STDMETHODCALLTYPE
CExplorerBand::CacheItem(long paramC
)
977 // *** IDispatch methods ***
978 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetTypeInfoCount(UINT
*pctinfo
)
984 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
990 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetIDsOfNames(REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
996 HRESULT STDMETHODCALLTYPE
CExplorerBand::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
998 switch (dispIdMember
)
1000 case DISPID_DOWNLOADCOMPLETE
:
1001 case DISPID_NAVIGATECOMPLETE2
:
1002 TRACE("DISPID_NAVIGATECOMPLETE2 received\n");
1003 NavigateToCurrentFolder();
1006 TRACE("Unknown dispid requested: %08x\n", dispIdMember
);
1007 return E_INVALIDARG
;
1010 // *** IDropTarget methods ***
1011 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragEnter(IDataObject
*pObj
, DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1017 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragOver(DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1023 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragLeave()
1029 HRESULT STDMETHODCALLTYPE
CExplorerBand::Drop(IDataObject
*pObj
, DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1035 // *** IDropSource methods ***
1036 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
1042 HRESULT STDMETHODCALLTYPE
CExplorerBand::GiveFeedback(DWORD dwEffect
)