2 * NamespaceTreeControl implementation.
4 * Copyright 2010 David Hedberg
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
33 #include "wine/list.h"
34 #include "wine/debug.h"
36 #include "explorerframe_main.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(nstc
);
40 typedef struct nstc_root
{
44 NSTCROOTSTYLE root_style
;
45 IShellItemFilter
*pif
;
50 const INameSpaceTreeControl2Vtbl
*lpVtbl
;
51 const IOleWindowVtbl
*lpowVtbl
;
61 INameSpaceTreeControlEvents
*pnstce
;
64 static const DWORD unsupported_styles
=
65 NSTCS_SINGLECLICKEXPAND
| NSTCS_NOREPLACEOPEN
| NSTCS_NOORDERSTREAM
| NSTCS_FAVORITESMODE
|
66 NSTCS_EMPTYTEXT
| NSTCS_ALLOWJUNCTIONS
| NSTCS_SHOWTABSBUTTON
| NSTCS_SHOWDELETEBUTTON
|
67 NSTCS_SHOWREFRESHBUTTON
| NSTCS_SPRINGEXPAND
| NSTCS_RICHTOOLTIP
| NSTCS_NOINDENTCHECKS
;
68 static const DWORD unsupported_styles2
=
69 NSTCS2_INTERRUPTNOTIFICATIONS
| NSTCS2_SHOWNULLSPACEMENU
| NSTCS2_DISPLAYPADDING
|
70 NSTCS2_DISPLAYPINNEDONLY
| NTSCS2_NOSINGLETONAUTOEXPAND
| NTSCS2_NEVERINSERTNONENUMERATED
;
72 /*************************************************************************
73 * NamespaceTree event wrappers
75 static HRESULT
events_OnGetDefaultIconIndex(NSTC2Impl
*This
, IShellItem
*psi
,
76 int *piDefaultIcon
, int *piOpenIcon
)
80 if(!This
->pnstce
) return E_NOTIMPL
;
82 refcount
= IShellItem_AddRef(psi
);
83 ret
= INameSpaceTreeControlEvents_OnGetDefaultIconIndex(This
->pnstce
, psi
, piDefaultIcon
, piOpenIcon
);
84 if(IShellItem_Release(psi
) < refcount
- 1)
85 ERR("ShellItem was released by client - please file a bug.\n");
89 static HRESULT
events_OnItemAdded(NSTC2Impl
*This
, IShellItem
*psi
, BOOL fIsRoot
)
93 if(!This
->pnstce
) return S_OK
;
95 refcount
= IShellItem_AddRef(psi
);
96 ret
= INameSpaceTreeControlEvents_OnItemAdded(This
->pnstce
, psi
, fIsRoot
);
97 if(IShellItem_Release(psi
) < refcount
- 1)
98 ERR("ShellItem was released by client - please file a bug.\n");
102 static HRESULT
events_OnItemDeleted(NSTC2Impl
*This
, IShellItem
*psi
, BOOL fIsRoot
)
106 if(!This
->pnstce
) return S_OK
;
108 refcount
= IShellItem_AddRef(psi
);
109 ret
= INameSpaceTreeControlEvents_OnItemDeleted(This
->pnstce
, psi
, fIsRoot
);
110 if(IShellItem_Release(psi
) < refcount
- 1)
111 ERR("ShellItem was released by client - please file a bug.\n");
115 /*************************************************************************
116 * NamespaceTree helper functions
118 static DWORD
treeview_style_from_nstcs(NSTC2Impl
*This
, NSTCSTYLE nstcs
,
119 NSTCSTYLE nstcs_mask
, DWORD
*new_style
)
121 DWORD old_style
, tv_mask
= 0;
122 TRACE("%p, %x, %x, %p\n", This
, nstcs
, nstcs_mask
, new_style
);
125 old_style
= GetWindowLongPtrW(This
->hwnd_tv
, GWL_STYLE
);
127 old_style
= /* The default */
128 WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
129 WS_TABSTOP
| TVS_NOHSCROLL
| TVS_NONEVENHEIGHT
| TVS_INFOTIP
|
130 TVS_EDITLABELS
| TVS_TRACKSELECT
;
132 if(nstcs_mask
& NSTCS_HASEXPANDOS
) tv_mask
|= TVS_HASBUTTONS
;
133 if(nstcs_mask
& NSTCS_HASLINES
) tv_mask
|= TVS_HASLINES
;
134 if(nstcs_mask
& NSTCS_FULLROWSELECT
) tv_mask
|= TVS_FULLROWSELECT
;
135 if(nstcs_mask
& NSTCS_HORIZONTALSCROLL
) tv_mask
|= TVS_NOHSCROLL
;
136 if(nstcs_mask
& NSTCS_ROOTHASEXPANDO
) tv_mask
|= TVS_LINESATROOT
;
137 if(nstcs_mask
& NSTCS_SHOWSELECTIONALWAYS
) tv_mask
|= TVS_SHOWSELALWAYS
;
138 if(nstcs_mask
& NSTCS_NOINFOTIP
) tv_mask
|= TVS_INFOTIP
;
139 if(nstcs_mask
& NSTCS_EVENHEIGHT
) tv_mask
|= TVS_NONEVENHEIGHT
;
140 if(nstcs_mask
& NSTCS_DISABLEDRAGDROP
) tv_mask
|= TVS_DISABLEDRAGDROP
;
141 if(nstcs_mask
& NSTCS_NOEDITLABELS
) tv_mask
|= TVS_EDITLABELS
;
142 if(nstcs_mask
& NSTCS_CHECKBOXES
) tv_mask
|= TVS_CHECKBOXES
;
146 if(nstcs
& NSTCS_HASEXPANDOS
) *new_style
|= TVS_HASBUTTONS
;
147 if(nstcs
& NSTCS_HASLINES
) *new_style
|= TVS_HASLINES
;
148 if(nstcs
& NSTCS_FULLROWSELECT
) *new_style
|= TVS_FULLROWSELECT
;
149 if(!(nstcs
& NSTCS_HORIZONTALSCROLL
)) *new_style
|= TVS_NOHSCROLL
;
150 if(nstcs
& NSTCS_ROOTHASEXPANDO
) *new_style
|= TVS_LINESATROOT
;
151 if(nstcs
& NSTCS_SHOWSELECTIONALWAYS
) *new_style
|= TVS_SHOWSELALWAYS
;
152 if(!(nstcs
& NSTCS_NOINFOTIP
)) *new_style
|= TVS_INFOTIP
;
153 if(!(nstcs
& NSTCS_EVENHEIGHT
)) *new_style
|= TVS_NONEVENHEIGHT
;
154 if(nstcs
& NSTCS_DISABLEDRAGDROP
) *new_style
|= TVS_DISABLEDRAGDROP
;
155 if(!(nstcs
& NSTCS_NOEDITLABELS
)) *new_style
|= TVS_EDITLABELS
;
156 if(nstcs
& NSTCS_CHECKBOXES
) *new_style
|= TVS_CHECKBOXES
;
158 *new_style
= (old_style
& ~tv_mask
) | (*new_style
& tv_mask
);
160 TRACE("old: %08x, new: %08x\n", old_style
, *new_style
);
162 return old_style
^*new_style
;
165 static IShellItem
*shellitem_from_treeitem(NSTC2Impl
*This
, HTREEITEM hitem
)
169 tvi
.mask
= TVIF_PARAM
;
173 SendMessageW(This
->hwnd_tv
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
175 TRACE("ShellItem: %p\n", (void*)tvi
.lParam
);
176 return (IShellItem
*)tvi
.lParam
;
179 static int get_icon(LPCITEMIDLIST lpi
, UINT extra_flags
)
182 UINT flags
= SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
;
183 SHGetFileInfoW((LPCWSTR
)lpi
, 0 ,&sfi
, sizeof(SHFILEINFOW
), flags
| extra_flags
);
187 /* Insert a shellitem into the given place in the tree and return the
188 resulting treeitem. */
189 static HTREEITEM
insert_shellitem(NSTC2Impl
*This
, IShellItem
*psi
,
190 HTREEITEM hParent
, HTREEITEM hInsertAfter
)
192 TVINSERTSTRUCTW tvins
;
193 TVITEMEXW
*tvi
= &tvins
.u
.itemex
;
195 TRACE("%p (%p, %p)\n", psi
, hParent
, hInsertAfter
);
197 tvi
->mask
= TVIF_PARAM
| TVIF_CHILDREN
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_TEXT
;
198 tvi
->cChildren
= I_CHILDRENCALLBACK
;
199 tvi
->iImage
= tvi
->iSelectedImage
= I_IMAGECALLBACK
;
200 tvi
->pszText
= LPSTR_TEXTCALLBACKW
;
202 /* Every treeitem contains a pointer to the corresponding ShellItem. */
203 tvi
->lParam
= (LPARAM
)psi
;
204 tvins
.hParent
= hParent
;
205 tvins
.hInsertAfter
= hInsertAfter
;
207 hinserted
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_INSERTITEMW
, 0,
208 (LPARAM
)(LPTVINSERTSTRUCTW
)&tvins
);
210 IShellItem_AddRef(psi
);
215 /*************************************************************************
216 * NamespaceTree window functions
218 static LRESULT
create_namespacetree(HWND hWnd
, CREATESTRUCTW
*crs
)
220 NSTC2Impl
*This
= crs
->lpCreateParams
;
221 HIMAGELIST ShellSmallIconList
;
222 DWORD treeview_style
, treeview_ex_style
;
224 TRACE("%p (%p)\n", This
, crs
);
225 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LPARAM
)This
);
226 This
->hwnd_main
= hWnd
;
228 treeview_style_from_nstcs(This
, This
->style
, 0xFFFFFFFF, &treeview_style
);
230 This
->hwnd_tv
= CreateWindowExW(0, WC_TREEVIEWW
, NULL
, treeview_style
,
231 0, 0, crs
->cx
, crs
->cy
,
232 hWnd
, NULL
, explorerframe_hinstance
, NULL
);
236 ERR("Failed to create treeview!\n");
237 return HRESULT_FROM_WIN32(GetLastError());
240 treeview_ex_style
= TVS_EX_DRAWIMAGEASYNC
| TVS_EX_RICHTOOLTIP
|
241 TVS_EX_DOUBLEBUFFER
| TVS_EX_NOSINGLECOLLAPSE
;
243 if(This
->style
& NSTCS_AUTOHSCROLL
)
244 treeview_ex_style
|= TVS_EX_AUTOHSCROLL
;
245 if(This
->style
& NSTCS_FADEINOUTEXPANDOS
)
246 treeview_ex_style
|= TVS_EX_FADEINOUTEXPANDOS
;
247 if(This
->style
& NSTCS_PARTIALCHECKBOXES
)
248 treeview_ex_style
|= TVS_EX_PARTIALCHECKBOXES
;
249 if(This
->style
& NSTCS_EXCLUSIONCHECKBOXES
)
250 treeview_ex_style
|= TVS_EX_EXCLUSIONCHECKBOXES
;
251 if(This
->style
& NSTCS_DIMMEDCHECKBOXES
)
252 treeview_ex_style
|= TVS_EX_DIMMEDCHECKBOXES
;
254 SendMessageW(This
->hwnd_tv
, TVM_SETEXTENDEDSTYLE
, treeview_ex_style
, 0xffff);
256 if(Shell_GetImageLists(NULL
, &ShellSmallIconList
))
258 SendMessageW(This
->hwnd_tv
, TVM_SETIMAGELIST
,
259 (WPARAM
)TVSIL_NORMAL
, (LPARAM
)ShellSmallIconList
);
263 ERR("Failed to get the System Image List.\n");
266 INameSpaceTreeControl_AddRef((INameSpaceTreeControl
*)This
);
271 static LRESULT
resize_namespacetree(NSTC2Impl
*This
)
276 GetClientRect(This
->hwnd_main
, &rc
);
277 MoveWindow(This
->hwnd_tv
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, TRUE
);
282 static LRESULT
destroy_namespacetree(NSTC2Impl
*This
)
286 INameSpaceTreeControl_RemoveAllRoots((INameSpaceTreeControl
*)This
);
288 /* This reference was added in create_namespacetree */
289 INameSpaceTreeControl_Release((INameSpaceTreeControl
*)This
);
293 static LRESULT
on_tvn_deleteitemw(NSTC2Impl
*This
, LPARAM lParam
)
295 NMTREEVIEWW
*nmtv
= (NMTREEVIEWW
*)lParam
;
298 IShellItem_Release((IShellItem
*)nmtv
->itemOld
.lParam
);
302 static LRESULT
on_tvn_getdispinfow(NSTC2Impl
*This
, LPARAM lParam
)
304 NMTVDISPINFOW
*dispinfo
= (NMTVDISPINFOW
*)lParam
;
305 TVITEMEXW
*item
= (TVITEMEXW
*)&dispinfo
->item
;
306 IShellItem
*psi
= shellitem_from_treeitem(This
, item
->hItem
);
309 TRACE("%p, %p (mask: %x)\n", This
, dispinfo
, item
->mask
);
311 if(item
->mask
& TVIF_CHILDREN
)
315 hr
= IShellItem_GetAttributes(psi
, SFGAO_HASSUBFOLDER
, &sfgao
);
317 item
->cChildren
= (sfgao
& SFGAO_HASSUBFOLDER
)?1:0;
321 item
->mask
|= TVIF_DI_SETITEM
;
324 if(item
->mask
& (TVIF_IMAGE
|TVIF_SELECTEDIMAGE
))
328 hr
= events_OnGetDefaultIconIndex(This
, psi
, &item
->iImage
, &item
->iSelectedImage
);
331 hr
= SHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
334 item
->iImage
= item
->iSelectedImage
= get_icon(pidl
, 0);
335 item
->mask
|= TVIF_DI_SETITEM
;
339 ERR("Failed to get IDList (%08x).\n", hr
);
343 if(item
->mask
& TVIF_TEXT
)
347 hr
= IShellItem_GetDisplayName(psi
, SIGDN_NORMALDISPLAY
, &display_name
);
350 lstrcpynW(item
->pszText
, display_name
, MAX_PATH
);
351 item
->mask
|= TVIF_DI_SETITEM
;
352 CoTaskMemFree(display_name
);
355 ERR("Failed to get display name (%08x).\n", hr
);
361 static LRESULT CALLBACK
NSTC2_WndProc(HWND hWnd
, UINT uMessage
,
362 WPARAM wParam
, LPARAM lParam
)
364 NSTC2Impl
*This
= (NSTC2Impl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
369 case WM_NCCREATE
: return create_namespacetree(hWnd
, (CREATESTRUCTW
*)lParam
);
370 case WM_SIZE
: return resize_namespacetree(This
);
371 case WM_DESTROY
: return destroy_namespacetree(This
);
373 nmhdr
= (NMHDR
*)lParam
;
376 case TVN_DELETEITEMW
: return on_tvn_deleteitemw(This
, lParam
);
377 case TVN_GETDISPINFOW
: return on_tvn_getdispinfow(This
, lParam
);
381 default: return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
386 /**************************************************************************
387 * INameSpaceTreeControl2 Implementation
389 static HRESULT WINAPI
NSTC2_fnQueryInterface(INameSpaceTreeControl2
* iface
,
393 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
394 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
397 if(IsEqualIID(riid
, &IID_INameSpaceTreeControl2
) ||
398 IsEqualIID(riid
, &IID_INameSpaceTreeControl
) ||
399 IsEqualIID(riid
, &IID_IUnknown
))
403 else if(IsEqualIID(riid
, &IID_IOleWindow
))
405 *ppvObject
= &This
->lpowVtbl
;
410 IUnknown_AddRef((IUnknown
*)*ppvObject
);
414 return E_NOINTERFACE
;
417 static ULONG WINAPI
NSTC2_fnAddRef(INameSpaceTreeControl2
* iface
)
419 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
420 LONG ref
= InterlockedIncrement(&This
->ref
);
422 TRACE("%p - ref %d\n", This
, ref
);
427 static ULONG WINAPI
NSTC2_fnRelease(INameSpaceTreeControl2
* iface
)
429 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
430 LONG ref
= InterlockedDecrement(&This
->ref
);
432 TRACE("%p - ref: %d\n", This
, ref
);
437 HeapFree(GetProcessHeap(), 0, This
);
438 EFRAME_UnlockModule();
445 static HRESULT WINAPI
NSTC2_fnInitialize(INameSpaceTreeControl2
* iface
,
448 NSTCSTYLE nstcsFlags
)
450 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
452 DWORD window_style
, window_ex_style
;
454 static const WCHAR NSTC2_CLASS_NAME
[] =
455 {'N','a','m','e','s','p','a','c','e','T','r','e','e',
456 'C','o','n','t','r','o','l',0};
458 TRACE("%p (%p, %p, %x)\n", This
, hwndParent
, prc
, nstcsFlags
);
460 if(nstcsFlags
& unsupported_styles
)
461 FIXME("0x%08x contains the unsupported style(s) 0x%08x\n",
462 nstcsFlags
, nstcsFlags
& unsupported_styles
);
464 This
->style
= nstcsFlags
;
466 if(!GetClassInfoW(explorerframe_hinstance
, NSTC2_CLASS_NAME
, &wc
))
468 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
469 wc
.lpfnWndProc
= NSTC2_WndProc
;
472 wc
.hInstance
= explorerframe_hinstance
;
474 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
475 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
476 wc
.lpszMenuName
= NULL
;
477 wc
.lpszClassName
= NSTC2_CLASS_NAME
;
479 if (!RegisterClassW(&wc
)) return E_FAIL
;
482 /* NSTCS_TABSTOP and NSTCS_BORDER affects the host window */
483 window_style
= WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
|
484 (nstcsFlags
& NSTCS_BORDER
? WS_BORDER
: 0);
485 window_ex_style
= nstcsFlags
& NSTCS_TABSTOP
? WS_EX_CONTROLPARENT
: 0;
490 rc
.left
= rc
.right
= rc
.top
= rc
.bottom
= 0;
492 This
->hwnd_main
= CreateWindowExW(window_ex_style
, NSTC2_CLASS_NAME
, NULL
, window_style
,
493 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
494 hwndParent
, 0, explorerframe_hinstance
, This
);
498 ERR("Failed to create the window.\n");
499 return HRESULT_FROM_WIN32(GetLastError());
505 static HRESULT WINAPI
NSTC2_fnTreeAdvise(INameSpaceTreeControl2
* iface
,
509 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
511 TRACE("%p (%p, %p)\n", This
, punk
, pdwCookie
);
515 /* Only one client supported */
519 hr
= IUnknown_QueryInterface(punk
, &IID_INameSpaceTreeControlEvents
,(void**)&This
->pnstce
);
529 static HRESULT WINAPI
NSTC2_fnTreeUnadvise(INameSpaceTreeControl2
* iface
,
532 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
533 TRACE("%p (%x)\n", This
, dwCookie
);
535 /* The cookie is ignored. */
539 INameSpaceTreeControlEvents_Release(This
->pnstce
);
546 static HRESULT WINAPI
NSTC2_fnInsertRoot(INameSpaceTreeControl2
* iface
,
549 SHCONTF grfEnumFlags
,
550 NSTCROOTSTYLE grfRootStyle
,
551 IShellItemFilter
*pif
)
553 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
555 struct list
*add_after_entry
;
556 HTREEITEM add_after_hitem
;
559 TRACE("%p, %d, %p, %x, %x, %p\n", This
, iIndex
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
561 new_root
= HeapAlloc(GetProcessHeap(), 0, sizeof(nstc_root
));
563 return E_OUTOFMEMORY
;
565 new_root
->psi
= psiRoot
;
566 new_root
->enum_flags
= grfEnumFlags
;
567 new_root
->root_style
= grfRootStyle
;
570 /* We want to keep the roots in the internal list and in the
571 * treeview in the same order. */
572 add_after_entry
= &This
->roots
;
573 for(i
= 0; i
< max(0, iIndex
) && list_next(&This
->roots
, add_after_entry
); i
++)
574 add_after_entry
= list_next(&This
->roots
, add_after_entry
);
576 if(add_after_entry
== &This
->roots
)
577 add_after_hitem
= TVI_FIRST
;
579 add_after_hitem
= LIST_ENTRY(add_after_entry
, nstc_root
, entry
)->htreeitem
;
581 new_root
->htreeitem
= insert_shellitem(This
, psiRoot
, TVI_ROOT
, add_after_hitem
);
582 if(!new_root
->htreeitem
)
584 WARN("Failed to add the root.\n");
585 HeapFree(GetProcessHeap(), 0, new_root
);
589 list_add_after(add_after_entry
, &new_root
->entry
);
590 events_OnItemAdded(This
, psiRoot
, TRUE
);
592 if(grfRootStyle
& NSTCRS_HIDDEN
)
595 tvi
.mask
= TVIF_STATEEX
;
596 tvi
.uStateEx
= TVIS_EX_FLAT
;
597 tvi
.hItem
= new_root
->htreeitem
;
599 SendMessageW(This
->hwnd_tv
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
602 if(grfRootStyle
& NSTCRS_EXPANDED
)
603 SendMessageW(This
->hwnd_tv
, TVM_EXPAND
, TVE_EXPAND
,
604 (LPARAM
)new_root
->htreeitem
);
609 static HRESULT WINAPI
NSTC2_fnAppendRoot(INameSpaceTreeControl2
* iface
,
611 SHCONTF grfEnumFlags
,
612 NSTCROOTSTYLE grfRootStyle
,
613 IShellItemFilter
*pif
)
615 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
617 TRACE("%p, %p, %x, %x, %p\n",
618 This
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
620 root_count
= list_count(&This
->roots
);
622 return NSTC2_fnInsertRoot(iface
, root_count
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
625 static HRESULT WINAPI
NSTC2_fnRemoveRoot(INameSpaceTreeControl2
* iface
,
628 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
629 nstc_root
*cursor
, *root
= NULL
;
630 TRACE("%p (%p)\n", This
, psiRoot
);
633 return E_NOINTERFACE
;
635 LIST_FOR_EACH_ENTRY(cursor
, &This
->roots
, nstc_root
, entry
)
639 hr
= IShellItem_Compare(psiRoot
, cursor
->psi
, SICHINT_DISPLAY
, &order
);
647 TRACE("root %p\n", root
);
650 SendMessageW(This
->hwnd_tv
, TVM_DELETEITEM
, 0, (LPARAM
)root
->htreeitem
);
651 events_OnItemDeleted(This
, root
->psi
, TRUE
);
652 list_remove(&root
->entry
);
653 HeapFree(GetProcessHeap(), 0, root
);
658 WARN("No matching root found.\n");
663 static HRESULT WINAPI
NSTC2_fnRemoveAllRoots(INameSpaceTreeControl2
* iface
)
665 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
666 nstc_root
*cur1
, *cur2
;
670 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->roots
, nstc_root
, entry
)
672 NSTC2_fnRemoveRoot(iface
, cur1
->psi
);
682 static HRESULT WINAPI
NSTC2_fnGetRootItems(INameSpaceTreeControl2
* iface
,
683 IShellItemArray
**ppsiaRootItems
)
685 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
691 TRACE("%p (%p)\n", This
, ppsiaRootItems
);
693 count
= list_count(&This
->roots
);
698 array
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
*)*count
);
701 LIST_FOR_EACH_ENTRY(root
, &This
->roots
, nstc_root
, entry
)
702 SHGetIDListFromObject((IUnknown
*)root
->psi
, &array
[i
++]);
704 SHGetDesktopFolder(&psf
);
705 hr
= SHCreateShellItemArray(NULL
, psf
, count
, (PCUITEMID_CHILD_ARRAY
)array
,
707 IShellFolder_Release(psf
);
709 for(i
= 0; i
< count
; i
++)
712 HeapFree(GetProcessHeap(), 0, array
);
717 static HRESULT WINAPI
NSTC2_fnSetItemState(INameSpaceTreeControl2
* iface
,
719 NSTCITEMSTATE nstcisMask
,
720 NSTCITEMSTATE nstcisFlags
)
722 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
723 FIXME("stub, %p (%p, %x, %x)\n", This
, psi
, nstcisMask
, nstcisFlags
);
727 static HRESULT WINAPI
NSTC2_fnGetItemState(INameSpaceTreeControl2
* iface
,
729 NSTCITEMSTATE nstcisMask
,
730 NSTCITEMSTATE
*pnstcisFlags
)
732 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
733 FIXME("stub, %p (%p, %x, %p)\n", This
, psi
, nstcisMask
, pnstcisFlags
);
737 static HRESULT WINAPI
NSTC2_fnGetSelectedItems(INameSpaceTreeControl2
* iface
,
738 IShellItemArray
**psiaItems
)
740 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
741 FIXME("stub, %p (%p)\n", This
, psiaItems
);
745 static HRESULT WINAPI
NSTC2_fnGetItemCustomState(INameSpaceTreeControl2
* iface
,
749 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
750 FIXME("stub, %p (%p, %p)\n", This
, psi
, piStateNumber
);
754 static HRESULT WINAPI
NSTC2_fnSetItemCustomState(INameSpaceTreeControl2
* iface
,
758 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
759 FIXME("stub, %p (%p, %d)\n", This
, psi
, iStateNumber
);
763 static HRESULT WINAPI
NSTC2_fnEnsureItemVisible(INameSpaceTreeControl2
* iface
,
766 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
767 FIXME("stub, %p (%p)\n", This
, psi
);
771 static HRESULT WINAPI
NSTC2_fnSetTheme(INameSpaceTreeControl2
* iface
,
774 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
775 FIXME("stub, %p (%p)\n", This
, pszTheme
);
779 static HRESULT WINAPI
NSTC2_fnGetNextItem(INameSpaceTreeControl2
* iface
,
782 IShellItem
**ppsiNext
)
784 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
785 FIXME("stub, %p (%p, %x, %p)\n", This
, psi
, nstcgi
, ppsiNext
);
789 static HRESULT WINAPI
NSTC2_fnHitTest(INameSpaceTreeControl2
* iface
,
791 IShellItem
**ppsiOut
)
793 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
794 FIXME("stub, %p (%p, %p)\n", This
, ppsiOut
, ppt
);
798 static HRESULT WINAPI
NSTC2_fnGetItemRect(INameSpaceTreeControl2
* iface
,
802 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
803 FIXME("stub, %p (%p, %p)\n", This
, psi
, prect
);
807 static HRESULT WINAPI
NSTC2_fnCollapseAll(INameSpaceTreeControl2
* iface
)
809 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
810 FIXME("stub, %p\n", This
);
814 static HRESULT WINAPI
NSTC2_fnSetControlStyle(INameSpaceTreeControl2
* iface
,
816 NSTCSTYLE nstcsStyle
)
818 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
819 static const DWORD tv_style_flags
=
820 NSTCS_HASEXPANDOS
| NSTCS_HASLINES
| NSTCS_FULLROWSELECT
|
821 NSTCS_HORIZONTALSCROLL
| NSTCS_ROOTHASEXPANDO
|
822 NSTCS_SHOWSELECTIONALWAYS
| NSTCS_NOINFOTIP
| NSTCS_EVENHEIGHT
|
823 NSTCS_DISABLEDRAGDROP
| NSTCS_NOEDITLABELS
| NSTCS_CHECKBOXES
;
824 static const DWORD host_style_flags
= NSTCS_TABSTOP
| NSTCS_BORDER
;
825 static const DWORD nstc_flags
=
826 NSTCS_SINGLECLICKEXPAND
| NSTCS_NOREPLACEOPEN
| NSTCS_NOORDERSTREAM
|
827 NSTCS_FAVORITESMODE
| NSTCS_EMPTYTEXT
| NSTCS_ALLOWJUNCTIONS
|
828 NSTCS_SHOWTABSBUTTON
| NSTCS_SHOWDELETEBUTTON
| NSTCS_SHOWREFRESHBUTTON
;
829 TRACE("%p (%x, %x)\n", This
, nstcsMask
, nstcsStyle
);
831 /* Fail if there is an attempt to set an unknown style. */
832 if(nstcsMask
& ~(tv_style_flags
| host_style_flags
| nstc_flags
))
835 if(nstcsMask
& tv_style_flags
)
838 treeview_style_from_nstcs(This
, nstcsStyle
, nstcsMask
, &new_style
);
839 SetWindowLongPtrW(This
->hwnd_tv
, GWL_STYLE
, new_style
);
842 /* Flags affecting the host window */
843 if(nstcsMask
& NSTCS_BORDER
)
845 DWORD new_style
= GetWindowLongPtrW(This
->hwnd_main
, GWL_STYLE
);
846 new_style
&= ~WS_BORDER
;
847 new_style
|= nstcsStyle
& NSTCS_BORDER
? WS_BORDER
: 0;
848 SetWindowLongPtrW(This
->hwnd_main
, GWL_STYLE
, new_style
);
850 if(nstcsMask
& NSTCS_TABSTOP
)
852 DWORD new_style
= GetWindowLongPtrW(This
->hwnd_main
, GWL_EXSTYLE
);
853 new_style
&= ~WS_EX_CONTROLPARENT
;
854 new_style
|= nstcsStyle
& NSTCS_TABSTOP
? WS_EX_CONTROLPARENT
: 0;
855 SetWindowLongPtrW(This
->hwnd_main
, GWL_EXSTYLE
, new_style
);
858 if((nstcsStyle
& nstcsMask
) & unsupported_styles
)
859 FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
860 (nstcsStyle
& nstcsMask
),
861 (nstcsStyle
& nstcsMask
) & unsupported_styles
);
863 This
->style
&= ~nstcsMask
;
864 This
->style
|= (nstcsStyle
& nstcsMask
);
869 static HRESULT WINAPI
NSTC2_fnGetControlStyle(INameSpaceTreeControl2
* iface
,
871 NSTCSTYLE
*pnstcsStyle
)
873 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
874 TRACE("%p (%x, %p)\n", This
, nstcsMask
, pnstcsStyle
);
876 *pnstcsStyle
= (This
->style
& nstcsMask
);
881 static HRESULT WINAPI
NSTC2_fnSetControlStyle2(INameSpaceTreeControl2
* iface
,
882 NSTCSTYLE2 nstcsMask
,
883 NSTCSTYLE2 nstcsStyle
)
885 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
886 TRACE("%p (%x, %x)\n", This
, nstcsMask
, nstcsStyle
);
888 if((nstcsStyle
& nstcsMask
) & unsupported_styles2
)
889 FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
890 (nstcsStyle
& nstcsMask
),
891 (nstcsStyle
& nstcsMask
) & unsupported_styles2
);
893 This
->style2
&= ~nstcsMask
;
894 This
->style2
|= (nstcsStyle
& nstcsMask
);
899 static HRESULT WINAPI
NSTC2_fnGetControlStyle2(INameSpaceTreeControl2
* iface
,
900 NSTCSTYLE2 nstcsMask
,
901 NSTCSTYLE2
*pnstcsStyle
)
903 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
904 TRACE("%p (%x, %p)\n", This
, nstcsMask
, pnstcsStyle
);
906 *pnstcsStyle
= (This
->style2
& nstcsMask
);
911 static const INameSpaceTreeControl2Vtbl vt_INameSpaceTreeControl2
= {
912 NSTC2_fnQueryInterface
,
917 NSTC2_fnTreeUnadvise
,
921 NSTC2_fnRemoveAllRoots
,
922 NSTC2_fnGetRootItems
,
923 NSTC2_fnSetItemState
,
924 NSTC2_fnGetItemState
,
925 NSTC2_fnGetSelectedItems
,
926 NSTC2_fnGetItemCustomState
,
927 NSTC2_fnSetItemCustomState
,
928 NSTC2_fnEnsureItemVisible
,
934 NSTC2_fnSetControlStyle
,
935 NSTC2_fnGetControlStyle
,
936 NSTC2_fnSetControlStyle2
,
937 NSTC2_fnGetControlStyle2
940 /**************************************************************************
941 * IOleWindow Implementation
944 static inline NSTC2Impl
*impl_from_IOleWindow(IOleWindow
*iface
)
946 return (NSTC2Impl
*)((char*)iface
- FIELD_OFFSET(NSTC2Impl
, lpowVtbl
));
949 static HRESULT WINAPI
IOW_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
951 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
953 return NSTC2_fnQueryInterface((INameSpaceTreeControl2
*)This
, riid
, ppvObject
);
956 static ULONG WINAPI
IOW_fnAddRef(IOleWindow
*iface
)
958 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
960 return NSTC2_fnAddRef((INameSpaceTreeControl2
*)This
);
963 static ULONG WINAPI
IOW_fnRelease(IOleWindow
*iface
)
965 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
967 return NSTC2_fnRelease((INameSpaceTreeControl2
*)This
);
970 static HRESULT WINAPI
IOW_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
972 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
973 TRACE("%p (%p)\n", This
, phwnd
);
975 *phwnd
= This
->hwnd_main
;
979 static HRESULT WINAPI
IOW_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMode
)
981 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
982 TRACE("%p (%d)\n", This
, fEnterMode
);
984 /* Not implemented */
988 static const IOleWindowVtbl vt_IOleWindow
= {
989 IOW_fnQueryInterface
,
993 IOW_fnContextSensitiveHelp
996 HRESULT
NamespaceTreeControl_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1001 TRACE ("%p %s %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
1006 return CLASS_E_NOAGGREGATION
;
1008 EFRAME_LockModule();
1010 nstc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(NSTC2Impl
));
1012 nstc
->lpVtbl
= &vt_INameSpaceTreeControl2
;
1013 nstc
->lpowVtbl
= &vt_IOleWindow
;
1015 list_init(&nstc
->roots
);
1017 ret
= INameSpaceTreeControl_QueryInterface((INameSpaceTreeControl
*)nstc
, riid
, ppv
);
1018 INameSpaceTreeControl_Release((INameSpaceTreeControl
*)nstc
);
1020 TRACE("--(%p)\n", ppv
);