Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4ad1050e
Commit
4ad1050e
authored
Aug 16, 2010
by
David Hedberg
Committed by
Alexandre Julliard
Aug 17, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
explorerframe: Implement expansion of nodes.
parent
6963f372
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
271 additions
and
0 deletions
+271
-0
nstc.c
dlls/explorerframe/nstc.c
+152
-0
nstc.c
dlls/explorerframe/tests/nstc.c
+119
-0
No files found.
dlls/explorerframe/nstc.c
View file @
4ad1050e
...
...
@@ -112,6 +112,32 @@ static HRESULT events_OnItemDeleted(NSTC2Impl *This, IShellItem *psi, BOOL fIsRo
return
ret
;
}
static
HRESULT
events_OnBeforeExpand
(
NSTC2Impl
*
This
,
IShellItem
*
psi
)
{
HRESULT
ret
;
LONG
refcount
;
if
(
!
This
->
pnstce
)
return
S_OK
;
refcount
=
IShellItem_AddRef
(
psi
);
ret
=
INameSpaceTreeControlEvents_OnBeforeExpand
(
This
->
pnstce
,
psi
);
if
(
IShellItem_Release
(
psi
)
<
refcount
-
1
)
ERR
(
"ShellItem was released by client - please file a bug.
\n
"
);
return
ret
;
}
static
HRESULT
events_OnAfterExpand
(
NSTC2Impl
*
This
,
IShellItem
*
psi
)
{
HRESULT
ret
;
LONG
refcount
;
if
(
!
This
->
pnstce
)
return
S_OK
;
refcount
=
IShellItem_AddRef
(
psi
);
ret
=
INameSpaceTreeControlEvents_OnAfterExpand
(
This
->
pnstce
,
psi
);
if
(
IShellItem_Release
(
psi
)
<
refcount
-
1
)
ERR
(
"ShellItem was released by client - please file a bug.
\n
"
);
return
ret
;
}
/*************************************************************************
* NamespaceTree helper functions
*/
...
...
@@ -176,6 +202,25 @@ static IShellItem *shellitem_from_treeitem(NSTC2Impl *This, HTREEITEM hitem)
return
(
IShellItem
*
)
tvi
.
lParam
;
}
/* Returns the root that the given treeitem belongs to. */
static
nstc_root
*
root_for_treeitem
(
NSTC2Impl
*
This
,
HTREEITEM
hitem
)
{
HTREEITEM
tmp
,
hroot
=
hitem
;
nstc_root
*
root
;
/* Work our way up the hierarchy */
for
(
tmp
=
hitem
;
tmp
!=
NULL
;
hroot
=
tmp
?
tmp
:
hroot
)
tmp
=
(
HTREEITEM
)
SendMessageW
(
This
->
hwnd_tv
,
TVM_GETNEXTITEM
,
TVGN_PARENT
,
(
LPARAM
)
hroot
);
/* Search through the list of roots for a match */
LIST_FOR_EACH_ENTRY
(
root
,
&
This
->
roots
,
nstc_root
,
entry
)
if
(
root
->
htreeitem
==
hroot
)
break
;
TRACE
(
"root is %p
\n
"
,
root
);
return
root
;
}
static
int
get_icon
(
LPCITEMIDLIST
lpi
,
UINT
extra_flags
)
{
SHFILEINFOW
sfi
;
...
...
@@ -212,6 +257,67 @@ static HTREEITEM insert_shellitem(NSTC2Impl *This, IShellItem *psi,
return
hinserted
;
}
/* Enumerates the children of the folder represented by hitem
* according to the settings for the root, and adds them to the
* treeview. Returns the number of children added. */
static
UINT
fill_sublevel
(
NSTC2Impl
*
This
,
HTREEITEM
hitem
)
{
IShellItem
*
psiParent
=
shellitem_from_treeitem
(
This
,
hitem
);
nstc_root
*
root
=
root_for_treeitem
(
This
,
hitem
);
LPITEMIDLIST
pidl_parent
;
IShellFolder
*
psf
;
IEnumIDList
*
peidl
;
UINT
added
=
0
;
HRESULT
hr
;
hr
=
SHGetIDListFromObject
((
IUnknown
*
)
psiParent
,
&
pidl_parent
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IShellItem_BindToHandler
(
psiParent
,
NULL
,
&
BHID_SFObject
,
&
IID_IShellFolder
,
(
void
**
)
&
psf
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IShellFolder_EnumObjects
(
psf
,
NULL
,
root
->
enum_flags
,
&
peidl
);
if
(
SUCCEEDED
(
hr
))
{
LPITEMIDLIST
pidl
;
IShellItem
*
psi
;
ULONG
fetched
;
while
(
S_OK
==
IEnumIDList_Next
(
peidl
,
1
,
&
pidl
,
&
fetched
)
)
{
hr
=
SHCreateShellItem
(
NULL
,
psf
,
pidl
,
&
psi
);
ILFree
(
pidl
);
if
(
SUCCEEDED
(
hr
))
{
if
(
insert_shellitem
(
This
,
psi
,
hitem
,
NULL
))
{
events_OnItemAdded
(
This
,
psi
,
FALSE
);
added
++
;
}
IShellItem_Release
(
psi
);
}
else
ERR
(
"SHCreateShellItem failed with 0x%08x
\n
"
,
hr
);
}
IEnumIDList_Release
(
peidl
);
}
else
ERR
(
"EnumObjects failed with 0x%08x
\n
"
,
hr
);
IShellFolder_Release
(
psf
);
}
else
ERR
(
"BindToHandler failed with 0x%08x
\n
"
,
hr
);
ILFree
(
pidl_parent
);
}
else
ERR
(
"SHGetIDListFromObject failed with 0x%08x
\n
"
,
hr
);
return
added
;
}
/*************************************************************************
* NamespaceTree window functions
*/
...
...
@@ -358,6 +464,50 @@ static LRESULT on_tvn_getdispinfow(NSTC2Impl *This, LPARAM lParam)
return
TRUE
;
}
static
BOOL
treenode_has_subfolders
(
NSTC2Impl
*
This
,
HTREEITEM
node
)
{
return
SendMessageW
(
This
->
hwnd_tv
,
TVM_GETNEXTITEM
,
TVGN_CHILD
,
(
LPARAM
)
node
);
}
static
LRESULT
on_tvn_itemexpandingw
(
NSTC2Impl
*
This
,
LPARAM
lParam
)
{
NMTREEVIEWW
*
nmtv
=
(
NMTREEVIEWW
*
)
lParam
;
IShellItem
*
psi
;
TRACE
(
"%p
\n
"
,
This
);
psi
=
shellitem_from_treeitem
(
This
,
nmtv
->
itemNew
.
hItem
);
events_OnBeforeExpand
(
This
,
psi
);
if
(
!
treenode_has_subfolders
(
This
,
nmtv
->
itemNew
.
hItem
))
{
/* The node has no children, try to find some */
if
(
!
fill_sublevel
(
This
,
nmtv
->
itemNew
.
hItem
))
{
TVITEMEXW
tvi
;
/* Failed to enumerate any children, remove the expando
* (if any). */
tvi
.
hItem
=
nmtv
->
itemNew
.
hItem
;
tvi
.
mask
=
TVIF_CHILDREN
;
tvi
.
cChildren
=
0
;
SendMessageW
(
This
->
hwnd_tv
,
TVM_SETITEMW
,
0
,
(
LPARAM
)
&
tvi
);
return
TRUE
;
}
}
return
FALSE
;
}
static
LRESULT
on_tvn_itemexpandedw
(
NSTC2Impl
*
This
,
LPARAM
lParam
)
{
NMTREEVIEWW
*
nmtv
=
(
NMTREEVIEWW
*
)
lParam
;
IShellItem
*
psi
;
TRACE
(
"%p
\n
"
,
This
);
psi
=
shellitem_from_treeitem
(
This
,
nmtv
->
itemNew
.
hItem
);
events_OnAfterExpand
(
This
,
psi
);
return
TRUE
;
}
static
LRESULT
CALLBACK
NSTC2_WndProc
(
HWND
hWnd
,
UINT
uMessage
,
WPARAM
wParam
,
LPARAM
lParam
)
{
...
...
@@ -375,6 +525,8 @@ static LRESULT CALLBACK NSTC2_WndProc(HWND hWnd, UINT uMessage,
{
case
TVN_DELETEITEMW
:
return
on_tvn_deleteitemw
(
This
,
lParam
);
case
TVN_GETDISPINFOW
:
return
on_tvn_getdispinfow
(
This
,
lParam
);
case
TVN_ITEMEXPANDINGW
:
return
on_tvn_itemexpandingw
(
This
,
lParam
);
case
TVN_ITEMEXPANDEDW
:
return
on_tvn_itemexpandedw
(
This
,
lParam
);
default:
break
;
}
break
;
...
...
dlls/explorerframe/tests/nstc.c
View file @
4ad1050e
...
...
@@ -317,6 +317,43 @@ static INameSpaceTreeControlEventsImpl *create_nstc_events(void)
return
This
;
}
/*********************************************************************
* Event count checking
*/
static
void
ok_no_events_
(
INameSpaceTreeControlEventsImpl
*
impl
,
const
char
*
file
,
int
line
)
{
UINT
i
;
for
(
i
=
0
;
i
<
LastEvent
;
i
++
)
{
ok_
(
file
,
line
)
(
!
impl
->
count
[
i
],
"Got event %d, count %d
\n
"
,
i
,
impl
->
count
[
i
]);
impl
->
count
[
i
]
=
0
;
}
}
#define ok_no_events(impl) \
ok_no_events_(impl, __FILE__, __LINE__)
#define ok_event_count_broken(impl, event, c, b) \
do { ok(impl->count[event] == c || broken(impl->count[event] == b), \
"Got event %d, count %d\n", event, impl->count[event]); \
impl->count[event] = 0; \
} while(0)
#define ok_event_count(impl, event, c) \
ok_event_count_broken(impl, event, c, -1)
#define ok_event_broken(impl, event) \
do { ok(impl->count[event] || broken(!impl->count[event]), \
"No event.\n"); \
impl->count[event] = 0; \
} while(0)
#define ok_event(impl, event) \
do { ok(impl->count[event], "No event %d.\n", event); \
impl->count[event] = 0; \
} while(0)
/* Process some messages */
static
void
process_msgs
(
void
)
{
...
...
@@ -403,6 +440,27 @@ static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
return
lpszPath
;
}
static
HWND
get_treeview_hwnd
(
INameSpaceTreeControl
*
pnstc
)
{
IOleWindow
*
pow
;
HRESULT
hr
;
HWND
treeview
=
NULL
;
hr
=
INameSpaceTreeControl_QueryInterface
(
pnstc
,
&
IID_IOleWindow
,
(
void
**
)
&
pow
);
ok
(
hr
==
S_OK
,
"Got 0x%08x
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
HWND
host
;
hr
=
IOleWindow_GetWindow
(
pow
,
&
host
);
ok
(
hr
==
S_OK
,
"Got 0x%08x
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
treeview
=
FindWindowExW
(
host
,
NULL
,
WC_TREEVIEWW
,
NULL
);
IOleWindow_Release
(
pow
);
}
return
treeview
;
}
/* Returns FALSE if the NamespaceTreeControl failed to be instantiated. */
static
BOOL
test_initialization
(
void
)
{
...
...
@@ -1053,6 +1111,7 @@ static void test_events(void)
IOleWindow
*
pow
;
LPITEMIDLIST
pidl_desktop
;
DWORD
cookie1
,
cookie2
;
HWND
hwnd_tv
;
HRESULT
hr
;
UINT
res
;
...
...
@@ -1074,6 +1133,7 @@ static void test_events(void)
/* Create two instances of INameSpaceTreeControlEvents */
pnstceimpl
=
create_nstc_events
();
pnstce
=
(
INameSpaceTreeControlEvents
*
)
pnstceimpl
;
ZeroMemory
(
&
pnstceimpl
->
count
,
sizeof
(
UINT
)
*
LastEvent
);
pnstceimpl2
=
create_nstc_events
();
pnstce2
=
(
INameSpaceTreeControlEvents
*
)
pnstceimpl2
;
...
...
@@ -1159,6 +1219,62 @@ static void test_events(void)
pnstceimpl
->
qi_called_count
);
ok
(
pnstceimpl
->
ref
==
1
,
"refcount was %d
\n
"
,
pnstceimpl
->
ref
);
/* Advise again.. */
pnstceimpl
->
qi_enable_events
=
1
;
pnstceimpl
->
qi_called_count
=
0
;
hr
=
INameSpaceTreeControl_TreeAdvise
(
pnstc
,
(
IUnknown
*
)
pnstce
,
&
cookie2
);
ok
(
hr
==
S_OK
,
"Got (0x%08x)
\n
"
,
hr
);
ok
(
cookie2
==
1
,
"Cookie is %d
\n
"
,
cookie2
);
ok
(
cookie1
==
cookie2
,
"Old cookie differs from old cookie.
\n
"
);
todo_wine
{
ok
(
pnstceimpl
->
qi_called_count
==
7
||
pnstceimpl
->
qi_called_count
==
4
/* Vista */
,
"QueryInterface called %d times.
\n
"
,
pnstceimpl
->
qi_called_count
);
}
ok
(
pnstceimpl
->
ref
==
2
,
"refcount was %d
\n
"
,
pnstceimpl
->
ref
);
/* Initialize the control */
hr
=
INameSpaceTreeControl_Initialize
(
pnstc
,
hwnd
,
NULL
,
0
);
ok
(
hr
==
S_OK
,
"Got (0x%08x)
\n
"
,
hr
);
ok_no_events
(
pnstceimpl
);
hr
=
INameSpaceTreeControl_AppendRoot
(
pnstc
,
psidesktop
,
SHCONTF_FOLDERS
|
SHCONTF_NONFOLDERS
,
0
,
NULL
);
ok
(
hr
==
S_OK
,
"Got (0x%08x)
\n
"
,
hr
);
process_msgs
();
ok_event_count_broken
(
pnstceimpl
,
OnItemAdded
,
1
,
0
/* Vista */
);
ok_event_count
(
pnstceimpl
,
OnGetDefaultIconIndex
,
0
);
ok_no_events
(
pnstceimpl
);
hwnd_tv
=
get_treeview_hwnd
(
pnstc
);
ok
(
hwnd_tv
!=
NULL
,
"Failed to get hwnd_tv HWND.
\n
"
);
if
(
hwnd_tv
)
{
HTREEITEM
hroot
;
/* Test On*Expand */
hroot
=
(
HTREEITEM
)
SendMessageW
(
hwnd_tv
,
TVM_GETNEXTITEM
,
TVGN_ROOT
,
0
);
SendMessage
(
hwnd_tv
,
TVM_EXPAND
,
TVE_EXPAND
,
(
LPARAM
)
hroot
);
process_msgs
();
ok_event_count
(
pnstceimpl
,
OnBeforeExpand
,
1
);
ok_event_count
(
pnstceimpl
,
OnAfterExpand
,
1
);
ok_event_broken
(
pnstceimpl
,
OnItemAdded
);
/* No event on Vista */
todo_wine
ok_event_count
(
pnstceimpl
,
OnSelectionChanged
,
1
);
ok_no_events
(
pnstceimpl
);
SendMessage
(
hwnd_tv
,
TVM_EXPAND
,
TVE_COLLAPSE
,
(
LPARAM
)
hroot
);
process_msgs
();
ok_no_events
(
pnstceimpl
);
SendMessage
(
hwnd_tv
,
TVM_EXPAND
,
TVE_EXPAND
,
(
LPARAM
)
hroot
);
process_msgs
();
ok_no_events
(
pnstceimpl
);
}
else
skip
(
"Skipping some tests.
\n
"
);
hr
=
INameSpaceTreeControl_RemoveAllRoots
(
pnstc
);
process_msgs
();
ok
(
hr
==
S_OK
,
"Got 0x%08x
\n
"
,
hr
);
hr
=
INameSpaceTreeControl_QueryInterface
(
pnstc
,
&
IID_IOleWindow
,
(
void
**
)
&
pow
);
ok
(
hr
==
S_OK
,
"Got 0x%08x
\n
"
,
hr
);
...
...
@@ -1171,6 +1287,9 @@ static void test_events(void)
IOleWindow_Release
(
pow
);
}
hr
=
INameSpaceTreeControl_TreeUnadvise
(
pnstc
,
cookie2
);
ok
(
hr
==
S_OK
,
"Got 0x%08x
\n
"
,
hr
);
res
=
INameSpaceTreeControl_Release
(
pnstc
);
ok
(
!
res
,
"res was %d!
\n
"
,
res
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment