comctl32/treeview: Fix tooltip window leak.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2018-02-01 10:09:03 +03:00 committed by Alexandre Julliard
parent f2b489591b
commit b413a93793
2 changed files with 106 additions and 11 deletions

View File

@ -1069,9 +1069,101 @@ static void test_get_set_textcolor(void)
static void test_get_set_tooltips(void) static void test_get_set_tooltips(void)
{ {
HWND hwndLastToolTip = NULL; HWND hTree, tooltips, hwnd;
HWND hPopupTreeView; DWORD style;
HWND hTree; int i;
/* TVS_NOTOOLTIPS */
hTree = create_treeview_control(TVS_NOTOOLTIPS);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
/* Toggle style */
style = GetWindowLongA(hTree, GWL_STYLE);
SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
style = GetWindowLongA(hTree, GWL_STYLE);
SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
DestroyWindow(hTree);
/* Set some valid window, does not have to be tooltips class. */
hTree = create_treeview_control(TVS_NOTOOLTIPS);
hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
ok(hwnd != NULL, "Failed to create child window.\n");
tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
/* Externally set tooltips window, disable style. */
style = GetWindowLongA(hTree, GWL_STYLE);
SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(IsWindow(tooltips) && tooltips != hwnd, "Unexpected tooltip window %p.\n", tooltips);
ok(IsWindow(hwnd), "Expected valid window.\n");
style = GetWindowLongA(hTree, GWL_STYLE);
SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
ok(!IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
ok(IsWindow(hwnd), "Expected valid window.\n");
DestroyWindow(hTree);
ok(IsWindow(hwnd), "Expected valid window.\n");
/* Set window, disable tooltips. */
hTree = create_treeview_control(0);
tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
style = GetWindowLongA(hTree, GWL_STYLE);
SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
ok(!IsWindow(hwnd), "Unexpected tooltip window %p.\n", tooltips);
ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
DestroyWindow(hTree);
ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
DestroyWindow(tooltips);
DestroyWindow(hwnd);
for (i = 0; i < 2; i++)
{
DWORD style = i == 0 ? 0 : TVS_NOTOOLTIPS;
hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
ok(hwnd != NULL, "Failed to create child window.\n");
hTree = create_treeview_control(style);
tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
ok(style & TVS_NOTOOLTIPS ? tooltips == NULL : IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
DestroyWindow(tooltips);
tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
/* TreeView is destroyed, check if set window is still around. */
DestroyWindow(hTree);
ok(!IsWindow(hwnd), "Unexpected window.\n");
}
hTree = create_treeview_control(0); hTree = create_treeview_control(0);
fill_tree(hTree); fill_tree(hTree);
@ -1079,20 +1171,23 @@ static void test_get_set_tooltips(void)
flush_sequences(sequences, NUM_MSG_SEQUENCES); flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */ /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
hPopupTreeView = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100, hwnd = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100,
hMainWnd, NULL, NULL, NULL); hMainWnd, NULL, NULL, NULL);
DestroyWindow(hPopupTreeView); DestroyWindow(hwnd);
/* Testing setting a NULL ToolTip */ /* Testing setting a NULL ToolTip */
SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0); tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
hwndLastToolTip = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0); ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
ok(hwndLastToolTip == NULL, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip);
hwnd = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
ok(hwnd == NULL, "Unexpected tooltip window %p.\n", hwnd);
ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_tooltips_seq, ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_tooltips_seq,
"test get set tooltips", TRUE); "test get set tooltips", TRUE);
/* TODO: Add a test of an actual tooltip */
DestroyWindow(hTree); DestroyWindow(hTree);
ok(IsWindow(tooltips), "Expected valid window.\n");
DestroyWindow(tooltips);
} }
static void test_get_set_unicodeformat(void) static void test_get_set_unicodeformat(void)
@ -2754,6 +2849,7 @@ START_TEST(treeview)
test_expandedimage(); test_expandedimage();
test_htreeitem_layout(); test_htreeitem_layout();
test_WM_GETDLGCODE(); test_WM_GETDLGCODE();
test_get_set_tooltips();
unload_v6_module(ctx_cookie, hCtx); unload_v6_module(ctx_cookie, hCtx);
} }

View File

@ -5188,8 +5188,6 @@ TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
TREEVIEW_FreeItem(infoPtr, infoPtr->root); TREEVIEW_FreeItem(infoPtr, infoPtr->root);
DPA_Destroy(infoPtr->items); DPA_Destroy(infoPtr->items);
/* tool tip is automatically destroyed: we are its owner */
/* Restore original wndproc */ /* Restore original wndproc */
if (infoPtr->hwndEdit) if (infoPtr->hwndEdit)
SetWindowLongPtrW(infoPtr->hwndEdit, GWLP_WNDPROC, SetWindowLongPtrW(infoPtr->hwndEdit, GWLP_WNDPROC,
@ -5204,6 +5202,7 @@ TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
DeleteObject(infoPtr->hBoldFont); DeleteObject(infoPtr->hBoldFont);
DeleteObject(infoPtr->hUnderlineFont); DeleteObject(infoPtr->hUnderlineFont);
DeleteObject(infoPtr->hBoldUnderlineFont); DeleteObject(infoPtr->hBoldUnderlineFont);
DestroyWindow(infoPtr->hwndToolTip);
Free(infoPtr); Free(infoPtr);
return 0; return 0;