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__)
31 CExplorerBand::CExplorerBand() :
32 pSite(NULL
), fVisible(FALSE
), bNavigating(FALSE
), dwBandID(0)
36 CExplorerBand::~CExplorerBand()
40 void CExplorerBand::InitializeExplorerBand()
42 // Init the treeview here
45 CComPtr
<IWebBrowser2
> browserService
;
46 SHChangeNotifyEntry shcne
;
48 hr
= SHGetDesktopFolder(&pDesktop
);
49 if (FAILED_UNEXPECTEDLY(hr
))
52 hr
= SHGetFolderLocation(m_hWnd
, CSIDL_DESKTOP
, NULL
, 0, &pidl
);
53 if (FAILED_UNEXPECTEDLY(hr
))
57 hr
= SHGetImageList(SHIL_SMALL
, IID_PPV_ARG(IImageList
, &piml
));
58 if (FAILED_UNEXPECTEDLY(hr
))
61 TreeView_SetImageList(m_hWnd
, (HIMAGELIST
)piml
, TVSIL_NORMAL
);
63 // Insert the root node
64 hRoot
= InsertItem(0, pDesktop
, pidl
, pidl
, FALSE
);
67 ERR("Failed to create root item\n");
71 NodeInfo
* pNodeInfo
= GetNodeInfo(hRoot
);
74 InsertSubitems(hRoot
, pNodeInfo
);
75 TreeView_Expand(m_hWnd
, hRoot
, TVE_EXPAND
);
77 // Navigate to current folder position
78 NavigateToCurrentFolder();
80 // Register shell notification
82 shcne
.fRecursive
= TRUE
;
83 shellRegID
= SHChangeNotifyRegister(
85 SHCNRF_ShellLevel
| SHCNRF_InterruptLevel
| SHCNRF_RecursiveInterrupt
,
86 SHCNE_DISKEVENTS
| SHCNE_RENAMEFOLDER
| SHCNE_RMDIR
| SHCNE_MKDIR
,
92 ERR("Something went wrong, error %08x\n", GetLastError());
94 // Register browser connection endpoint
95 hr
= IUnknown_QueryService(pSite
, SID_SWebBrowserApp
, IID_PPV_ARG(IWebBrowser2
, &browserService
));
96 if (FAILED_UNEXPECTEDLY(hr
))
99 hr
= AtlAdvise(browserService
, dynamic_cast<IDispatch
*>(this), DIID_DWebBrowserEvents
, &adviseCookie
);
100 if (FAILED_UNEXPECTEDLY(hr
))
106 void CExplorerBand::DestroyExplorerBand()
109 CComPtr
<IWebBrowser2
> browserService
;
111 TRACE("Cleaning up explorer band ...\n");
113 hr
= IUnknown_QueryService(pSite
, SID_SWebBrowserApp
, IID_PPV_ARG(IWebBrowser2
, &browserService
));
114 if (FAILED_UNEXPECTEDLY(hr
))
117 hr
= AtlUnadvise(browserService
, DIID_DWebBrowserEvents
, adviseCookie
);
118 /* Remove all items of the treeview */
119 RevokeDragDrop(m_hWnd
);
120 TreeView_DeleteAllItems(m_hWnd
);
123 TRACE("Cleanup done !\n");
126 CExplorerBand::NodeInfo
* CExplorerBand::GetNodeInfo(HTREEITEM hItem
)
130 tvItem
.mask
= TVIF_PARAM
;
131 tvItem
.hItem
= hItem
;
133 if (!TreeView_GetItem(m_hWnd
, &tvItem
))
136 return reinterpret_cast<NodeInfo
*>(tvItem
.lParam
);
139 HRESULT
CExplorerBand::ExecuteCommand(CComPtr
<IContextMenu
>& menu
, UINT nCmd
)
141 CComPtr
<IOleWindow
> pBrowserOleWnd
;
142 CMINVOKECOMMANDINFO cmi
;
146 hr
= IUnknown_QueryService(pSite
, SID_SShellBrowser
, IID_PPV_ARG(IOleWindow
, &pBrowserOleWnd
));
147 if (FAILED_UNEXPECTEDLY(hr
))
150 hr
= pBrowserOleWnd
->GetWindow(&browserWnd
);
151 if (FAILED_UNEXPECTEDLY(hr
))
154 ZeroMemory(&cmi
, sizeof(cmi
));
155 cmi
.cbSize
= sizeof(cmi
);
156 cmi
.lpVerb
= MAKEINTRESOURCEA(nCmd
);
157 cmi
.hwnd
= browserWnd
;
158 if (GetKeyState(VK_SHIFT
) & 0x8000)
159 cmi
.fMask
|= CMIC_MASK_SHIFT_DOWN
;
160 if (GetKeyState(VK_CONTROL
) & 0x8000)
161 cmi
.fMask
|= CMIC_MASK_CONTROL_DOWN
;
163 return menu
->InvokeCommand(&cmi
);
166 HRESULT
CExplorerBand::UpdateBrowser(LPITEMIDLIST pidlGoto
)
168 CComPtr
<IShellBrowser
> pBrowserService
;
171 hr
= IUnknown_QueryService(pSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IShellBrowser
, &pBrowserService
));
172 if (FAILED_UNEXPECTEDLY(hr
))
175 hr
= pBrowserService
->BrowseObject(pidlGoto
, SBSP_SAMEBROWSER
| SBSP_ABSOLUTE
);
176 if (FAILED_UNEXPECTEDLY(hr
))
182 // *** notifications handling ***
183 BOOL
CExplorerBand::OnTreeItemExpanding(LPNMTREEVIEW pnmtv
)
187 if (pnmtv
->action
== TVE_COLLAPSE
) {
188 if (pnmtv
->itemNew
.hItem
== hRoot
)
190 // Prenvent root from collapsing
191 pnmtv
->itemNew
.mask
|= TVIF_STATE
;
192 pnmtv
->itemNew
.stateMask
|= TVIS_EXPANDED
;
193 pnmtv
->itemNew
.state
&= ~TVIS_EXPANDED
;
194 pnmtv
->action
= TVE_EXPAND
;
198 if (pnmtv
->action
== TVE_EXPAND
) {
199 // Grab our directory PIDL
200 pNodeInfo
= GetNodeInfo(pnmtv
->itemNew
.hItem
);
201 // We have it, let's try
202 if (pNodeInfo
&& !pNodeInfo
->expanded
)
203 if (!InsertSubitems(pnmtv
->itemNew
.hItem
, pNodeInfo
)) {
204 // remove subitem "+" since we failed to add subitems
207 tvItem
.mask
= TVIF_CHILDREN
;
208 tvItem
.hItem
= pnmtv
->itemNew
.hItem
;
209 tvItem
.cChildren
= 0;
211 TreeView_SetItem(m_hWnd
, &tvItem
);
217 void CExplorerBand::OnSelectionChanged(LPNMTREEVIEW pnmtv
)
219 NodeInfo
* pNodeInfo
= GetNodeInfo(pnmtv
->itemNew
.hItem
);
221 /* Prevents navigation if selection is initiated inside the band */
225 UpdateBrowser(pNodeInfo
->absolutePidl
);
229 //TreeView_Expand(m_hWnd, pnmtv->itemNew.hItem, TVE_EXPAND);
233 // *** ATL event handlers ***
234 LRESULT
CExplorerBand::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
241 CComPtr
<IShellFolder
> pFolder
;
242 CComPtr
<IContextMenu
> contextMenu
;
245 LPITEMIDLIST pidlChild
;
248 item
= TreeView_GetSelection(m_hWnd
);
257 if (x
== -1 && y
== -1)
259 // TODO: grab position of tree item and position it correctly
262 info
= GetNodeInfo(item
);
265 ERR("No node data, something has gone wrong !\n");
268 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pFolder
),
269 (LPCITEMIDLIST
*)&pidlChild
);
272 ERR("Can't bind to folder!\n");
275 hr
= pFolder
->GetUIObjectOf(m_hWnd
, 1, (LPCITEMIDLIST
*)&pidlChild
, IID_IContextMenu
,
276 NULL
, reinterpret_cast<void**>(&contextMenu
));
279 ERR("Can't get IContextMenu interface\n");
282 treeMenu
= CreatePopupMenu();
283 hr
= contextMenu
->QueryContextMenu(treeMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
,
287 WARN("Can't get context menu for item\n");
288 DestroyMenu(treeMenu
);
291 uCommand
= TrackPopupMenu(treeMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
| TPM_LEFTBUTTON
| TPM_RIGHTBUTTON
,
292 x
, y
, 0, m_hWnd
, NULL
);
294 ExecuteCommand(contextMenu
, uCommand
);
297 DestroyMenu(treeMenu
);
299 TreeView_SelectItem(m_hWnd
, oldSelected
);
304 LRESULT
CExplorerBand::ContextMenuHack(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
307 if (uMsg
== WM_RBUTTONDOWN
)
310 info
.pt
.x
= LOWORD(lParam
);
311 info
.pt
.y
= HIWORD(lParam
);
312 info
.flags
= TVHT_ONITEM
;
315 // Save the current location
316 oldSelected
= TreeView_GetSelection(m_hWnd
);
318 // Move to the item selected by the treeview (don't change right pane)
319 TreeView_HitTest(m_hWnd
, &info
);
321 TreeView_SelectItem(m_hWnd
, info
.hItem
);
324 return FALSE
; /* let the wndproc process the message */
326 // *** Helper functions ***
327 HTREEITEM
CExplorerBand::InsertItem(HTREEITEM hParent
, IShellFolder
*psfParent
, LPITEMIDLIST pElt
, LPITEMIDLIST pEltRelative
, BOOL bSort
)
329 TV_INSERTSTRUCT tvInsert
;
330 HTREEITEM htiCreated
;
332 /* Get the attributes of the node */
333 SFGAOF attrs
= SFGAO_STREAM
| SFGAO_HASSUBFOLDER
;
334 HRESULT hr
= psfParent
->GetAttributesOf(1, &pEltRelative
, &attrs
);
335 if (FAILED_UNEXPECTEDLY(hr
))
339 if ((attrs
& SFGAO_STREAM
))
341 TRACE("Ignoring stream\n");
345 /* Get the name of the node */
346 WCHAR wszDisplayName
[MAX_PATH
];
347 if (!ILGetDisplayNameEx(psfParent
, pElt
, wszDisplayName
, ILGDN_INFOLDER
))
349 ERR("Failed to get node name\n");
353 /* Get the icon of the node */
354 INT iIcon
= SHMapPIDLToSystemImageListIndex(psfParent
, pEltRelative
, NULL
);
356 NodeInfo
* pChildInfo
= new NodeInfo
;
359 ERR("Failed to allocate NodeInfo\n");
363 // Store our node info
364 pChildInfo
->absolutePidl
= ILClone(pElt
);
365 pChildInfo
->relativePidl
= ILClone(pEltRelative
);
366 pChildInfo
->expanded
= FALSE
;
368 // Set up our treeview template
369 tvInsert
.hParent
= hParent
;
370 tvInsert
.hInsertAfter
= TVI_LAST
;
371 tvInsert
.item
.mask
= TVIF_PARAM
| TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_CHILDREN
;
372 tvInsert
.item
.cchTextMax
= MAX_PATH
;
373 tvInsert
.item
.pszText
= wszDisplayName
;
374 tvInsert
.item
.iImage
= tvInsert
.item
.iSelectedImage
= iIcon
;
375 tvInsert
.item
.cChildren
= (attrs
& SFGAO_HASSUBFOLDER
) ? 1 : 0;
376 tvInsert
.item
.lParam
= (LPARAM
)pChildInfo
;
378 htiCreated
= TreeView_InsertItem(m_hWnd
, &tvInsert
);
383 /* This is the slow version of the above method */
384 HTREEITEM
CExplorerBand::InsertItem(HTREEITEM hParent
, LPITEMIDLIST pElt
, LPITEMIDLIST pEltRelative
, BOOL bSort
)
386 CComPtr
<IShellFolder
> psfFolder
;
387 HRESULT hr
= SHBindToParent(pElt
, IID_PPV_ARG(IShellFolder
, &psfFolder
), NULL
);
388 if (FAILED_UNEXPECTEDLY(hr
))
391 return InsertItem(hParent
, psfFolder
, pElt
, pEltRelative
, bSort
);
394 BOOL
CExplorerBand::InsertSubitems(HTREEITEM hItem
, NodeInfo
*pNodeInfo
)
396 CComPtr
<IEnumIDList
> pEnumIDList
;
397 LPITEMIDLIST pidlSub
;
403 CComPtr
<IShellFolder
> pFolder
;
405 entry
= pNodeInfo
->absolutePidl
;
408 EnumFlags
= SHCONTF_FOLDERS
;
410 hr
= SHGetFolderLocation(m_hWnd
, CSIDL_DESKTOP
, NULL
, 0, &pidlSub
);
413 ERR("Can't get desktop PIDL !\n");
417 if (!pDesktop
->CompareIDs(NULL
, pidlSub
, entry
))
419 // We are the desktop, so use pDesktop as pFolder
424 // Get an IShellFolder of our pidl
425 hr
= pDesktop
->BindToObject(entry
, NULL
, IID_PPV_ARG(IShellFolder
, &pFolder
));
429 ERR("Can't bind folder to desktop !\n");
435 // TODO: handle hidden folders according to settings !
436 EnumFlags
|= SHCONTF_INCLUDEHIDDEN
;
438 // Enum through objects
439 hr
= pFolder
->EnumObjects(NULL
,EnumFlags
,&pEnumIDList
);
441 // avoid broken IShellFolder implementations that return null pointer with success
442 if (!SUCCEEDED(hr
) || !pEnumIDList
)
444 ERR("Can't enum the folder !\n");
448 /* Don't redraw while we add stuff into the tree */
449 SendMessage(WM_SETREDRAW
, FALSE
, 0);
450 while(SUCCEEDED(pEnumIDList
->Next(1, &pidlSub
, &fetched
)) && pidlSub
&& fetched
)
452 LPITEMIDLIST pidlSubComplete
;
453 pidlSubComplete
= ILCombine(entry
, pidlSub
);
455 if (InsertItem(hItem
, pFolder
, pidlSubComplete
, pidlSub
, FALSE
))
457 ILFree(pidlSubComplete
);
460 pNodeInfo
->expanded
= TRUE
;
462 /* Now we can redraw */
463 SendMessage(WM_SETREDRAW
, TRUE
, 0);
465 return (uItemCount
> 0) ? TRUE
: FALSE
;
469 * Navigate to a given PIDL in the treeview, and return matching tree item handle
470 * - dest: The absolute PIDL we should navigate in the treeview
471 * - item: Handle of the tree item matching the PIDL
472 * - bExpand: expand collapsed nodes in order to find the right element
473 * - bInsert: insert the element at the right place if we don't find it
474 * - bSelect: select the item after we found it
476 BOOL
CExplorerBand::NavigateToPIDL(LPITEMIDLIST dest
, HTREEITEM
*item
, BOOL bExpand
, BOOL bInsert
,
484 LPITEMIDLIST relativeChild
;
495 nodeData
= GetNodeInfo(current
);
498 ERR("Something has gone wrong, no data associated to node !\n");
502 // If we found our node, give it back
503 if (!pDesktop
->CompareIDs(0, nodeData
->absolutePidl
, dest
))
506 TreeView_SelectItem(m_hWnd
, current
);
511 // Check if we are a parent of the requested item
512 relativeChild
= ILFindChild(nodeData
->absolutePidl
, dest
);
513 if (relativeChild
!= 0)
515 // Notify treeview we have children
516 tvItem
.mask
= TVIF_CHILDREN
;
517 tvItem
.hItem
= current
;
518 tvItem
.cChildren
= 1;
519 TreeView_SetItem(m_hWnd
, &tvItem
);
521 // If we can expand and the node isn't expanded yet, do it
524 if (!nodeData
->expanded
)
525 InsertSubitems(current
, nodeData
);
526 TreeView_Expand(m_hWnd
, current
, TVE_EXPAND
);
529 // Try to get a child
530 tmp
= TreeView_GetChild(m_hWnd
, current
);
533 // We have a child, let's continue with it
539 if (bInsert
&& nodeData
->expanded
)
541 // Happens when we have to create a subchild inside a child
542 current
= InsertItem(current
, dest
, relativeChild
, TRUE
);
544 // We end up here, without any children, so we found nothing
545 // Tell the parent node it has children
546 ZeroMemory(&tvItem
, sizeof(tvItem
));
552 tmp
= TreeView_GetNextSibling(m_hWnd
, current
);
560 current
= InsertItem(parent
, dest
, ILFindLastID(dest
), TRUE
);
570 BOOL
CExplorerBand::NavigateToCurrentFolder()
572 LPITEMIDLIST explorerPidl
;
573 CComPtr
<IBrowserService
> pBrowserService
;
579 hr
= IUnknown_QueryService(pSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IBrowserService
, &pBrowserService
));
582 ERR("Can't get IBrowserService !\n");
586 hr
= pBrowserService
->GetPidl(&explorerPidl
);
587 if (!SUCCEEDED(hr
) || !explorerPidl
)
589 ERR("Unable to get browser PIDL !\n");
593 /* find PIDL into our explorer */
594 result
= NavigateToPIDL(explorerPidl
, &dummy
, TRUE
, FALSE
, TRUE
);
599 // *** IOleWindow methods ***
600 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetWindow(HWND
*lphwnd
)
608 HRESULT STDMETHODCALLTYPE
CExplorerBand::ContextSensitiveHelp(BOOL fEnterMode
)
615 // *** IDockingWindow methods ***
616 HRESULT STDMETHODCALLTYPE
CExplorerBand::CloseDW(DWORD dwReserved
)
618 // We do nothing, we don't have anything to save yet
619 TRACE("CloseDW called\n");
623 HRESULT STDMETHODCALLTYPE
CExplorerBand::ResizeBorderDW(const RECT
*prcBorder
, IUnknown
*punkToolbarSite
, BOOL fReserved
)
625 /* Must return E_NOTIMPL according to MSDN */
629 HRESULT STDMETHODCALLTYPE
CExplorerBand::ShowDW(BOOL fShow
)
637 // *** IDeskBand methods ***
638 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetBandInfo(DWORD dwBandID
, DWORD dwViewMode
, DESKBANDINFO
*pdbi
)
644 this->dwBandID
= dwBandID
;
646 if (pdbi
->dwMask
& DBIM_MINSIZE
)
648 pdbi
->ptMinSize
.x
= 200;
649 pdbi
->ptMinSize
.y
= 30;
652 if (pdbi
->dwMask
& DBIM_MAXSIZE
)
654 pdbi
->ptMaxSize
.y
= -1;
657 if (pdbi
->dwMask
& DBIM_INTEGRAL
)
659 pdbi
->ptIntegral
.y
= 1;
662 if (pdbi
->dwMask
& DBIM_ACTUAL
)
664 pdbi
->ptActual
.x
= 200;
665 pdbi
->ptActual
.y
= 30;
668 if (pdbi
->dwMask
& DBIM_TITLE
)
670 if (!LoadStringW(_AtlBaseModule
.GetResourceInstance(), IDS_FOLDERSLABEL
, pdbi
->wszTitle
, _countof(pdbi
->wszTitle
)))
671 return HRESULT_FROM_WIN32(GetLastError());
674 if (pdbi
->dwMask
& DBIM_MODEFLAGS
)
676 pdbi
->dwModeFlags
= DBIMF_NORMAL
| DBIMF_VARIABLEHEIGHT
;
679 if (pdbi
->dwMask
& DBIM_BKCOLOR
)
681 pdbi
->dwMask
&= ~DBIM_BKCOLOR
;
687 // *** IObjectWithSite methods ***
688 HRESULT STDMETHODCALLTYPE
CExplorerBand::SetSite(IUnknown
*pUnkSite
)
693 if (pUnkSite
== pSite
)
696 TRACE("SetSite called \n");
699 DestroyExplorerBand();
704 if (pUnkSite
!= pSite
)
712 hr
= IUnknown_GetWindow(pUnkSite
, &parentWnd
);
715 ERR("Could not get parent's window ! Status: %08lx\n", hr
);
724 SetParent(parentWnd
);
728 HWND wnd
= CreateWindow(WC_TREEVIEW
, NULL
,
729 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
730 0, 0, 0, 0, parentWnd
, NULL
, _AtlBaseModule
.GetModuleInstance(), NULL
);
732 // Subclass the window
735 // Initialize our treeview now
736 InitializeExplorerBand();
737 RegisterDragDrop(m_hWnd
, dynamic_cast<IDropTarget
*>(this));
742 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetSite(REFIID riid
, void **ppvSite
)
751 // *** IOleCommandTarget methods ***
752 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
758 HRESULT STDMETHODCALLTYPE
CExplorerBand::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
765 // *** IServiceProvider methods ***
766 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
773 // *** IInputObject methods ***
774 HRESULT STDMETHODCALLTYPE
CExplorerBand::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
781 // TODO: handle message
784 TranslateMessage(lpMsg
);
785 DispatchMessage(lpMsg
);
790 HRESULT STDMETHODCALLTYPE
CExplorerBand::HasFocusIO()
792 return bFocused
? S_OK
: S_FALSE
;
795 HRESULT STDMETHODCALLTYPE
CExplorerBand::TranslateAcceleratorIO(LPMSG lpMsg
)
797 if (lpMsg
->hwnd
== m_hWnd
)
799 TranslateMessage(lpMsg
);
800 DispatchMessage(lpMsg
);
807 // *** IPersist methods ***
808 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetClassID(CLSID
*pClassID
)
812 memcpy(pClassID
, &CLSID_ExplorerBand
, sizeof(CLSID
));
817 // *** IPersistStream methods ***
818 HRESULT STDMETHODCALLTYPE
CExplorerBand::IsDirty()
824 HRESULT STDMETHODCALLTYPE
CExplorerBand::Load(IStream
*pStm
)
830 HRESULT STDMETHODCALLTYPE
CExplorerBand::Save(IStream
*pStm
, BOOL fClearDirty
)
836 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetSizeMax(ULARGE_INTEGER
*pcbSize
)
843 // *** IWinEventHandler methods ***
844 HRESULT STDMETHODCALLTYPE
CExplorerBand::OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
847 if (uMsg
== WM_NOTIFY
)
849 NMHDR
*pNotifyHeader
= (NMHDR
*)lParam
;
850 switch (pNotifyHeader
->code
)
852 case TVN_ITEMEXPANDING
:
853 *theResult
= OnTreeItemExpanding((LPNMTREEVIEW
)lParam
);
856 OnSelectionChanged((LPNMTREEVIEW
)lParam
);
859 OnContextMenu(WM_CONTEXTMENU
, (WPARAM
)m_hWnd
, GetMessagePos(), bHandled
);
862 case TVN_BEGINLABELEDITW
:
864 // TODO: put this in a function ? (mostly copypasta from CDefView)
865 DWORD dwAttr
= SFGAO_CANRENAME
;
866 LPNMTVDISPINFO dispInfo
= (LPNMTVDISPINFO
)lParam
;
867 CComPtr
<IShellFolder
> pParent
;
868 LPCITEMIDLIST pChild
;
872 NodeInfo
*info
= GetNodeInfo(dispInfo
->item
.hItem
);
875 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pParent
), &pChild
);
876 if (!SUCCEEDED(hr
) || !pParent
.p
)
879 hr
= pParent
->GetAttributesOf(1, &pChild
, &dwAttr
);
880 if (SUCCEEDED(hr
) && (dwAttr
& SFGAO_CANRENAME
))
884 case TVN_ENDLABELEDITW
:
886 LPNMTVDISPINFO dispInfo
= (LPNMTVDISPINFO
)lParam
;
887 NodeInfo
*info
= GetNodeInfo(dispInfo
->item
.hItem
);
891 if (dispInfo
->item
.pszText
)
893 LPITEMIDLIST pidlNew
;
894 CComPtr
<IShellFolder
> pParent
;
895 LPCITEMIDLIST pidlChild
;
897 hr
= SHBindToParent(info
->absolutePidl
, IID_PPV_ARG(IShellFolder
, &pParent
), &pidlChild
);
898 if (!SUCCEEDED(hr
) || !pParent
.p
)
901 hr
= pParent
->SetNameOf(0, pidlChild
, dispInfo
->item
.pszText
, SHGDN_INFOLDER
, &pidlNew
);
902 if(SUCCEEDED(hr
) && pidlNew
)
904 CComPtr
<IPersistFolder2
> pPersist
;
905 LPITEMIDLIST pidlParent
, pidlNewAbs
;
907 hr
= pParent
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &pPersist
));
911 hr
= pPersist
->GetCurFolder(&pidlParent
);
914 pidlNewAbs
= ILCombine(pidlParent
, pidlNew
);
916 // Navigate to our new location
917 UpdateBrowser(pidlNewAbs
);
933 HRESULT STDMETHODCALLTYPE
CExplorerBand::IsWindowOwner(HWND hWnd
)
935 return (hWnd
== m_hWnd
) ? S_OK
: S_FALSE
;
938 // *** IBandNavigate methods ***
939 HRESULT STDMETHODCALLTYPE
CExplorerBand::Select(long paramC
)
945 // *** INamespaceProxy ***
946 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetNavigateTarget(long paramC
, long param10
, long param14
)
952 HRESULT STDMETHODCALLTYPE
CExplorerBand::Invoke(long paramC
)
958 HRESULT STDMETHODCALLTYPE
CExplorerBand::OnSelectionChanged(long paramC
)
964 HRESULT STDMETHODCALLTYPE
CExplorerBand::RefreshFlags(long paramC
, long param10
, long param14
)
970 HRESULT STDMETHODCALLTYPE
CExplorerBand::CacheItem(long paramC
)
976 // *** IDispatch methods ***
977 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetTypeInfoCount(UINT
*pctinfo
)
983 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
989 HRESULT STDMETHODCALLTYPE
CExplorerBand::GetIDsOfNames(REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
995 HRESULT STDMETHODCALLTYPE
CExplorerBand::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
997 switch (dispIdMember
)
999 case DISPID_DOWNLOADCOMPLETE
:
1000 case DISPID_NAVIGATECOMPLETE2
:
1001 TRACE("DISPID_NAVIGATECOMPLETE2 received\n");
1002 NavigateToCurrentFolder();
1005 TRACE("Unknown dispid requested: %08x\n", dispIdMember
);
1006 return E_INVALIDARG
;
1009 // *** IDropTarget methods ***
1010 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragEnter(IDataObject
*pObj
, DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1016 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragOver(DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1022 HRESULT STDMETHODCALLTYPE
CExplorerBand::DragLeave()
1028 HRESULT STDMETHODCALLTYPE
CExplorerBand::Drop(IDataObject
*pObj
, DWORD glfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1034 // *** IDropSource methods ***
1035 HRESULT STDMETHODCALLTYPE
CExplorerBand::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
1041 HRESULT STDMETHODCALLTYPE
CExplorerBand::GiveFeedback(DWORD dwEffect
)