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
;
57 WNDPROC tv_oldwndproc
;
63 INameSpaceTreeControlEvents
*pnstce
;
66 static const DWORD unsupported_styles
=
67 NSTCS_SINGLECLICKEXPAND
| NSTCS_NOREPLACEOPEN
| NSTCS_NOORDERSTREAM
| NSTCS_FAVORITESMODE
|
68 NSTCS_EMPTYTEXT
| NSTCS_ALLOWJUNCTIONS
| NSTCS_SHOWTABSBUTTON
| NSTCS_SHOWDELETEBUTTON
|
69 NSTCS_SHOWREFRESHBUTTON
| NSTCS_SPRINGEXPAND
| NSTCS_RICHTOOLTIP
| NSTCS_NOINDENTCHECKS
;
70 static const DWORD unsupported_styles2
=
71 NSTCS2_INTERRUPTNOTIFICATIONS
| NSTCS2_SHOWNULLSPACEMENU
| NSTCS2_DISPLAYPADDING
|
72 NSTCS2_DISPLAYPINNEDONLY
| NTSCS2_NOSINGLETONAUTOEXPAND
| NTSCS2_NEVERINSERTNONENUMERATED
;
74 /* Forward declarations */
75 static LRESULT CALLBACK
tv_wndproc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
);
77 /*************************************************************************
78 * NamespaceTree event wrappers
80 static HRESULT
events_OnGetDefaultIconIndex(NSTC2Impl
*This
, IShellItem
*psi
,
81 int *piDefaultIcon
, int *piOpenIcon
)
85 if(!This
->pnstce
) return E_NOTIMPL
;
87 refcount
= IShellItem_AddRef(psi
);
88 ret
= INameSpaceTreeControlEvents_OnGetDefaultIconIndex(This
->pnstce
, psi
, piDefaultIcon
, piOpenIcon
);
89 if(IShellItem_Release(psi
) < refcount
- 1)
90 ERR("ShellItem was released by client - please file a bug.\n");
94 static HRESULT
events_OnItemAdded(NSTC2Impl
*This
, IShellItem
*psi
, BOOL fIsRoot
)
98 if(!This
->pnstce
) return S_OK
;
100 refcount
= IShellItem_AddRef(psi
);
101 ret
= INameSpaceTreeControlEvents_OnItemAdded(This
->pnstce
, psi
, fIsRoot
);
102 if(IShellItem_Release(psi
) < refcount
- 1)
103 ERR("ShellItem was released by client - please file a bug.\n");
107 static HRESULT
events_OnItemDeleted(NSTC2Impl
*This
, IShellItem
*psi
, BOOL fIsRoot
)
111 if(!This
->pnstce
) return S_OK
;
113 refcount
= IShellItem_AddRef(psi
);
114 ret
= INameSpaceTreeControlEvents_OnItemDeleted(This
->pnstce
, psi
, fIsRoot
);
115 if(IShellItem_Release(psi
) < refcount
- 1)
116 ERR("ShellItem was released by client - please file a bug.\n");
120 static HRESULT
events_OnBeforeExpand(NSTC2Impl
*This
, IShellItem
*psi
)
124 if(!This
->pnstce
) return S_OK
;
126 refcount
= IShellItem_AddRef(psi
);
127 ret
= INameSpaceTreeControlEvents_OnBeforeExpand(This
->pnstce
, psi
);
128 if(IShellItem_Release(psi
) < refcount
- 1)
129 ERR("ShellItem was released by client - please file a bug.\n");
133 static HRESULT
events_OnAfterExpand(NSTC2Impl
*This
, IShellItem
*psi
)
137 if(!This
->pnstce
) return S_OK
;
139 refcount
= IShellItem_AddRef(psi
);
140 ret
= INameSpaceTreeControlEvents_OnAfterExpand(This
->pnstce
, psi
);
141 if(IShellItem_Release(psi
) < refcount
- 1)
142 ERR("ShellItem was released by client - please file a bug.\n");
146 static HRESULT
events_OnItemClick(NSTC2Impl
*This
, IShellItem
*psi
,
147 NSTCEHITTEST nstceHitTest
, NSTCECLICKTYPE nstceClickType
)
151 if(!This
->pnstce
) return S_OK
;
153 refcount
= IShellItem_AddRef(psi
);
154 ret
= INameSpaceTreeControlEvents_OnItemClick(This
->pnstce
, psi
, nstceHitTest
, nstceClickType
);
155 if(IShellItem_Release(psi
) < refcount
- 1)
156 ERR("ShellItem was released by client - please file a bug.\n");
160 static HRESULT
events_OnSelectionChanged(NSTC2Impl
*This
, IShellItemArray
*psia
)
162 if(!This
->pnstce
) return S_OK
;
164 return INameSpaceTreeControlEvents_OnSelectionChanged(This
->pnstce
, psia
);
167 static HRESULT
events_OnKeyboardInput(NSTC2Impl
*This
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
169 if(!This
->pnstce
) return S_OK
;
171 return INameSpaceTreeControlEvents_OnKeyboardInput(This
->pnstce
, uMsg
, wParam
, lParam
);
174 /*************************************************************************
175 * NamespaceTree helper functions
177 static DWORD
treeview_style_from_nstcs(NSTC2Impl
*This
, NSTCSTYLE nstcs
,
178 NSTCSTYLE nstcs_mask
, DWORD
*new_style
)
180 DWORD old_style
, tv_mask
= 0;
181 TRACE("%p, %x, %x, %p\n", This
, nstcs
, nstcs_mask
, new_style
);
184 old_style
= GetWindowLongPtrW(This
->hwnd_tv
, GWL_STYLE
);
186 old_style
= /* The default */
187 WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
188 WS_TABSTOP
| TVS_NOHSCROLL
| TVS_NONEVENHEIGHT
| TVS_INFOTIP
|
189 TVS_EDITLABELS
| TVS_TRACKSELECT
;
191 if(nstcs_mask
& NSTCS_HASEXPANDOS
) tv_mask
|= TVS_HASBUTTONS
;
192 if(nstcs_mask
& NSTCS_HASLINES
) tv_mask
|= TVS_HASLINES
;
193 if(nstcs_mask
& NSTCS_FULLROWSELECT
) tv_mask
|= TVS_FULLROWSELECT
;
194 if(nstcs_mask
& NSTCS_HORIZONTALSCROLL
) tv_mask
|= TVS_NOHSCROLL
;
195 if(nstcs_mask
& NSTCS_ROOTHASEXPANDO
) tv_mask
|= TVS_LINESATROOT
;
196 if(nstcs_mask
& NSTCS_SHOWSELECTIONALWAYS
) tv_mask
|= TVS_SHOWSELALWAYS
;
197 if(nstcs_mask
& NSTCS_NOINFOTIP
) tv_mask
|= TVS_INFOTIP
;
198 if(nstcs_mask
& NSTCS_EVENHEIGHT
) tv_mask
|= TVS_NONEVENHEIGHT
;
199 if(nstcs_mask
& NSTCS_DISABLEDRAGDROP
) tv_mask
|= TVS_DISABLEDRAGDROP
;
200 if(nstcs_mask
& NSTCS_NOEDITLABELS
) tv_mask
|= TVS_EDITLABELS
;
201 if(nstcs_mask
& NSTCS_CHECKBOXES
) tv_mask
|= TVS_CHECKBOXES
;
205 if(nstcs
& NSTCS_HASEXPANDOS
) *new_style
|= TVS_HASBUTTONS
;
206 if(nstcs
& NSTCS_HASLINES
) *new_style
|= TVS_HASLINES
;
207 if(nstcs
& NSTCS_FULLROWSELECT
) *new_style
|= TVS_FULLROWSELECT
;
208 if(!(nstcs
& NSTCS_HORIZONTALSCROLL
)) *new_style
|= TVS_NOHSCROLL
;
209 if(nstcs
& NSTCS_ROOTHASEXPANDO
) *new_style
|= TVS_LINESATROOT
;
210 if(nstcs
& NSTCS_SHOWSELECTIONALWAYS
) *new_style
|= TVS_SHOWSELALWAYS
;
211 if(!(nstcs
& NSTCS_NOINFOTIP
)) *new_style
|= TVS_INFOTIP
;
212 if(!(nstcs
& NSTCS_EVENHEIGHT
)) *new_style
|= TVS_NONEVENHEIGHT
;
213 if(nstcs
& NSTCS_DISABLEDRAGDROP
) *new_style
|= TVS_DISABLEDRAGDROP
;
214 if(!(nstcs
& NSTCS_NOEDITLABELS
)) *new_style
|= TVS_EDITLABELS
;
215 if(nstcs
& NSTCS_CHECKBOXES
) *new_style
|= TVS_CHECKBOXES
;
217 *new_style
= (old_style
& ~tv_mask
) | (*new_style
& tv_mask
);
219 TRACE("old: %08x, new: %08x\n", old_style
, *new_style
);
221 return old_style
^*new_style
;
224 static IShellItem
*shellitem_from_treeitem(NSTC2Impl
*This
, HTREEITEM hitem
)
228 tvi
.mask
= TVIF_PARAM
;
232 SendMessageW(This
->hwnd_tv
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
234 TRACE("ShellItem: %p\n", (void*)tvi
.lParam
);
235 return (IShellItem
*)tvi
.lParam
;
238 /* Returns the root that the given treeitem belongs to. */
239 static nstc_root
*root_for_treeitem(NSTC2Impl
*This
, HTREEITEM hitem
)
241 HTREEITEM tmp
, hroot
= hitem
;
244 /* Work our way up the hierarchy */
245 for(tmp
= hitem
; tmp
!= NULL
; hroot
= tmp
?tmp
:hroot
)
246 tmp
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
, TVGN_PARENT
, (LPARAM
)hroot
);
248 /* Search through the list of roots for a match */
249 LIST_FOR_EACH_ENTRY(root
, &This
->roots
, nstc_root
, entry
)
250 if(root
->htreeitem
== hroot
)
253 TRACE("root is %p\n", root
);
257 /* Find a shellitem in the tree, starting from the given node. */
258 static HTREEITEM
search_for_shellitem(NSTC2Impl
*This
, HTREEITEM node
,
261 IShellItem
*psi_node
;
262 HTREEITEM next
, result
= NULL
;
265 TRACE("%p, %p, %p\n", This
, node
, psi
);
267 /* Check this node */
268 psi_node
= shellitem_from_treeitem(This
, node
);
269 hr
= IShellItem_Compare(psi
, psi_node
, SICHINT_DISPLAY
, &cmpo
);
274 next
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
,
275 TVGN_CHILD
, (LPARAM
)node
);
278 result
= search_for_shellitem(This
, next
, psi
);
279 if(result
) return result
;
282 /* Try our next sibling. */
283 next
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
,
284 TVGN_NEXT
, (LPARAM
)node
);
286 result
= search_for_shellitem(This
, next
, psi
);
291 static HTREEITEM
treeitem_from_shellitem(NSTC2Impl
*This
, IShellItem
*psi
)
294 TRACE("%p, %p\n", This
, psi
);
296 root
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
,
301 return search_for_shellitem(This
, root
, psi
);
304 static int get_icon(LPCITEMIDLIST lpi
, UINT extra_flags
)
307 UINT flags
= SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
;
308 SHGetFileInfoW((LPCWSTR
)lpi
, 0 ,&sfi
, sizeof(SHFILEINFOW
), flags
| extra_flags
);
312 /* Insert a shellitem into the given place in the tree and return the
313 resulting treeitem. */
314 static HTREEITEM
insert_shellitem(NSTC2Impl
*This
, IShellItem
*psi
,
315 HTREEITEM hParent
, HTREEITEM hInsertAfter
)
317 TVINSERTSTRUCTW tvins
;
318 TVITEMEXW
*tvi
= &tvins
.u
.itemex
;
320 TRACE("%p (%p, %p)\n", psi
, hParent
, hInsertAfter
);
322 tvi
->mask
= TVIF_PARAM
| TVIF_CHILDREN
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_TEXT
;
323 tvi
->cChildren
= I_CHILDRENCALLBACK
;
324 tvi
->iImage
= tvi
->iSelectedImage
= I_IMAGECALLBACK
;
325 tvi
->pszText
= LPSTR_TEXTCALLBACKW
;
327 /* Every treeitem contains a pointer to the corresponding ShellItem. */
328 tvi
->lParam
= (LPARAM
)psi
;
329 tvins
.hParent
= hParent
;
330 tvins
.hInsertAfter
= hInsertAfter
;
332 hinserted
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_INSERTITEMW
, 0,
333 (LPARAM
)(LPTVINSERTSTRUCTW
)&tvins
);
335 IShellItem_AddRef(psi
);
340 /* Enumerates the children of the folder represented by hitem
341 * according to the settings for the root, and adds them to the
342 * treeview. Returns the number of children added. */
343 static UINT
fill_sublevel(NSTC2Impl
*This
, HTREEITEM hitem
)
345 IShellItem
*psiParent
= shellitem_from_treeitem(This
, hitem
);
346 nstc_root
*root
= root_for_treeitem(This
, hitem
);
347 LPITEMIDLIST pidl_parent
;
353 hr
= SHGetIDListFromObject((IUnknown
*)psiParent
, &pidl_parent
);
356 hr
= IShellItem_BindToHandler(psiParent
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&psf
);
359 hr
= IShellFolder_EnumObjects(psf
, NULL
, root
->enum_flags
, &peidl
);
366 while( S_OK
== IEnumIDList_Next(peidl
, 1, &pidl
, &fetched
) )
368 hr
= SHCreateShellItem(NULL
, psf
, pidl
, &psi
);
372 if(insert_shellitem(This
, psi
, hitem
, NULL
))
374 events_OnItemAdded(This
, psi
, FALSE
);
378 IShellItem_Release(psi
);
381 ERR("SHCreateShellItem failed with 0x%08x\n", hr
);
383 IEnumIDList_Release(peidl
);
386 ERR("EnumObjects failed with 0x%08x\n", hr
);
388 IShellFolder_Release(psf
);
391 ERR("BindToHandler failed with 0x%08x\n", hr
);
396 ERR("SHGetIDListFromObject failed with 0x%08x\n", hr
);
401 static HTREEITEM
get_selected_treeitem(NSTC2Impl
*This
)
403 return (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
406 static IShellItem
*get_selected_shellitem(NSTC2Impl
*This
)
408 return shellitem_from_treeitem(This
, get_selected_treeitem(This
));
411 static void collapse_all(NSTC2Impl
*This
, HTREEITEM node
)
415 /* Collapse this node first, and then first child/next sibling. */
416 SendMessageW(This
->hwnd_tv
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)node
);
418 next
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)node
);
419 if(next
) collapse_all(This
, next
);
421 next
= (HTREEITEM
)SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
, TVGN_NEXT
, (LPARAM
)node
);
422 if(next
) collapse_all(This
, next
);
425 /*************************************************************************
426 * NamespaceTree window functions
428 static LRESULT
create_namespacetree(HWND hWnd
, CREATESTRUCTW
*crs
)
430 NSTC2Impl
*This
= crs
->lpCreateParams
;
431 HIMAGELIST ShellSmallIconList
;
432 DWORD treeview_style
, treeview_ex_style
;
434 TRACE("%p (%p)\n", This
, crs
);
435 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LPARAM
)This
);
436 This
->hwnd_main
= hWnd
;
438 treeview_style_from_nstcs(This
, This
->style
, 0xFFFFFFFF, &treeview_style
);
440 This
->hwnd_tv
= CreateWindowExW(0, WC_TREEVIEWW
, NULL
, treeview_style
,
441 0, 0, crs
->cx
, crs
->cy
,
442 hWnd
, NULL
, explorerframe_hinstance
, NULL
);
446 ERR("Failed to create treeview!\n");
447 return HRESULT_FROM_WIN32(GetLastError());
450 treeview_ex_style
= TVS_EX_DRAWIMAGEASYNC
| TVS_EX_RICHTOOLTIP
|
451 TVS_EX_DOUBLEBUFFER
| TVS_EX_NOSINGLECOLLAPSE
;
453 if(This
->style
& NSTCS_AUTOHSCROLL
)
454 treeview_ex_style
|= TVS_EX_AUTOHSCROLL
;
455 if(This
->style
& NSTCS_FADEINOUTEXPANDOS
)
456 treeview_ex_style
|= TVS_EX_FADEINOUTEXPANDOS
;
457 if(This
->style
& NSTCS_PARTIALCHECKBOXES
)
458 treeview_ex_style
|= TVS_EX_PARTIALCHECKBOXES
;
459 if(This
->style
& NSTCS_EXCLUSIONCHECKBOXES
)
460 treeview_ex_style
|= TVS_EX_EXCLUSIONCHECKBOXES
;
461 if(This
->style
& NSTCS_DIMMEDCHECKBOXES
)
462 treeview_ex_style
|= TVS_EX_DIMMEDCHECKBOXES
;
464 SendMessageW(This
->hwnd_tv
, TVM_SETEXTENDEDSTYLE
, treeview_ex_style
, 0xffff);
466 if(Shell_GetImageLists(NULL
, &ShellSmallIconList
))
468 SendMessageW(This
->hwnd_tv
, TVM_SETIMAGELIST
,
469 (WPARAM
)TVSIL_NORMAL
, (LPARAM
)ShellSmallIconList
);
473 ERR("Failed to get the System Image List.\n");
476 INameSpaceTreeControl_AddRef((INameSpaceTreeControl
*)This
);
478 /* Subclass the treeview to get the keybord events. */
479 This
->tv_oldwndproc
= (WNDPROC
)SetWindowLongPtrW(This
->hwnd_tv
, GWLP_WNDPROC
,
480 (ULONG_PTR
)tv_wndproc
);
481 if(This
->tv_oldwndproc
)
482 SetPropA(This
->hwnd_tv
, "PROP_THIS", This
);
487 static LRESULT
resize_namespacetree(NSTC2Impl
*This
)
492 GetClientRect(This
->hwnd_main
, &rc
);
493 MoveWindow(This
->hwnd_tv
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, TRUE
);
498 static LRESULT
destroy_namespacetree(NSTC2Impl
*This
)
502 /* Undo the subclassing */
503 if(This
->tv_oldwndproc
)
505 SetWindowLongPtrW(This
->hwnd_tv
, GWLP_WNDPROC
, (ULONG_PTR
)This
->tv_oldwndproc
);
506 RemovePropA(This
->hwnd_tv
, "PROP_THIS");
509 INameSpaceTreeControl_RemoveAllRoots((INameSpaceTreeControl
*)This
);
511 /* This reference was added in create_namespacetree */
512 INameSpaceTreeControl_Release((INameSpaceTreeControl
*)This
);
516 static LRESULT
on_tvn_deleteitemw(NSTC2Impl
*This
, LPARAM lParam
)
518 NMTREEVIEWW
*nmtv
= (NMTREEVIEWW
*)lParam
;
521 IShellItem_Release((IShellItem
*)nmtv
->itemOld
.lParam
);
525 static LRESULT
on_tvn_getdispinfow(NSTC2Impl
*This
, LPARAM lParam
)
527 NMTVDISPINFOW
*dispinfo
= (NMTVDISPINFOW
*)lParam
;
528 TVITEMEXW
*item
= (TVITEMEXW
*)&dispinfo
->item
;
529 IShellItem
*psi
= shellitem_from_treeitem(This
, item
->hItem
);
532 TRACE("%p, %p (mask: %x)\n", This
, dispinfo
, item
->mask
);
534 if(item
->mask
& TVIF_CHILDREN
)
538 hr
= IShellItem_GetAttributes(psi
, SFGAO_HASSUBFOLDER
, &sfgao
);
540 item
->cChildren
= (sfgao
& SFGAO_HASSUBFOLDER
)?1:0;
544 item
->mask
|= TVIF_DI_SETITEM
;
547 if(item
->mask
& (TVIF_IMAGE
|TVIF_SELECTEDIMAGE
))
551 hr
= events_OnGetDefaultIconIndex(This
, psi
, &item
->iImage
, &item
->iSelectedImage
);
554 hr
= SHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
557 item
->iImage
= item
->iSelectedImage
= get_icon(pidl
, 0);
558 item
->mask
|= TVIF_DI_SETITEM
;
562 ERR("Failed to get IDList (%08x).\n", hr
);
566 if(item
->mask
& TVIF_TEXT
)
570 hr
= IShellItem_GetDisplayName(psi
, SIGDN_NORMALDISPLAY
, &display_name
);
573 lstrcpynW(item
->pszText
, display_name
, MAX_PATH
);
574 item
->mask
|= TVIF_DI_SETITEM
;
575 CoTaskMemFree(display_name
);
578 ERR("Failed to get display name (%08x).\n", hr
);
584 static BOOL
treenode_has_subfolders(NSTC2Impl
*This
, HTREEITEM node
)
586 return SendMessageW(This
->hwnd_tv
, TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)node
);
589 static LRESULT
on_tvn_itemexpandingw(NSTC2Impl
*This
, LPARAM lParam
)
591 NMTREEVIEWW
*nmtv
= (NMTREEVIEWW
*)lParam
;
595 psi
= shellitem_from_treeitem(This
, nmtv
->itemNew
.hItem
);
596 events_OnBeforeExpand(This
, psi
);
598 if(!treenode_has_subfolders(This
, nmtv
->itemNew
.hItem
))
600 /* The node has no children, try to find some */
601 if(!fill_sublevel(This
, nmtv
->itemNew
.hItem
))
604 /* Failed to enumerate any children, remove the expando
606 tvi
.hItem
= nmtv
->itemNew
.hItem
;
607 tvi
.mask
= TVIF_CHILDREN
;
609 SendMessageW(This
->hwnd_tv
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
617 static LRESULT
on_tvn_itemexpandedw(NSTC2Impl
*This
, LPARAM lParam
)
619 NMTREEVIEWW
*nmtv
= (NMTREEVIEWW
*)lParam
;
623 psi
= shellitem_from_treeitem(This
, nmtv
->itemNew
.hItem
);
624 events_OnAfterExpand(This
, psi
);
628 static LRESULT
on_tvn_selchangedw(NSTC2Impl
*This
, LPARAM lParam
)
630 NMTREEVIEWW
*nmtv
= (NMTREEVIEWW
*)lParam
;
631 IShellItemArray
*psia
;
636 /* Note: Only supports one selected item. */
637 psi
= shellitem_from_treeitem(This
, nmtv
->itemNew
.hItem
);
638 hr
= SHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
641 events_OnSelectionChanged(This
, psia
);
642 IShellItemArray_Release(psia
);
648 static LRESULT
on_nm_click(NSTC2Impl
*This
, NMHDR
*nmhdr
)
653 TRACE("%p (%p)\n", This
, nmhdr
);
655 GetCursorPos(&tvhit
.pt
);
656 ScreenToClient(This
->hwnd_tv
, &tvhit
.pt
);
657 SendMessageW(This
->hwnd_tv
, TVM_HITTEST
, 0, (LPARAM
)&tvhit
);
659 if(tvhit
.flags
& (TVHT_NOWHERE
|TVHT_ABOVE
|TVHT_BELOW
))
662 /* TVHT_ maps onto the corresponding NSTCEHT_ */
663 psi
= shellitem_from_treeitem(This
, tvhit
.hItem
);
664 hr
= events_OnItemClick(This
, psi
, tvhit
.flags
, NSTCECT_LBUTTON
);
666 /* The expando should not be expanded unless
668 if(tvhit
.flags
== TVHT_ONITEMBUTTON
)
677 static LRESULT
on_wm_mbuttonup(NSTC2Impl
*This
, WPARAM wParam
, LPARAM lParam
)
682 TRACE("%p (%lx, %lx)\n", This
, wParam
, lParam
);
684 tvhit
.pt
.x
= (int)(short)LOWORD(lParam
);
685 tvhit
.pt
.y
= (int)(short)HIWORD(lParam
);
687 SendMessageW(This
->hwnd_tv
, TVM_HITTEST
, 0, (LPARAM
)&tvhit
);
689 /* Seems to generate only ONITEM and ONITEMICON */
690 if( !(tvhit
.flags
& (TVHT_ONITEM
|TVHT_ONITEMICON
)) )
693 psi
= shellitem_from_treeitem(This
, tvhit
.hItem
);
694 hr
= events_OnItemClick(This
, psi
, tvhit
.flags
, NSTCECT_MBUTTON
);
702 static LRESULT
on_kbd_event(NSTC2Impl
*This
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
706 TRACE("%p : %d, %lx, %lx\n", This
, uMsg
, wParam
, lParam
);
708 /* Handled by the client? */
709 if(FAILED(events_OnKeyboardInput(This
, uMsg
, wParam
, lParam
)))
712 if(uMsg
== WM_KEYDOWN
)
717 psi
= get_selected_shellitem(This
);
718 FIXME("Deletion of file requested (shellitem: %p).\n", psi
);
722 hitem
= get_selected_treeitem(This
);
723 SendMessageW(This
->hwnd_tv
, TVM_EDITLABELW
, 0, (LPARAM
)hitem
);
728 /* Let the TreeView handle the key */
732 static LRESULT CALLBACK
tv_wndproc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
734 NSTC2Impl
*This
= (NSTC2Impl
*)GetPropA(hWnd
, "PROP_THIS");
743 if(on_kbd_event(This
, uMessage
, wParam
, lParam
))
747 case WM_MBUTTONUP
: return on_wm_mbuttonup(This
, wParam
, lParam
);
750 /* Pass the message on to the treeview */
751 return CallWindowProcW(This
->tv_oldwndproc
, hWnd
, uMessage
, wParam
, lParam
);
754 static LRESULT CALLBACK
NSTC2_WndProc(HWND hWnd
, UINT uMessage
,
755 WPARAM wParam
, LPARAM lParam
)
757 NSTC2Impl
*This
= (NSTC2Impl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
762 case WM_NCCREATE
: return create_namespacetree(hWnd
, (CREATESTRUCTW
*)lParam
);
763 case WM_SIZE
: return resize_namespacetree(This
);
764 case WM_DESTROY
: return destroy_namespacetree(This
);
766 nmhdr
= (NMHDR
*)lParam
;
769 case NM_CLICK
: return on_nm_click(This
, nmhdr
);
770 case TVN_DELETEITEMW
: return on_tvn_deleteitemw(This
, lParam
);
771 case TVN_GETDISPINFOW
: return on_tvn_getdispinfow(This
, lParam
);
772 case TVN_ITEMEXPANDINGW
: return on_tvn_itemexpandingw(This
, lParam
);
773 case TVN_ITEMEXPANDEDW
: return on_tvn_itemexpandedw(This
, lParam
);
774 case TVN_SELCHANGEDW
: return on_tvn_selchangedw(This
, lParam
);
778 default: return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
783 /**************************************************************************
784 * INameSpaceTreeControl2 Implementation
786 static HRESULT WINAPI
NSTC2_fnQueryInterface(INameSpaceTreeControl2
* iface
,
790 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
791 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
794 if(IsEqualIID(riid
, &IID_INameSpaceTreeControl2
) ||
795 IsEqualIID(riid
, &IID_INameSpaceTreeControl
) ||
796 IsEqualIID(riid
, &IID_IUnknown
))
800 else if(IsEqualIID(riid
, &IID_IOleWindow
))
802 *ppvObject
= &This
->lpowVtbl
;
807 IUnknown_AddRef((IUnknown
*)*ppvObject
);
811 return E_NOINTERFACE
;
814 static ULONG WINAPI
NSTC2_fnAddRef(INameSpaceTreeControl2
* iface
)
816 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
817 LONG ref
= InterlockedIncrement(&This
->ref
);
819 TRACE("%p - ref %d\n", This
, ref
);
824 static ULONG WINAPI
NSTC2_fnRelease(INameSpaceTreeControl2
* iface
)
826 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
827 LONG ref
= InterlockedDecrement(&This
->ref
);
829 TRACE("%p - ref: %d\n", This
, ref
);
834 HeapFree(GetProcessHeap(), 0, This
);
835 EFRAME_UnlockModule();
842 static HRESULT WINAPI
NSTC2_fnInitialize(INameSpaceTreeControl2
* iface
,
845 NSTCSTYLE nstcsFlags
)
847 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
849 DWORD window_style
, window_ex_style
;
851 static const WCHAR NSTC2_CLASS_NAME
[] =
852 {'N','a','m','e','s','p','a','c','e','T','r','e','e',
853 'C','o','n','t','r','o','l',0};
855 TRACE("%p (%p, %p, %x)\n", This
, hwndParent
, prc
, nstcsFlags
);
857 if(nstcsFlags
& unsupported_styles
)
858 FIXME("0x%08x contains the unsupported style(s) 0x%08x\n",
859 nstcsFlags
, nstcsFlags
& unsupported_styles
);
861 This
->style
= nstcsFlags
;
863 if(!GetClassInfoW(explorerframe_hinstance
, NSTC2_CLASS_NAME
, &wc
))
865 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
866 wc
.lpfnWndProc
= NSTC2_WndProc
;
869 wc
.hInstance
= explorerframe_hinstance
;
871 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
872 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
873 wc
.lpszMenuName
= NULL
;
874 wc
.lpszClassName
= NSTC2_CLASS_NAME
;
876 if (!RegisterClassW(&wc
)) return E_FAIL
;
879 /* NSTCS_TABSTOP and NSTCS_BORDER affects the host window */
880 window_style
= WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
|
881 (nstcsFlags
& NSTCS_BORDER
? WS_BORDER
: 0);
882 window_ex_style
= nstcsFlags
& NSTCS_TABSTOP
? WS_EX_CONTROLPARENT
: 0;
887 rc
.left
= rc
.right
= rc
.top
= rc
.bottom
= 0;
889 This
->hwnd_main
= CreateWindowExW(window_ex_style
, NSTC2_CLASS_NAME
, NULL
, window_style
,
890 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
891 hwndParent
, 0, explorerframe_hinstance
, This
);
895 ERR("Failed to create the window.\n");
896 return HRESULT_FROM_WIN32(GetLastError());
902 static HRESULT WINAPI
NSTC2_fnTreeAdvise(INameSpaceTreeControl2
* iface
,
906 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
908 TRACE("%p (%p, %p)\n", This
, punk
, pdwCookie
);
912 /* Only one client supported */
916 hr
= IUnknown_QueryInterface(punk
, &IID_INameSpaceTreeControlEvents
,(void**)&This
->pnstce
);
926 static HRESULT WINAPI
NSTC2_fnTreeUnadvise(INameSpaceTreeControl2
* iface
,
929 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
930 TRACE("%p (%x)\n", This
, dwCookie
);
932 /* The cookie is ignored. */
936 INameSpaceTreeControlEvents_Release(This
->pnstce
);
943 static HRESULT WINAPI
NSTC2_fnInsertRoot(INameSpaceTreeControl2
* iface
,
946 SHCONTF grfEnumFlags
,
947 NSTCROOTSTYLE grfRootStyle
,
948 IShellItemFilter
*pif
)
950 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
952 struct list
*add_after_entry
;
953 HTREEITEM add_after_hitem
;
956 TRACE("%p, %d, %p, %x, %x, %p\n", This
, iIndex
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
958 new_root
= HeapAlloc(GetProcessHeap(), 0, sizeof(nstc_root
));
960 return E_OUTOFMEMORY
;
962 new_root
->psi
= psiRoot
;
963 new_root
->enum_flags
= grfEnumFlags
;
964 new_root
->root_style
= grfRootStyle
;
967 /* We want to keep the roots in the internal list and in the
968 * treeview in the same order. */
969 add_after_entry
= &This
->roots
;
970 for(i
= 0; i
< max(0, iIndex
) && list_next(&This
->roots
, add_after_entry
); i
++)
971 add_after_entry
= list_next(&This
->roots
, add_after_entry
);
973 if(add_after_entry
== &This
->roots
)
974 add_after_hitem
= TVI_FIRST
;
976 add_after_hitem
= LIST_ENTRY(add_after_entry
, nstc_root
, entry
)->htreeitem
;
978 new_root
->htreeitem
= insert_shellitem(This
, psiRoot
, TVI_ROOT
, add_after_hitem
);
979 if(!new_root
->htreeitem
)
981 WARN("Failed to add the root.\n");
982 HeapFree(GetProcessHeap(), 0, new_root
);
986 list_add_after(add_after_entry
, &new_root
->entry
);
987 events_OnItemAdded(This
, psiRoot
, TRUE
);
989 if(grfRootStyle
& NSTCRS_HIDDEN
)
992 tvi
.mask
= TVIF_STATEEX
;
993 tvi
.uStateEx
= TVIS_EX_FLAT
;
994 tvi
.hItem
= new_root
->htreeitem
;
996 SendMessageW(This
->hwnd_tv
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
999 if(grfRootStyle
& NSTCRS_EXPANDED
)
1000 SendMessageW(This
->hwnd_tv
, TVM_EXPAND
, TVE_EXPAND
,
1001 (LPARAM
)new_root
->htreeitem
);
1006 static HRESULT WINAPI
NSTC2_fnAppendRoot(INameSpaceTreeControl2
* iface
,
1007 IShellItem
*psiRoot
,
1008 SHCONTF grfEnumFlags
,
1009 NSTCROOTSTYLE grfRootStyle
,
1010 IShellItemFilter
*pif
)
1012 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1014 TRACE("%p, %p, %x, %x, %p\n",
1015 This
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
1017 root_count
= list_count(&This
->roots
);
1019 return NSTC2_fnInsertRoot(iface
, root_count
, psiRoot
, grfEnumFlags
, grfRootStyle
, pif
);
1022 static HRESULT WINAPI
NSTC2_fnRemoveRoot(INameSpaceTreeControl2
* iface
,
1023 IShellItem
*psiRoot
)
1025 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1026 nstc_root
*cursor
, *root
= NULL
;
1027 TRACE("%p (%p)\n", This
, psiRoot
);
1030 return E_NOINTERFACE
;
1032 LIST_FOR_EACH_ENTRY(cursor
, &This
->roots
, nstc_root
, entry
)
1036 hr
= IShellItem_Compare(psiRoot
, cursor
->psi
, SICHINT_DISPLAY
, &order
);
1044 TRACE("root %p\n", root
);
1047 events_OnItemDeleted(This
, root
->psi
, TRUE
);
1048 SendMessageW(This
->hwnd_tv
, TVM_DELETEITEM
, 0, (LPARAM
)root
->htreeitem
);
1049 list_remove(&root
->entry
);
1050 HeapFree(GetProcessHeap(), 0, root
);
1055 WARN("No matching root found.\n");
1060 static HRESULT WINAPI
NSTC2_fnRemoveAllRoots(INameSpaceTreeControl2
* iface
)
1062 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1063 nstc_root
*cur1
, *cur2
;
1065 TRACE("%p\n", This
);
1067 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->roots
, nstc_root
, entry
)
1069 NSTC2_fnRemoveRoot(iface
, cur1
->psi
);
1076 return E_INVALIDARG
;
1079 static HRESULT WINAPI
NSTC2_fnGetRootItems(INameSpaceTreeControl2
* iface
,
1080 IShellItemArray
**ppsiaRootItems
)
1082 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1084 LPITEMIDLIST
*array
;
1088 TRACE("%p (%p)\n", This
, ppsiaRootItems
);
1090 count
= list_count(&This
->roots
);
1093 return E_INVALIDARG
;
1095 array
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
*)*count
);
1098 LIST_FOR_EACH_ENTRY(root
, &This
->roots
, nstc_root
, entry
)
1099 SHGetIDListFromObject((IUnknown
*)root
->psi
, &array
[i
++]);
1101 SHGetDesktopFolder(&psf
);
1102 hr
= SHCreateShellItemArray(NULL
, psf
, count
, (PCUITEMID_CHILD_ARRAY
)array
,
1104 IShellFolder_Release(psf
);
1106 for(i
= 0; i
< count
; i
++)
1109 HeapFree(GetProcessHeap(), 0, array
);
1114 static HRESULT WINAPI
NSTC2_fnSetItemState(INameSpaceTreeControl2
* iface
,
1116 NSTCITEMSTATE nstcisMask
,
1117 NSTCITEMSTATE nstcisFlags
)
1119 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1123 TRACE("%p (%p, %x, %x)\n", This
, psi
, nstcisMask
, nstcisFlags
);
1125 hitem
= treeitem_from_shellitem(This
, psi
);
1126 if(!hitem
) return E_INVALIDARG
;
1128 /* Passing both NSTCIS_SELECTED and NSTCIS_SELECTEDNOEXPAND results
1129 in two TVM_SETITEMW's */
1130 if((nstcisMask
&nstcisFlags
) & NSTCIS_SELECTED
)
1132 SendMessageW(This
->hwnd_tv
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hitem
);
1133 SendMessageW(This
->hwnd_tv
, TVM_ENSUREVISIBLE
, 0, (LPARAM
)hitem
);
1135 if((nstcisMask
&nstcisFlags
) & NSTCIS_SELECTEDNOEXPAND
)
1137 SendMessageW(This
->hwnd_tv
, TVM_SELECTITEM
, TVGN_CARET
|TVSI_NOSINGLEEXPAND
, (LPARAM
)hitem
);
1140 /* If NSTCIS_EXPANDED is among the flags, the mask is ignored. */
1141 if((nstcisMask
|nstcisFlags
) & NSTCIS_EXPANDED
)
1143 WPARAM arg
= nstcisFlags
&NSTCIS_EXPANDED
? TVE_EXPAND
:TVE_COLLAPSE
;
1144 SendMessageW(This
->hwnd_tv
, TVM_EXPAND
, arg
, (LPARAM
)hitem
);
1147 if(nstcisMask
& NSTCIS_DISABLED
)
1148 tvi
.mask
= TVIF_STATE
| TVIF_STATEEX
;
1149 else if( ((nstcisMask
^nstcisFlags
) & (NSTCIS_SELECTED
|NSTCIS_EXPANDED
|NSTCIS_SELECTEDNOEXPAND
)) ||
1150 ((nstcisMask
|nstcisFlags
) & NSTCIS_BOLD
) ||
1151 (nstcisFlags
& NSTCIS_DISABLED
) )
1152 tvi
.mask
= TVIF_STATE
;
1158 tvi
.stateMask
= tvi
.state
= 0;
1159 tvi
.stateMask
|= ((nstcisFlags
^nstcisMask
)&NSTCIS_SELECTED
) ? TVIS_SELECTED
: 0;
1160 tvi
.stateMask
|= (nstcisMask
|nstcisFlags
)&NSTCIS_BOLD
? TVIS_BOLD
:0;
1161 tvi
.state
|= (nstcisMask
&nstcisFlags
)&NSTCIS_BOLD
? TVIS_BOLD
:0;
1163 if((nstcisMask
&NSTCIS_EXPANDED
)^(nstcisFlags
&NSTCIS_EXPANDED
))
1168 tvi
.uStateEx
= (nstcisFlags
&nstcisMask
)&NSTCIS_DISABLED
?TVIS_EX_DISABLED
:0;
1171 SendMessageW(This
->hwnd_tv
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
1177 static HRESULT WINAPI
NSTC2_fnGetItemState(INameSpaceTreeControl2
* iface
,
1179 NSTCITEMSTATE nstcisMask
,
1180 NSTCITEMSTATE
*pnstcisFlags
)
1182 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1185 TRACE("%p (%p, %x, %p)\n", This
, psi
, nstcisMask
, pnstcisFlags
);
1187 hitem
= treeitem_from_shellitem(This
, psi
);
1189 return E_INVALIDARG
;
1194 tvi
.mask
= TVIF_STATE
;
1195 tvi
.stateMask
= TVIS_SELECTED
|TVIS_EXPANDED
|TVIS_BOLD
;
1197 if(nstcisMask
& NSTCIS_DISABLED
)
1198 tvi
.mask
|= TVIF_STATEEX
;
1200 SendMessageW(This
->hwnd_tv
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
1201 *pnstcisFlags
|= (tvi
.state
& TVIS_SELECTED
)?NSTCIS_SELECTED
:0;
1202 *pnstcisFlags
|= (tvi
.state
& TVIS_EXPANDED
)?NSTCIS_EXPANDED
:0;
1203 *pnstcisFlags
|= (tvi
.state
& TVIS_BOLD
)?NSTCIS_BOLD
:0;
1204 *pnstcisFlags
|= (tvi
.uStateEx
& TVIS_EX_DISABLED
)?NSTCIS_DISABLED
:0;
1206 *pnstcisFlags
&= nstcisMask
;
1211 static HRESULT WINAPI
NSTC2_fnGetSelectedItems(INameSpaceTreeControl2
* iface
,
1212 IShellItemArray
**psiaItems
)
1214 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1215 FIXME("stub, %p (%p)\n", This
, psiaItems
);
1219 static HRESULT WINAPI
NSTC2_fnGetItemCustomState(INameSpaceTreeControl2
* iface
,
1223 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1224 FIXME("stub, %p (%p, %p)\n", This
, psi
, piStateNumber
);
1228 static HRESULT WINAPI
NSTC2_fnSetItemCustomState(INameSpaceTreeControl2
* iface
,
1232 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1233 FIXME("stub, %p (%p, %d)\n", This
, psi
, iStateNumber
);
1237 static HRESULT WINAPI
NSTC2_fnEnsureItemVisible(INameSpaceTreeControl2
* iface
,
1240 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1241 FIXME("stub, %p (%p)\n", This
, psi
);
1245 static HRESULT WINAPI
NSTC2_fnSetTheme(INameSpaceTreeControl2
* iface
,
1248 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1249 FIXME("stub, %p (%p)\n", This
, pszTheme
);
1253 static HRESULT WINAPI
NSTC2_fnGetNextItem(INameSpaceTreeControl2
* iface
,
1256 IShellItem
**ppsiNext
)
1258 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1259 FIXME("stub, %p (%p, %x, %p)\n", This
, psi
, nstcgi
, ppsiNext
);
1263 static HRESULT WINAPI
NSTC2_fnHitTest(INameSpaceTreeControl2
* iface
,
1265 IShellItem
**ppsiOut
)
1267 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1268 FIXME("stub, %p (%p, %p)\n", This
, ppsiOut
, ppt
);
1272 static HRESULT WINAPI
NSTC2_fnGetItemRect(INameSpaceTreeControl2
* iface
,
1276 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1277 FIXME("stub, %p (%p, %p)\n", This
, psi
, prect
);
1281 static HRESULT WINAPI
NSTC2_fnCollapseAll(INameSpaceTreeControl2
* iface
)
1283 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1285 TRACE("%p\n", This
);
1287 LIST_FOR_EACH_ENTRY(root
, &This
->roots
, nstc_root
, entry
)
1288 collapse_all(This
, root
->htreeitem
);
1293 static HRESULT WINAPI
NSTC2_fnSetControlStyle(INameSpaceTreeControl2
* iface
,
1294 NSTCSTYLE nstcsMask
,
1295 NSTCSTYLE nstcsStyle
)
1297 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1298 static const DWORD tv_style_flags
=
1299 NSTCS_HASEXPANDOS
| NSTCS_HASLINES
| NSTCS_FULLROWSELECT
|
1300 NSTCS_HORIZONTALSCROLL
| NSTCS_ROOTHASEXPANDO
|
1301 NSTCS_SHOWSELECTIONALWAYS
| NSTCS_NOINFOTIP
| NSTCS_EVENHEIGHT
|
1302 NSTCS_DISABLEDRAGDROP
| NSTCS_NOEDITLABELS
| NSTCS_CHECKBOXES
;
1303 static const DWORD host_style_flags
= NSTCS_TABSTOP
| NSTCS_BORDER
;
1304 static const DWORD nstc_flags
=
1305 NSTCS_SINGLECLICKEXPAND
| NSTCS_NOREPLACEOPEN
| NSTCS_NOORDERSTREAM
|
1306 NSTCS_FAVORITESMODE
| NSTCS_EMPTYTEXT
| NSTCS_ALLOWJUNCTIONS
|
1307 NSTCS_SHOWTABSBUTTON
| NSTCS_SHOWDELETEBUTTON
| NSTCS_SHOWREFRESHBUTTON
;
1308 TRACE("%p (%x, %x)\n", This
, nstcsMask
, nstcsStyle
);
1310 /* Fail if there is an attempt to set an unknown style. */
1311 if(nstcsMask
& ~(tv_style_flags
| host_style_flags
| nstc_flags
))
1314 if(nstcsMask
& tv_style_flags
)
1317 treeview_style_from_nstcs(This
, nstcsStyle
, nstcsMask
, &new_style
);
1318 SetWindowLongPtrW(This
->hwnd_tv
, GWL_STYLE
, new_style
);
1321 /* Flags affecting the host window */
1322 if(nstcsMask
& NSTCS_BORDER
)
1324 DWORD new_style
= GetWindowLongPtrW(This
->hwnd_main
, GWL_STYLE
);
1325 new_style
&= ~WS_BORDER
;
1326 new_style
|= nstcsStyle
& NSTCS_BORDER
? WS_BORDER
: 0;
1327 SetWindowLongPtrW(This
->hwnd_main
, GWL_STYLE
, new_style
);
1329 if(nstcsMask
& NSTCS_TABSTOP
)
1331 DWORD new_style
= GetWindowLongPtrW(This
->hwnd_main
, GWL_EXSTYLE
);
1332 new_style
&= ~WS_EX_CONTROLPARENT
;
1333 new_style
|= nstcsStyle
& NSTCS_TABSTOP
? WS_EX_CONTROLPARENT
: 0;
1334 SetWindowLongPtrW(This
->hwnd_main
, GWL_EXSTYLE
, new_style
);
1337 if((nstcsStyle
& nstcsMask
) & unsupported_styles
)
1338 FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
1339 (nstcsStyle
& nstcsMask
),
1340 (nstcsStyle
& nstcsMask
) & unsupported_styles
);
1342 This
->style
&= ~nstcsMask
;
1343 This
->style
|= (nstcsStyle
& nstcsMask
);
1348 static HRESULT WINAPI
NSTC2_fnGetControlStyle(INameSpaceTreeControl2
* iface
,
1349 NSTCSTYLE nstcsMask
,
1350 NSTCSTYLE
*pnstcsStyle
)
1352 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1353 TRACE("%p (%x, %p)\n", This
, nstcsMask
, pnstcsStyle
);
1355 *pnstcsStyle
= (This
->style
& nstcsMask
);
1360 static HRESULT WINAPI
NSTC2_fnSetControlStyle2(INameSpaceTreeControl2
* iface
,
1361 NSTCSTYLE2 nstcsMask
,
1362 NSTCSTYLE2 nstcsStyle
)
1364 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1365 TRACE("%p (%x, %x)\n", This
, nstcsMask
, nstcsStyle
);
1367 if((nstcsStyle
& nstcsMask
) & unsupported_styles2
)
1368 FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
1369 (nstcsStyle
& nstcsMask
),
1370 (nstcsStyle
& nstcsMask
) & unsupported_styles2
);
1372 This
->style2
&= ~nstcsMask
;
1373 This
->style2
|= (nstcsStyle
& nstcsMask
);
1378 static HRESULT WINAPI
NSTC2_fnGetControlStyle2(INameSpaceTreeControl2
* iface
,
1379 NSTCSTYLE2 nstcsMask
,
1380 NSTCSTYLE2
*pnstcsStyle
)
1382 NSTC2Impl
*This
= (NSTC2Impl
*)iface
;
1383 TRACE("%p (%x, %p)\n", This
, nstcsMask
, pnstcsStyle
);
1385 *pnstcsStyle
= (This
->style2
& nstcsMask
);
1390 static const INameSpaceTreeControl2Vtbl vt_INameSpaceTreeControl2
= {
1391 NSTC2_fnQueryInterface
,
1396 NSTC2_fnTreeUnadvise
,
1400 NSTC2_fnRemoveAllRoots
,
1401 NSTC2_fnGetRootItems
,
1402 NSTC2_fnSetItemState
,
1403 NSTC2_fnGetItemState
,
1404 NSTC2_fnGetSelectedItems
,
1405 NSTC2_fnGetItemCustomState
,
1406 NSTC2_fnSetItemCustomState
,
1407 NSTC2_fnEnsureItemVisible
,
1409 NSTC2_fnGetNextItem
,
1411 NSTC2_fnGetItemRect
,
1412 NSTC2_fnCollapseAll
,
1413 NSTC2_fnSetControlStyle
,
1414 NSTC2_fnGetControlStyle
,
1415 NSTC2_fnSetControlStyle2
,
1416 NSTC2_fnGetControlStyle2
1419 /**************************************************************************
1420 * IOleWindow Implementation
1423 static inline NSTC2Impl
*impl_from_IOleWindow(IOleWindow
*iface
)
1425 return (NSTC2Impl
*)((char*)iface
- FIELD_OFFSET(NSTC2Impl
, lpowVtbl
));
1428 static HRESULT WINAPI
IOW_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
1430 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
1431 TRACE("%p\n", This
);
1432 return NSTC2_fnQueryInterface((INameSpaceTreeControl2
*)This
, riid
, ppvObject
);
1435 static ULONG WINAPI
IOW_fnAddRef(IOleWindow
*iface
)
1437 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
1438 TRACE("%p\n", This
);
1439 return NSTC2_fnAddRef((INameSpaceTreeControl2
*)This
);
1442 static ULONG WINAPI
IOW_fnRelease(IOleWindow
*iface
)
1444 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
1445 TRACE("%p\n", This
);
1446 return NSTC2_fnRelease((INameSpaceTreeControl2
*)This
);
1449 static HRESULT WINAPI
IOW_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
1451 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
1452 TRACE("%p (%p)\n", This
, phwnd
);
1454 *phwnd
= This
->hwnd_main
;
1458 static HRESULT WINAPI
IOW_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMode
)
1460 NSTC2Impl
*This
= impl_from_IOleWindow(iface
);
1461 TRACE("%p (%d)\n", This
, fEnterMode
);
1463 /* Not implemented */
1467 static const IOleWindowVtbl vt_IOleWindow
= {
1468 IOW_fnQueryInterface
,
1472 IOW_fnContextSensitiveHelp
1475 HRESULT
NamespaceTreeControl_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1480 TRACE ("%p %s %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
1485 return CLASS_E_NOAGGREGATION
;
1487 EFRAME_LockModule();
1489 nstc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(NSTC2Impl
));
1491 nstc
->lpVtbl
= &vt_INameSpaceTreeControl2
;
1492 nstc
->lpowVtbl
= &vt_IOleWindow
;
1494 list_init(&nstc
->roots
);
1496 ret
= INameSpaceTreeControl_QueryInterface((INameSpaceTreeControl
*)nstc
, riid
, ppv
);
1497 INameSpaceTreeControl_Release((INameSpaceTreeControl
*)nstc
);
1499 TRACE("--(%p)\n", ppv
);