http://bugs.winehq.org/show_bug.cgi?id=3476
Summary: Treeview control has invalid update region when built by COMCTL32.OCX Product: Wine Version: CVS Platform: PC OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: wine-gui AssignedTo: wine-bugs@winehq.org ReportedBy: a_villacis@palosanto.com
When COMCTL32.OCX (ships with MS VisualBasic 5) builds a TreeView control, the control is not repainted correctly: only the very first item is repainted, instead of the entire tree. This happens regardless of the expanded status of the treeview.
After some digging in the treeview control, I saw that the code in the control tries to save some drawing by querying the update region of the control window. When the WM_PAINT message indicates a non-null HDC in wParam, the code fetches the update region for the control window. If I understand the intent of the code correctly, the WM_PAINT message can be sent to the control with an wParam of the HDC of an offscreen bitmap, in order to draw the tree into it. When the update region of the control is NULL, the code fetches the BITMAP structure of the target HDC in order to clip the drawing to the dimensions of the target bitmap.
The problem is that, in the case of the treeview managed by COMCTL32.OCX, for some as yet undiscovered reason, the control *always* has a null update region, except for the very first rendering (which is overwritten by a second rendering with the problematic null region). No matter how the window is uncovered, the update region remains null. Therefore, the control believes that the target is an offscreen bitmap, even for the rendering to the screen. It then fetches the default bitmap selected, which is an 1x1 dummy bitmap, gets a 1x1 target region, and believes that only 1 pixel should be updated. Only the very first item gets redrawn because of this.
The following patch works around this issue. However, this is not a proper fix, because the control window should have been properly invalidated in the first place, and the control should therefore have a proper update region. I am not really sure whether the root cause is in the treeview code or in the region updating code. I am inclined to the former, because the same treeview control seems to work correctly in regedit.exe:
--- wine-20050930-cvs/dlls/comctl32/treeview.c 2005-09-12 17:34:07.000000000 -0500 +++ wine-20050930-cvs-patch/dlls/comctl32/treeview.c 2005-10-02 22:08:08.000000000 -0500 @@ -2790,6 +2790,8 @@ RECT rect = *rc; TREEVIEW_ITEM *wineItem;
+ TRACE("refreshing on (%ld,%ld)-(%ld,%ld)\n", rect.left, rect.top, rect.right, rect.bottom); + if (infoPtr->clientHeight == 0 || infoPtr->clientWidth == 0) { TRACE("empty window\n"); @@ -2859,6 +2861,12 @@ rc.left = 0; rc.top = 0; rc.right = bitmap.bmWidth; rc.bottom = bitmap.bmHeight; + if (bitmap.bmWidth == 1 && + bitmap.bmHeight == 1 && + bitmap.bmWidthBytes == 2) { + ERR("failed to recover a valid update region, using GetClientRect()\n"); + GetClientRect(infoPtr->hwnd, &rc); + } TREEVIEW_EraseBackground(infoPtr, (HDC)wParam); } }