From: Dan Bassi Subject: comctl32: Use strcmpW instead of pointer comparison to ensure treeview updates correctly (try 2) Message-Id: Date: Sun, 26 Oct 2014 17:02:10 +0000

From 3402c9fe09711eb7dec00bbe723f599f7e7bedb5 Mon Sep 17 00:00:00 2001 From: Dan Bassi Date: Sun, 26 Oct 2014 16:48:47 +0000 Subject: comctl32: Use strcmpW instead of pointer comparison to ensure treeview updates correctly (try 2) --- dlls/comctl32/tests/treeview.c | 116 +++++++++++++++++++++++++++++++++++++++++ dlls/comctl32/treeview.c | 5 +- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index ce65f06..103e9ba 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -2155,6 +2155,121 @@ static void test_WM_KEYDOWN(void) DestroyWindow(hwnd); } +static void test_screen_update_after_text_change(void) +{ + HWND hTree; + RECT rc; + TVINSERTSTRUCTA ins; + TVITEMA tvi; + HTREEITEM hItem1; + HDC hdc; + HDC mem_dc; + HBITMAP bmp; + BITMAPINFO bmi; + VOID *buffer1 = NULL, *buffer2 = NULL, *pBits = NULL; + CHAR received[] = "received", not_received[] = "not received", initial_text[] = "Initial Text", new_text[] = "New Text"; + CHAR *insertitem_wm_paint_result, *setitem_wm_paint_result; + BOOL wm_paint_message_received = FALSE; + MSG msg; + LONG window_width, window_height, buffer_size, bitmap_bytes_per_pixel = 3; + DWORD ret; + + hTree = create_treeview_control(0); + + hdc = GetDC(hTree); + mem_dc = CreateCompatibleDC(hdc); + + GetClientRect(hTree, &rc); + + window_width = rc.right - rc.left; + window_height = rc.bottom - rc.top; + + buffer_size = window_width * window_height * bitmap_bytes_per_pixel; + + buffer1 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size); + buffer2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size); + + memset(&bmi, 0, sizeof(BITMAPINFO) ); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = window_width; + bmi.bmiHeader.biHeight = window_height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + bmp = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); + SelectObject(mem_dc, bmp); + + ok( (buffer1 != 0) && (buffer2 != 0) && (pBits != 0), "Could not allocate buffers\n"); + + memset(&ins, 0, sizeof(TVINSERTSTRUCTA) ); + ins.hParent=TVI_ROOT; + ins.hInsertAfter=TVI_FIRST; + U(ins).item.mask = TVIF_TEXT ; + U(ins).item.pszText = initial_text; + U(ins).item.cchTextMax = sizeof(initial_text)/sizeof(initial_text[0]); + hItem1 = TreeView_InsertItemA(hTree,&ins) ; + + /* Pump the message queue to process any (expected) WM_PAINT messages received following TreeView_InsertItem, and allow the screen to update */ + + wm_paint_message_received = FALSE; + + while (PeekMessageA(&msg,NULL,0,0,PM_NOREMOVE) ) + { + if (GetMessageA(&msg, NULL, 0, 0) <= 0) break; + TranslateMessage(&msg); + if (msg.message == WM_PAINT) wm_paint_message_received = TRUE; + DispatchMessageA(&msg); + } + + if (wm_paint_message_received == FALSE) insertitem_wm_paint_result = not_received; + else insertitem_wm_paint_result = received; + + /* Take a copy of the screen buffer before changing the text */ + + BitBlt(mem_dc, 0, 0, window_width, window_height, hdc, 0, 0, SRCCOPY); + memcpy(buffer1, pBits, buffer_size); + + memset(&tvi, 0, sizeof(TVITEMA) ); + tvi.mask = TVIF_TEXT; + tvi.hItem = hItem1; + tvi.pszText = new_text; + tvi.cchTextMax = sizeof(new_text)/sizeof(new_text[0]); + ret = TreeView_SetItemA(hTree, &tvi); + expect(TRUE, ret); + + /* Pump the message queue again */ + + wm_paint_message_received = FALSE; + + while (PeekMessageA(&msg,NULL,0,0,PM_NOREMOVE) ) + { + if (GetMessageA(&msg, NULL, 0, 0) <= 0) break; + TranslateMessage(&msg); + if (msg.message == WM_PAINT) wm_paint_message_received = TRUE; + DispatchMessageA(&msg); + } + + if (wm_paint_message_received == FALSE) setitem_wm_paint_result = not_received; + else setitem_wm_paint_result = received; + + /* Take another copy of the screen buffer after changing text, and compare with the previous buffer to check whether the screen has been updated */ + + BitBlt(mem_dc, 0, 0, window_width, window_height, hdc, 0, 0, SRCCOPY); + memcpy(buffer2, pBits, buffer_size); + + ok( memcmp(buffer1, buffer2, buffer_size) != 0, "Screen is not updating following text change (WM_PAINT %s following TreeView_InsertItem; WM_PAINT %s following TreeView_SetItem)\n", insertitem_wm_paint_result, setitem_wm_paint_result); + + HeapFree(GetProcessHeap(), 0, buffer1); + HeapFree(GetProcessHeap(), 0, buffer2); + + DeleteObject(bmp); + DeleteDC(mem_dc); + ReleaseDC(hTree, hdc); + + DestroyWindow(hTree); +} + START_TEST(treeview) { HMODULE hComctl32; @@ -2230,6 +2345,7 @@ START_TEST(treeview) test_WM_GETDLGCODE(); test_customdraw(); test_WM_KEYDOWN(); + test_screen_update_after_text_change(); if (!load_v6_module(&ctx_cookie, &hCtx)) { diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index 4067323..3447efe 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -255,7 +255,7 @@ static inline BOOL item_changed (const TREEVIEW_ITEM *tiOld, const TREEVIEW_ITEM return TRUE; /* Text has changed and it's not a callback */ - if ((tvChange->mask & TVIF_TEXT) && (tiOld->pszText != tiNew->pszText) && + if( tiOld->pszText && tiNew->pszText ) if ((tvChange->mask & TVIF_TEXT) && (strcmpW(tiOld->pszText, tiNew->pszText) != 0) && tiNew->pszText != LPSTR_TEXTCALLBACKW) return TRUE; @@ -2169,6 +2169,8 @@ TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, const TVITEMEXW *tvItem, BOOL isW) /* store the original item values */ originalItem = *item; + originalItem.pszText = Alloc(originalItem.cchTextMax * sizeof(WCHAR)); + if (originalItem.pszText) memcpy(originalItem.pszText, item->pszText, item->cchTextMax * sizeof(WCHAR)); if (!TREEVIEW_DoSetItemT(infoPtr, item, tvItem, isW)) return FALSE; @@ -2205,6 +2207,7 @@ TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, const TVITEMEXW *tvItem, BOOL isW) } } + if (originalItem.pszText) Free(originalItem.pszText); return TRUE; } -- 1.9.1