comctl32: [try 2] correct handling of toolbar separators' size

Igor Tarasov tarasov.igor at gmail.com
Sat Mar 21 06:48:52 CDT 2009


Second try, applied advice from wine-devel.

2009/3/18 Igor Tarasov <tarasov.igor at gmail.com>:
> Currently, wine uses iBitmap property for determining toolbar
> separators width all the time, stating it's an undocumented feature.
> This is not correct.
>
> According to MSDN, iBitmap is used only on inserting separator (since
> there is no cx field in TBBUTTON structure).
> http://msdn.microsoft.com/en-us/library/bb760476(VS.85).aspx
>
> In other cases, cx property that can be updated via get/set buttoninfo
> is used, as tests show. Also, tests show that this property differs
> from zero only if application specifically sets. Setting it to 0 makes
> separator display in default width. All this is implemented in this
> patch. More tests results in bugtracker (link below).
>
> As of setting iBitmap for separators: native comctl32 starts behaving
> very buggy, misplacing button bitmaps, even outside of the buttons,
> thus producing visual glitches. While autosizing toolbar puts bitmaps
> at their places, but, IMHO, it's rather bug than feature.
>
> This patch fixes bug 17654
> http://bugs.winehq.org/show_bug.cgi?id=17654

P.S: Best used with my previous patch ;)
http://www.winehq.org/pipermail/wine-patches/2009-March/070888.html

--
Igor
-------------- next part --------------
diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index 92a1366..fe4c539 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -1326,17 +1326,14 @@ TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
 	if (btnPtr[i].fsState & TBSTATE_HIDDEN)
 	    continue;
 
-	/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
-	/* it is the actual width of the separator. This is used for */
-	/* custom controls in toolbars.                              */
-	/*                                                           */
+        if (btnPtr[i].cx > 0)
+            cx = btnPtr[i].cx;
         /* horizontal separators are treated as buttons for width    */
-	if ((btnPtr[i].fsStyle & BTNS_SEP) &&
+	else if ((btnPtr[i].fsStyle & BTNS_SEP) &&
             !(infoPtr->dwStyle & CCS_VERT))
-	    cx = (btnPtr[i].iBitmap > 0) ?
-			btnPtr[i].iBitmap : SEPARATOR_WIDTH;
+	    cx = SEPARATOR_WIDTH;
 	else
-	    cx = (btnPtr[i].cx) ? btnPtr[i].cx : infoPtr->nButtonWidth;
+	    cx = infoPtr->nButtonWidth;
 
 	/* Two or more adjacent separators form a separator group.   */
 	/* The first separator in a group should be wrapped to the   */
@@ -1684,18 +1681,13 @@ TOOLBAR_LayoutToolbar(HWND hwnd)
 
 	cy = infoPtr->nButtonHeight;
 
-	/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
-	/* it is the actual width of the separator. This is used for */
-	/* custom controls in toolbars.                              */
 	if (btnPtr->fsStyle & BTNS_SEP) {
 	    if (infoPtr->dwStyle & CCS_VERT) {
-		cy = (btnPtr->iBitmap > 0) ?
-		     btnPtr->iBitmap : SEPARATOR_WIDTH;
-		cx = infoPtr->nButtonWidth;
+                cy = SEPARATOR_WIDTH;
+                cx = (btnPtr->cx > 0) ? btnPtr->cx : infoPtr->nButtonWidth;
 	    }
 	    else
-		cx = (btnPtr->iBitmap > 0) ?
-		     btnPtr->iBitmap : SEPARATOR_WIDTH;
+                cx = (btnPtr->cx > 0) ? btnPtr->cx : SEPARATOR_WIDTH;
 	}
 	else
 	{
@@ -1758,12 +1750,9 @@ TOOLBAR_LayoutToolbar(HWND hwnd)
 	        y += cy;
 	    else
 	    {
-		/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
-		/* it is the actual width of the separator. This is used for */
-		/* custom controls in toolbars. 			     */
                if ( !(infoPtr->dwStyle & CCS_VERT))
-		    y += cy + ( (btnPtr->iBitmap > 0 ) ?
-				btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
+                    y += cy + ( (btnPtr->cx > 0 ) ?
+                                btnPtr->cx : SEPARATOR_WIDTH) * 2 /3;
 		else
 		    y += cy;
 
@@ -1845,7 +1834,12 @@ TOOLBAR_InternalInsertButtonsT(TOOLBAR_INFO *infoPtr, INT iIndex, UINT nAddButto
         TOOLBAR_DumpTBButton(lpTbb, fUnicode);
 
         ZeroMemory(btnPtr, sizeof(*btnPtr));
-        btnPtr->iBitmap   = lpTbb[iButton].iBitmap;
+
+        /* When inserting separator, iBitmap controls it's size */
+        if (lpTbb[iButton].fsStyle & BTNS_SEP) {
+            btnPtr->cx        = lpTbb[iButton].iBitmap;
+        } else
+            btnPtr->iBitmap   = lpTbb[iButton].iBitmap;
         btnPtr->idCommand = lpTbb[iButton].idCommand;
         btnPtr->fsState   = lpTbb[iButton].fsState;
         btnPtr->fsStyle   = lpTbb[iButton].fsStyle;
@@ -3400,7 +3394,11 @@ TOOLBAR_GetButtonInfoT(HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode)
     if (lpTbInfo->dwMask & TBIF_LPARAM)
 	lpTbInfo->lParam = btnPtr->dwData;
     if (lpTbInfo->dwMask & TBIF_SIZE)
-	lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
+        /* tests show that for separators TBIF_SIZE returns not calculated width,
+           but cx property, that differs from 0 only if application have
+           specifically set it */
+        lpTbInfo->cx = (btnPtr->fsStyle & BTNS_SEP)
+            ? btnPtr->cx : (WORD)(btnPtr->rect.right - btnPtr->rect.left);
     if (lpTbInfo->dwMask & TBIF_STATE)
 	lpTbInfo->fsState = btnPtr->fsState;
     if (lpTbInfo->dwMask & TBIF_STYLE)
@@ -4240,7 +4238,9 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave)
                 {
                     /* separator */
                     nmtbr.tbButton.fsStyle = TBSTYLE_SEP;
-                    nmtbr.tbButton.iBitmap = SEPARATOR_WIDTH;
+                    /* when inserting separators, iBitmap controls it's size.
+                       0 sets default size (width) */
+                    nmtbr.tbButton.iBitmap = 0;
                 }
                 else if (*nmtbr.pCurrent == (DWORD)-2)
                     /* hidden button */


More information about the wine-patches mailing list