When the listview expands or collapses an item it notifies the parent using the TVN_ITEMEXPANDING message. The parent can return true on this message and it prevents the treeview from expanding or collapsing the item. WINE does not let you deny TVN_ITEMEXPANDING by returning true.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53727
-- v7: comctl32/treeview: Allow treeview parent to deny treeview expansion. comctl32/tests: Add test to check if treeview expansion can be denied.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/tests/treeview.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index db4cc4fda71..b8c8175400f 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -52,6 +52,8 @@ static char *g_endedit_overwrite_ptr; static HFONT g_customdraw_font; static BOOL g_v6;
+static int g_reject_tvn_itemexpanding = 0; + #define NUM_MSG_SEQUENCES 3 #define TREEVIEW_SEQ_INDEX 0 #define PARENT_SEQ_INDEX 1 @@ -1361,7 +1363,11 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, } case TVN_ITEMEXPANDINGA: { - UINT newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN; + UINT newmask; + + if (g_reject_tvn_itemexpanding) + return TRUE; + newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN; ok(newmask == (TVIF_HANDLE | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_PARAM | TVIF_STATE), "got wrong mask %x\n", pTreeView->itemNew.mask); @@ -1837,6 +1843,7 @@ static void test_expandnotify(void) HWND hTree; BOOL ret; TVITEMA item; + RECT rc;
hTree = create_treeview_control(0); fill_tree(hTree); @@ -1898,6 +1905,28 @@ static void test_expandnotify(void)
DestroyWindow(hTree);
+ /* check that expansion can be denied by parent */ + hTree = create_treeview_control(0); + fill_tree(hTree); + + g_reject_tvn_itemexpanding = 1; + memset(&item, 0, sizeof(item)); + item.mask = TVIF_STATE; + item.hItem = hRoot; + *((HTREEITEM *)&rc) = item.hItem; + + /* Simulate the double-click */ + SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc); + SendMessageA(hTree, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(rc.left + ((rc.right - rc.left) / 2), rc.top + ((rc.bottom - rc.top) / 2))); + g_reject_tvn_itemexpanding = 0; + + /* check that it's expanded */ + item.state = TVIS_EXPANDED; + ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); + todo_wine ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n"); + + DestroyWindow(hTree); + /* test TVM_GETITEMRECT inside TVN_ITEMEXPANDED notification */ hTree = create_treeview_control(0); fill_tree(hTree);
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53727 --- dlls/comctl32/tests/treeview.c | 2 +- dlls/comctl32/treeview.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index b8c8175400f..d5926efdb66 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -1923,7 +1923,7 @@ static void test_expandnotify(void) /* check that it's expanded */ item.state = TVIS_EXPANDED; ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); - todo_wine ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n"); + ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n");
DestroyWindow(hTree);
diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index e2a4280f131..8e9dcebf6ee 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -3348,7 +3348,7 @@ static BOOL TREEVIEW_SendExpanding(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, UINT action) { - return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, + return TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, TVIF_HANDLE | TVIF_STATE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE, 0, item); @@ -3383,8 +3383,8 @@ TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, if (!TREEVIEW_HasChildren(infoPtr, item)) return FALSE;
- if (bUser) - TREEVIEW_SendExpanding(infoPtr, item, action); + if (bUser && TREEVIEW_SendExpanding(infoPtr, item, action)) + return TRUE;
if (item->firstChild == NULL) return FALSE; @@ -3513,12 +3513,13 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, !(item->state & TVIS_EXPANDEDONCE)); if (sendsNotifications) { - if (!TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND)) - { - TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); - return FALSE; - } + if(TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND)) + { + TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); + return TRUE; + } } + if (!item->firstChild) return FALSE;
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
static HFONT g_customdraw_font; static BOOL g_v6;
Let's delete this new line before g_reject_tvn_itemexpanding.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/treeview.c:
TREEVIEW_SendExpanding(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, UINT action) {
- return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action,
- return TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action,
Please keep the parameters aligned to the first parameter. It's off by 1 character.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/treeview.c:
!(item->state & TVIS_EXPANDEDONCE)); if (sendsNotifications) {
- if (!TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND))
- {
TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n");
return FALSE;
- }
if(TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND))
Add a space after if. I notice this has happened multiple times. You might want to check your editor's config.
And it looks good besides these minor style issues. Thanks for working on this.