COMCTL32 - TreeView control not correctly updated with COMCTL32.OCX

Alex Villací­s Lasso a_villacis at palosanto.com
Mon Oct 10 12:04:49 CDT 2005


Alex Villací­s Lasso wrote:

> This SIAP application is revealing more problems with Wine. This time 
> it is the
> reason for the original complaint: Mr. Maximiliano Curia reported that 
> in the
> version of Wine he could test, the treeview control in the middle of 
> the screen
> was not updated correctly. The treeview control should have looked 
> like this:
>
> +---------------------------------+
> |Persona Física                   |
> | |                               |
> | +- Datos identificatorios       |
> | |     |                         |
> | |     +- Nombre y otros datos   |
> | |     +- Domicilio              |
> | |     +- Actividades            |
> | +- Datos comerciales            |
> | |     |                         |
> | |     +- Datos de interés fiscal|
> | |     +- Claves bancarias       |
> | +- Responsable por deuda ajena  |
> +---------------------------------+
>
> Don't mind the actual meaning of the text in the nodes. The problem is 
> that for
> Mr. Curia, the treeview control actually shows up like this:
>
> +---------------------------------+
> |Persona Física                   |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> |                                 |
> +---------------------------------+
>
> That is, the treeview control only shows the first line of the tree. 
> 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);
>         }
>     }
>
> The sample (VisualBasic) code and executable have been uploaded as 
> testcases for
> the following bug report: http://bugs.winehq.org/show_bug.cgi?id=3476

Further testing with native vs. builtin comctl32 show that native 
treeview (which works correctly) does NOT issue a GetUpdateRect() in 
response to a WM_PAINT message with a wParam=someHDC. This suggests that 
native comctl32 knows that a non-null wParam means that the tree must be 
painted anyway, regardless of whether the control window might have an 
update rect. The attached patch gets rid of the (incorrect?) extra 
GetUpdateRect() call and does a GetClientRect() on the control window 
instead to get a working bounding rect. This fixes the bug for the 
sample app in bug 3476.

Changelog:
* Do not issue a GetUpdateRect() to query an update region for 
WM_PAINT(wParam=HDC) case. Instead, use GetClientRect() for a bounding rect.

Alex Villacís Lasso

-------------- next part --------------
A non-text attachment was scrubbed...
Name: wine-comctl32-treeview_fix.patch
Type: text/x-patch
Size: 842 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20051010/10d81068/wine-comctl32-treeview_fix-0001.patch
-------------- next part --------------



More information about the wine-devel mailing list