[COMCTL32] -Take into account the upper theme margin when drawing the icon so that...
[reactos.git] / reactos / dll / win32 / comctl32 / toolbar.c
index 1cda50e..2c7d8bd 100644 (file)
  *     - TBSTYLE_REGISTERDROP
  *     - TBSTYLE_EX_DOUBLEBUFFER
  *   - Messages:
- *     - TB_GETMETRICS
  *     - TB_GETOBJECT
  *     - TB_INSERTMARKHITTEST
  *     - TB_SAVERESTORE
- *     - TB_SETMETRICS
  *     - WM_WININICHANGE
  *   - Notifications:
  *     - NM_CHAR
@@ -80,8 +78,8 @@ typedef struct
     INT idCommand;
     BYTE  fsState;
     BYTE  fsStyle;
-    BYTE  bHot;
-    BYTE  bDropDownPressed;
+    BOOL  bHot;
+    BOOL  bDropDownPressed;
     DWORD_PTR dwData;
     INT_PTR iString;
     INT nRow;
@@ -105,7 +103,6 @@ typedef struct
 typedef struct
 {
     DWORD    dwStructSize;    /* size of TBBUTTON struct */
-    INT      nWidth;          /* width of the toolbar */
     RECT     client_rect;
     RECT     rcBound;         /* bounding rectangle */
     INT      nButtonHeight;
@@ -126,6 +123,11 @@ typedef struct
     INT      nOldHit;
     INT      nHotItem;        /* index of the "hot" item */
     SIZE     szPadding;       /* padding values around button */
+#ifdef __REACTOS__
+    SIZE     szBarPadding;       /* padding values around the toolbar (NOT USED BUT STORED) */
+    SIZE     szSpacing;       /* spacing values between buttons */
+    MARGINS  themeMargins;
+#endif
     INT      iTopMargin;      /* the top margin */
     INT      iListGap;        /* default gap between text and image for toolbar with list style */
     HFONT    hDefaultFont;
@@ -191,12 +193,24 @@ typedef enum
 #define ARROW_HEIGHT       3
 #define INSERTMARK_WIDTH   2
 
+/* default padding inside a button */
 #define DEFPAD_CX 7
 #define DEFPAD_CY 6
+
+#ifdef __REACTOS__
+/* default space between buttons and between rows */
+#define DEFSPACE_CX 7
+#define DEFSPACE_CY 6
+#endif
+
 #define DEFLISTGAP 4
 
 /* vertical padding used in list mode when image is present */
+#ifdef __REACTOS__
+#define LISTPAD_CY 2
+#else
 #define LISTPAD_CY 9
+#endif
 
 /* how wide to treat the bitmap if it isn't present */
 #define NONLIST_NOTEXT_OFFSET 2
@@ -234,10 +248,16 @@ static LRESULT TOOLBAR_AutoSize(TOOLBAR_INFO *infoPtr);
 static void TOOLBAR_CheckImageListIconSize(TOOLBAR_INFO *infoPtr);
 static void TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button);
 static void TOOLBAR_TooltipSetRect(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button);
+static LRESULT TOOLBAR_SetButtonInfo(TOOLBAR_INFO *infoPtr, INT Id,
+                                     const TBBUTTONINFOW *lptbbi, BOOL isW);
 
 
 static inline int default_top_margin(const TOOLBAR_INFO *infoPtr)
 {
+#ifdef __REACTOS__
+    if (infoPtr->iVersion == 6)
+        return 0;
+#endif
     return (infoPtr->dwStyle & TBSTYLE_FLAT ? 0 : TOP_BORDER);
 }
 
@@ -246,6 +266,12 @@ static inline BOOL TOOLBAR_HasDropDownArrows(DWORD exStyle)
     return (exStyle & TBSTYLE_EX_DRAWDDARROWS) != 0;
 }
 
+static inline BOOL button_has_ddarrow(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *btnPtr)
+{
+    return (TOOLBAR_HasDropDownArrows( infoPtr->dwExStyle ) && (btnPtr->fsStyle & BTNS_DROPDOWN)) ||
+        (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
+}
+
 static LPWSTR
 TOOLBAR_GetText(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *btnPtr)
 {
@@ -309,6 +335,37 @@ TOOLBAR_ButtonHasString(const TBUTTON_INFO *btnPtr)
     return HIWORD(btnPtr->iString) && btnPtr->iString != -1;
 }
 
+static void set_string_index( TBUTTON_INFO *btn, INT_PTR str, BOOL unicode )
+{
+    if (!IS_INTRESOURCE( str ) && str != -1)
+    {
+        if (!TOOLBAR_ButtonHasString( btn )) btn->iString = 0;
+
+        if (unicode)
+            Str_SetPtrW( (WCHAR **)&btn->iString, (WCHAR *)str );
+        else
+            Str_SetPtrAtoW( (WCHAR **)&btn->iString, (char *)str );
+    }
+    else
+    {
+        if (TOOLBAR_ButtonHasString( btn )) Free( (WCHAR *)btn->iString );
+
+        btn->iString  = str;
+    }
+}
+
+static void set_stringT( TBUTTON_INFO *btn, const WCHAR *str, BOOL unicode )
+{
+    if (IS_INTRESOURCE( (DWORD_PTR)str ) || (DWORD_PTR)str == -1) return;
+    set_string_index( btn, (DWORD_PTR)str, unicode );
+}
+
+static void free_string( TBUTTON_INFO *btn )
+{
+    set_string_index( btn, 0, TRUE );
+
+}
+
 /***********************************************************************
 *              TOOLBAR_CheckStyle
 *
@@ -560,6 +617,9 @@ TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText,
     COLORREF clrOldBk = 0;
     int oldBkMode = 0;
     UINT state = tbcd->nmcd.uItemState;
+#ifdef __REACTOS__
+    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
+#endif
 
     /* draw text */
     if (lpText && infoPtr->nMaxTextRows > 0) {
@@ -589,6 +649,25 @@ TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText,
            clrOld = SetTextColor (hdc, tbcd->clrText);
        }
 
+#ifdef __REACTOS__
+    if (theme)
+    {
+        int partId = TP_BUTTON;
+        int stateId = TS_NORMAL;
+
+        if (state & CDIS_DISABLED)
+            stateId = TS_DISABLED;
+        else if (state & CDIS_SELECTED)
+            stateId = TS_PRESSED;
+        else if (state & CDIS_CHECKED)
+            stateId = (state & CDIS_HOT) ? TS_HOTCHECKED : TS_HOT;
+        else if (state & CDIS_HOT)
+            stateId = TS_HOT;
+
+        DrawThemeText(theme, hdc, partId, stateId, lpText, -1, infoPtr->dwDTFlags, 0, rcText);
+    }
+    else
+#endif
        DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
        SetTextColor (hdc, clrOld);
        if ((state & CDIS_MARKED) && !(dwItemCDFlag & TBCDRF_NOMARK))
@@ -685,10 +764,14 @@ TOOLBAR_DrawImage(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, I
                   const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag)
 {
     HIMAGELIST himl = NULL;
-    BOOL draw_masked = FALSE;
+    BOOL draw_masked = FALSE, draw_desaturated = FALSE;
     INT index;
     INT offset = 0;
     UINT draw_flags = ILD_TRANSPARENT;
+#ifdef __REACTOS__
+    IMAGEINFO info = {0};
+    BITMAP bm = {0};
+#endif
 
     if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
     {
@@ -696,7 +779,22 @@ TOOLBAR_DrawImage(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, I
         if (!himl)
         {
             himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index);
+
+#ifdef __REACTOS__
+            ImageList_GetImageInfo(himl, index, &info);
+            GetObjectW(info.hbmImage, sizeof(bm), &bm);
+
+            if (bm.bmBitsPixel == 32)
+            {
+                draw_desaturated = TRUE;
+            }
+            else
+            {
+                draw_masked = TRUE;
+            }
+#else
             draw_masked = TRUE;
+#endif
         }
     }
     else if (tbcd->nmcd.uItemState & CDIS_CHECKED ||
@@ -727,17 +825,42 @@ TOOLBAR_DrawImage(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, I
       index, himl, left, top, offset);
 
     if (draw_masked)
+    {
+        /* code path for drawing flat disabled icons without alpha channel */
         TOOLBAR_DrawMasked (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags);
+    }
+    else if (draw_desaturated)
+    {
+        /* code path for drawing disabled, alpha-blended (32bpp) icons */
+        IMAGELISTDRAWPARAMS imldp = {0};
+
+        imldp.cbSize = sizeof(imldp);
+        imldp.himl   = himl;
+        imldp.i      = index;
+        imldp.hdcDst = tbcd->nmcd.hdc,
+        imldp.x      = offset + left;
+        imldp.y      = offset + top;
+        imldp.rgbBk  = CLR_NONE;
+        imldp.rgbFg  = CLR_DEFAULT;
+        imldp.fStyle = ILD_TRANSPARENT;
+        imldp.fState = ILS_ALPHA | ILS_SATURATE;
+        imldp.Frame  = 192;
+
+        ImageList_DrawIndirect (&imldp);
+    }
     else
+    {
+        /* code path for drawing standard icons as-is */
         ImageList_Draw (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags);
+    }
 }
 
 /* draws a blank frame for a toolbar button */
 static void
-TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag)
+TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, const RECT *rect, DWORD dwItemCDFlag)
 {
     HDC hdc = tbcd->nmcd.hdc;
-    RECT rc = tbcd->nmcd.rc;
+    RECT rc = *rect;
     /* if the state is disabled or indeterminate then the button
      * cannot have an interactive look like pressed or hot */
     BOOL non_interactive_state = (tbcd->nmcd.uItemState & CDIS_DISABLED) ||
@@ -810,9 +933,7 @@ static void
 TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc, DWORD dwBaseCustDraw)
 {
     DWORD dwStyle = infoPtr->dwStyle;
-    BOOL hasDropDownArrow = (TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
-                            (btnPtr->fsStyle & BTNS_DROPDOWN)) ||
-                            (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
+    BOOL hasDropDownArrow = button_has_ddarrow( infoPtr, btnPtr );
     BOOL drawSepDropDownArrow = hasDropDownArrow && 
                                 (~btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
     RECT rc, rcArrow, rcBitmap, rcText;
@@ -826,7 +947,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
 
     rc = btnPtr->rect;
-    CopyRect (&rcArrow, &rc);
+    rcArrow = rc;
 
     /* separator - doesn't send NM_CUSTOMDRAW */
     if (btnPtr->fsStyle & BTNS_SEP) {
@@ -848,14 +969,15 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
                 InflateRect(&rcsep, -infoPtr->szPadding.cx, -infoPtr->szPadding.cy);
                 TOOLBAR_DrawFlatHorizontalSeparator (&rcsep, hdc, infoPtr);
             }
-           else
-               TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
-       }
-       else if (btnPtr->fsStyle != BTNS_SEP) {
-           FIXME("Draw some kind of separator: fsStyle=%x\n",
-                 btnPtr->fsStyle);
-       }
-       return;
+            else {
+                TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
+            }
+        }
+        else if (btnPtr->fsStyle != BTNS_SEP) {
+            FIXME("Draw some kind of separator: fsStyle=%x\n",
+              btnPtr->fsStyle);
+        }
+        return;
     }
 
     /* get a pointer to the text */
@@ -879,8 +1001,8 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
     /* copy text & bitmap rects after adjusting for drop-down arrow
      * so that text & bitmap is centered in the rectangle not containing
      * the arrow */
-    CopyRect(&rcText, &rc);
-    CopyRect(&rcBitmap, &rc);
+    rcText = rc;
+    rcBitmap = rc;
 
     /* Center the bitmap horizontally and vertically */
     if (dwStyle & TBSTYLE_LIST)
@@ -897,6 +1019,9 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
         rcBitmap.left += ((rc.right - rc.left) - infoPtr->nBitmapWidth) / 2;
 
     rcBitmap.top += infoPtr->szPadding.cy / 2;
+#ifdef __REACTOS__
+    rcBitmap.top += infoPtr->themeMargins.cyTopHeight;
+#endif
 
     TRACE("iBitmap=%d, start=(%d,%d) w=%d, h=%d\n",
       btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
@@ -907,8 +1032,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
     /* calculate text position */
     if (lpText)
     {
-        rcText.left += GetSystemMetrics(SM_CXEDGE);
-        rcText.right -= GetSystemMetrics(SM_CXEDGE);
+        InflateRect(&rcText, -GetSystemMetrics(SM_CXEDGE), 0);
         if (dwStyle & TBSTYLE_LIST)
         {
             rcText.left += infoPtr->nBitmapWidth + infoPtr->iListGap + 2;
@@ -940,7 +1064,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
     tbcd.rcText.bottom = rcText.bottom - rc.top;
     tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
     tbcd.nmcd.hdc = hdc;
-    tbcd.nmcd.rc = rc;
+    tbcd.nmcd.rc = btnPtr->rect;
     tbcd.hbrMonoDither = COMCTL32_hPattern55AABrush;
 
     /* FIXME: what are these used for? */
@@ -958,7 +1082,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
        ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
         /* reset these fields so the user can't alter the behaviour like native */
         tbcd.nmcd.hdc = hdc;
-        tbcd.nmcd.rc = rc;
+        tbcd.nmcd.rc = btnPtr->rect;
 
        dwItemCustDraw = ntfret & 0xffff;
        dwItemCDFlag = ntfret & 0xffff0000;
@@ -992,7 +1116,11 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
         }
     }
 
+#ifdef __REACTOS__
+    if (theme && !(dwItemCDFlag & TBCDRF_NOBACKGROUND))
+#else
     if (theme)
+#endif
     {
         int partId = drawSepDropDownArrow ? TP_SPLITBUTTON : TP_BUTTON;
         int stateId = TS_NORMAL;
@@ -1007,10 +1135,15 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
             || (drawSepDropDownArrow && btnPtr->bDropDownPressed))
             stateId = TS_HOT;
             
-        DrawThemeBackground (theme, hdc, partId, stateId, &tbcd.nmcd.rc, NULL);
+        DrawThemeBackground (theme, hdc, partId, stateId, &rc, NULL);
     }
+
+#ifdef __REACTOS__
+    if (!theme)
+#else
     else
-        TOOLBAR_DrawFrame(infoPtr, &tbcd, dwItemCDFlag);
+#endif
+        TOOLBAR_DrawFrame(infoPtr, &tbcd, &rc, dwItemCDFlag);
 
     if (drawSepDropDownArrow)
     {
@@ -1181,9 +1314,7 @@ TOOLBAR_MeasureString(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *btnPtr,
            GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
 
            /* feed above size into the rectangle for DrawText */
-           myrect.left = myrect.top = 0;
-           myrect.right = lpSize->cx;
-           myrect.bottom = lpSize->cy;
+            SetRect(&myrect, 0, 0, lpSize->cx, lpSize->cy);
 
            /* Use DrawText to get true size as drawn (less pesky "&") */
            DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE |
@@ -1268,8 +1399,7 @@ static void
 TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
 {
     TBUTTON_INFO *btnPtr;
-    INT x, cx, i, j;
-    RECT rc;
+    INT x, cx, i, j, width;
     BOOL bButtonWrap;
 
     /*         When the toolbar window style is not TBSTYLE_WRAPABLE,  */
@@ -1280,26 +1410,12 @@ TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
 
     btnPtr = infoPtr->buttons;
     x  = infoPtr->nIndent;
-
-    if (GetParent(infoPtr->hwndSelf))
-    {
-        /* this can get the parents width, to know how far we can extend
-         * this toolbar.  We cannot use its height, as there may be multiple
-         * toolbars in a rebar control
-         */
-        GetClientRect( GetParent(infoPtr->hwndSelf), &rc );
-        infoPtr->nWidth = rc.right - rc.left;
-    }
-    else
-    {
-        GetWindowRect( infoPtr->hwndSelf, &rc );
-        infoPtr->nWidth = rc.right - rc.left;
-    }
+    width = infoPtr->client_rect.right - infoPtr->client_rect.left;
 
     bButtonWrap = FALSE;
 
-    TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
-         infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
+    TRACE("start ButtonWidth=%d, BitmapWidth=%d, width=%d, nIndent=%d\n",
+         infoPtr->nButtonWidth, infoPtr->nBitmapWidth, width,
          infoPtr->nIndent);
 
     for (i = 0; i < infoPtr->nNumButtons; i++ )
@@ -1318,6 +1434,9 @@ TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
        else
            cx = infoPtr->nButtonWidth;
 
+        if (!btnPtr[i].cx && button_has_ddarrow( infoPtr, btnPtr + i ))
+            cx += DDARROW_WIDTH;
+
        /* Two or more adjacent separators form a separator group.   */
        /* The first separator in a group should be wrapped to the   */
        /* next row if the previous wrapping is on a button.         */
@@ -1337,9 +1456,8 @@ TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
        /* The layout makes sure the bitmap is visible, but not the button. */
        /* Test added to also wrap after a button that starts a row but     */
        /* is bigger than the area.  - GA  8/01                             */
-       if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
-          > infoPtr->nWidth ) ||
-           ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
+        if ((x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 > width) ||
+            ((x == infoPtr->nIndent) && (cx > width)))
        {
            BOOL bFound = FALSE;
 
@@ -1550,9 +1668,14 @@ static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeS
         /* ... add on the necessary padding */
         if (bValidImageList)
         {
+#ifdef __REACTOS__
+            sizeButton.cy += infoPtr->szPadding.cy;
+            if (!bHasBitmap)
+#else
             if (bHasBitmap)
                 sizeButton.cy += DEFPAD_CY;
             else
+#endif
                 sizeButton.cy += LISTPAD_CY;
         }
         else
@@ -1569,7 +1692,11 @@ static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeS
     {
         if (bHasBitmap)
         {
+#ifdef __REACTOS__
+            sizeButton.cy = infoPtr->nBitmapHeight + infoPtr->szPadding.cy;
+#else
             sizeButton.cy = infoPtr->nBitmapHeight + DEFPAD_CY;
+#endif
             if (sizeString.cy > 0)
                 sizeButton.cy += 1 + sizeString.cy;
             sizeButton.cx = infoPtr->szPadding.cx +
@@ -1583,6 +1710,12 @@ static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeS
                 max(2*GetSystemMetrics(SM_CXEDGE) + sizeString.cx, infoPtr->nBitmapWidth);
         }
     }
+
+#ifdef __REACTOS__
+    sizeButton.cx += infoPtr->themeMargins.cxLeftWidth + infoPtr->themeMargins.cxRightWidth;
+    sizeButton.cy += infoPtr->themeMargins.cyTopHeight + infoPtr->themeMargins.cyBottomHeight;
+#endif
+
     return sizeButton;
 }
 
@@ -1631,7 +1764,6 @@ TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
     INT x, y, cx, cy;
     BOOL bWrap;
     BOOL validImageList = TOOLBAR_IsValidImageList(infoPtr, 0);
-    BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
 
     TOOLBAR_WrapToolbar(infoPtr);
 
@@ -1657,6 +1789,7 @@ TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
        if (btnPtr->fsState & TBSTATE_HIDDEN)
        {
            SetRectEmpty (&btnPtr->rect);
+           TOOLBAR_TooltipSetRect(infoPtr, btnPtr);
            continue;
        }
 
@@ -1675,8 +1808,14 @@ TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
        {
             if (btnPtr->cx)
               cx = btnPtr->cx;
+#ifdef __REACTOS__
+            /* Revert Wine Commit 5b7b911 as it breaks Explorer Toolbar Buttons
+               FIXME: Revisit this when the bug is fixed. CORE-9970 */
             else if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || 
                 (btnPtr->fsStyle & BTNS_AUTOSIZE))
+#else
+            else if (btnPtr->fsStyle & BTNS_AUTOSIZE)
+#endif
             {
               SIZE sz;
              HDC hdc;
@@ -1700,11 +1839,10 @@ TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
 
             /* if size has been set manually then don't add on extra space
              * for the drop down arrow */
-           if (!btnPtr->cx && hasDropDownArrows && 
-                ((btnPtr->fsStyle & BTNS_DROPDOWN) || (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)))
-             cx += DDARROW_WIDTH;
+            if (!btnPtr->cx && button_has_ddarrow( infoPtr, btnPtr ))
+              cx += DDARROW_WIDTH;
        }
-       if (btnPtr->fsState & TBSTATE_WRAP )
+       if (btnPtr->fsState & TBSTATE_WRAP)
                    bWrap = TRUE;
 
        SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
@@ -1816,6 +1954,7 @@ TOOLBAR_InternalInsertButtonsT(TOOLBAR_INFO *infoPtr, INT iIndex, UINT nAddButto
     /* insert new buttons data */
     for (iButton = 0; iButton < nAddButtons; iButton++) {
         TBUTTON_INFO *btnPtr = &infoPtr->buttons[iIndex + iButton];
+        INT_PTR str;
 
         TOOLBAR_DumpTBButton(lpTbb + iButton, fUnicode);
 
@@ -1826,18 +1965,13 @@ TOOLBAR_InternalInsertButtonsT(TOOLBAR_INFO *infoPtr, INT iIndex, UINT nAddButto
         btnPtr->fsState   = lpTbb[iButton].fsState;
         btnPtr->fsStyle   = lpTbb[iButton].fsStyle;
         btnPtr->dwData    = lpTbb[iButton].dwData;
+
         if (btnPtr->fsStyle & BTNS_SEP)
-            btnPtr->iString = -1;
-        else if(!IS_INTRESOURCE(lpTbb[iButton].iString) && lpTbb[iButton].iString != -1)
-        {
-            if (fUnicode)
-                Str_SetPtrW((LPWSTR*)&btnPtr->iString, (LPWSTR)lpTbb[iButton].iString );
-            else
-                Str_SetPtrAtoW((LPWSTR*)&btnPtr->iString, (LPSTR)lpTbb[iButton].iString);
-            fHasString = TRUE;
-        }
+            str = -1;
         else
-            btnPtr->iString   = lpTbb[iButton].iString;
+            str = lpTbb[iButton].iString;
+        set_string_index( btnPtr, str, fUnicode );
+        fHasString |= TOOLBAR_ButtonHasString( btnPtr );
 
         TOOLBAR_TooltipAddTool(infoPtr, btnPtr);
     }
@@ -1940,6 +2074,7 @@ TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
     SendMessageW (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
 }
 
+
 static void
 TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button)
 {
@@ -2620,9 +2755,9 @@ TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                           lpdis->rcItem.right, lpdis->rcItem.bottom);
 
                /* calculate button and text rectangles */
-               CopyRect (&rcButton, &lpdis->rcItem);
+                rcButton = lpdis->rcItem;
                InflateRect (&rcButton, -1, -1);
-               CopyRect (&rcText, &rcButton);
+                rcText = rcButton;
                rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
                rcText.left = rcButton.right + 2;
 
@@ -3004,38 +3139,28 @@ TOOLBAR_AddStringA (TOOLBAR_INFO *infoPtr, HINSTANCE hInstance, LPARAM lParam)
 static LRESULT
 TOOLBAR_AutoSize (TOOLBAR_INFO *infoPtr)
 {
-    RECT parent_rect;
-    HWND parent;
-    INT  x, y;
-    INT  cx, cy;
-
     TRACE("auto sizing, style=%x!\n", infoPtr->dwStyle);
+    TRACE("nRows: %d, infoPtr->nButtonHeight: %d\n", infoPtr->nRows, infoPtr->nButtonHeight);
 
-    parent = GetParent (infoPtr->hwndSelf);
-
-    if (!parent || !infoPtr->bDoRedraw)
-        return 0;
-
-    GetClientRect(parent, &parent_rect);
+    if (!(infoPtr->dwStyle & CCS_NORESIZE))
+    {
+        RECT window_rect, parent_rect;
+        UINT uPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
+        HWND parent;
+        INT  x, y, cx, cy;
 
-    x = parent_rect.left;
-    y = parent_rect.top;
+        parent = GetParent (infoPtr->hwndSelf);
 
-    TRACE("nRows: %d, infoPtr->nButtonHeight: %d\n", infoPtr->nRows, infoPtr->nButtonHeight);
+        if (!parent || !infoPtr->bDoRedraw)
+            return 0;
 
-    cy = TOP_BORDER + infoPtr->nRows * infoPtr->nButtonHeight + BOTTOM_BORDER;
-    cx = parent_rect.right - parent_rect.left;
+        GetClientRect(parent, &parent_rect);
 
-    if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL))
-    {
-        TOOLBAR_LayoutToolbar(infoPtr);
-        InvalidateRect( infoPtr->hwndSelf, NULL, TRUE );
-    }
+        x = parent_rect.left;
+        y = parent_rect.top;
 
-    if (!(infoPtr->dwStyle & CCS_NORESIZE))
-    {
-        RECT window_rect;
-        UINT uPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
+        cy = TOP_BORDER + infoPtr->nRows * infoPtr->nButtonHeight + BOTTOM_BORDER;
+        cx = parent_rect.right - parent_rect.left;
 
         if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY)
         {
@@ -3064,6 +3189,12 @@ TOOLBAR_AutoSize (TOOLBAR_INFO *infoPtr)
         SetWindowPos(infoPtr->hwndSelf, NULL, x, y, cx, cy, uPosFlags);
     }
 
+    if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL))
+    {
+        TOOLBAR_LayoutToolbar(infoPtr);
+        InvalidateRect( infoPtr->hwndSelf, NULL, TRUE );
+    }
+
     return 0;
 }
 
@@ -3126,7 +3257,7 @@ TOOLBAR_CheckButton (TOOLBAR_INFO *infoPtr, INT Id, LPARAM lParam)
 
     bChecked = (btnPtr->fsState & TBSTATE_CHECKED) != 0;
 
-    if (LOWORD(lParam) == FALSE)
+    if (!LOWORD(lParam))
        btnPtr->fsState &= ~TBSTATE_CHECKED;
     else {
        if (btnPtr->fsStyle & BTNS_GROUP) {
@@ -3206,8 +3337,7 @@ TOOLBAR_DeleteButton (TOOLBAR_INFO *infoPtr, INT nIndex)
 
     if (infoPtr->nNumButtons == 1) {
        TRACE(" simple delete!\n");
-       if (TOOLBAR_ButtonHasString(infoPtr->buttons))
-           Free((LPWSTR)infoPtr->buttons[0].iString);
+        free_string( infoPtr->buttons );
        Free (infoPtr->buttons);
        infoPtr->buttons = NULL;
        infoPtr->nNumButtons = 0;
@@ -3228,8 +3358,7 @@ TOOLBAR_DeleteButton (TOOLBAR_INFO *infoPtr, INT nIndex)
                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
         }
 
-        if (TOOLBAR_ButtonHasString(&oldButtons[nIndex]))
-            Free((LPWSTR)oldButtons[nIndex].iString);
+        free_string( oldButtons + nIndex );
        Free (oldButtons);
     }
 
@@ -3260,7 +3389,7 @@ TOOLBAR_EnableButton (TOOLBAR_INFO *infoPtr, INT Id, LPARAM lParam)
     bState = btnPtr->fsState & TBSTATE_ENABLED;
 
     /* update the toolbar button state */
-    if(LOWORD(lParam) == FALSE) {
+    if(!LOWORD(lParam)) {
        btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
     } else {
        btnPtr->fsState |= TBSTATE_ENABLED;
@@ -3350,8 +3479,7 @@ TOOLBAR_GetButtonInfoT(const TOOLBAR_INFO *infoPtr, INT Id, LPTBBUTTONINFOW lpTb
     if (nIndex == -1)
        return -1;
 
-    if (!(btnPtr = &infoPtr->buttons[nIndex])) return -1;
-
+    btnPtr = &infoPtr->buttons[nIndex];
     if (lpTbInfo->dwMask & TBIF_COMMAND)
        lpTbInfo->idCommand = btnPtr->idCommand;
     if (lpTbInfo->dwMask & TBIF_IMAGE)
@@ -3377,7 +3505,7 @@ TOOLBAR_GetButtonInfoT(const TOOLBAR_INFO *infoPtr, INT Id, LPTBBUTTONINFOW lpTb
                 Str_GetPtrW(lpText, lpTbInfo->pszText, lpTbInfo->cchText);
             else
                 Str_GetPtrWtoA(lpText, (LPSTR)lpTbInfo->pszText, lpTbInfo->cchText);
-        } else
+        } else if (!bUnicode || lpTbInfo->pszText)
             lpTbInfo->pszText[0] = '\0';
     }
     return nIndex;
@@ -3528,6 +3656,36 @@ TOOLBAR_GetMaxSize (const TOOLBAR_INFO *infoPtr, LPSIZE lpSize)
     return TRUE;
 }
 
+#ifdef __REACTOS__
+static LRESULT
+TOOLBAR_GetMetrics(const TOOLBAR_INFO *infoPtr, TBMETRICS *pMetrics)
+{
+    if (pMetrics == NULL)
+        return FALSE;
+
+    /* TODO: check if cbSize is a valid value */
+
+    if (pMetrics->dwMask & TBMF_PAD)
+    {
+        pMetrics->cxPad = infoPtr->szPadding.cx;
+        pMetrics->cyPad = infoPtr->szPadding.cy;
+    }
+
+    if (pMetrics->dwMask & TBMF_BARPAD)
+    {
+        pMetrics->cxBarPad = infoPtr->szBarPadding.cx;
+        pMetrics->cyBarPad = infoPtr->szBarPadding.cy;
+    }
+
+    if (pMetrics->dwMask & TBMF_BUTTONSPACING)
+    {
+        pMetrics->cxButtonSpacing = infoPtr->szSpacing.cx;
+        pMetrics->cyButtonSpacing = infoPtr->szSpacing.cy;
+    }
+
+    return TRUE;
+}
+#endif
 
 /* << TOOLBAR_GetObject >> */
 
@@ -4050,12 +4208,55 @@ TOOLBAR_ReplaceBitmap (TOOLBAR_INFO *infoPtr, const TBREPLACEBITMAP *lpReplace)
 
 /* helper for TOOLBAR_SaveRestoreW */
 static BOOL
-TOOLBAR_Save(const TBSAVEPARAMSW *lpSave)
+TOOLBAR_Save(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *params)
 {
-    FIXME("save to %s %s\n", debugstr_w(lpSave->pszSubKey),
-        debugstr_w(lpSave->pszValueName));
+    NMTBSAVE save;
+    INT ret, i;
+    BOOL alloced = FALSE;
+    HKEY key;
 
-    return FALSE;
+    TRACE( "save to %s %s\n", debugstr_w(params->pszSubKey), debugstr_w(params->pszValueName) );
+
+    memset( &save, 0, sizeof(save) );
+    save.cbData = infoPtr->nNumButtons * sizeof(DWORD);
+    save.iItem = -1;
+    save.cButtons = infoPtr->nNumButtons;
+    save.tbButton.idCommand = -1;
+    TOOLBAR_SendNotify( &save.hdr, infoPtr, TBN_SAVE );
+
+    if (!save.pData)
+    {
+        save.pData = Alloc( save.cbData );
+        if (!save.pData) return FALSE;
+        alloced = TRUE;
+    }
+    if (!save.pCurrent) save.pCurrent = save.pData;
+
+    for (i = 0; i < infoPtr->nNumButtons; i++)
+    {
+        save.iItem = i;
+        save.tbButton.iBitmap = infoPtr->buttons[i].iBitmap;
+        save.tbButton.idCommand = infoPtr->buttons[i].idCommand;
+        save.tbButton.fsState = infoPtr->buttons[i].fsState;
+        save.tbButton.fsStyle = infoPtr->buttons[i].fsStyle;
+        memset( save.tbButton.bReserved, 0, sizeof(save.tbButton.bReserved) );
+        save.tbButton.dwData = infoPtr->buttons[i].dwData;
+        save.tbButton.iString = infoPtr->buttons[i].iString;
+
+        *save.pCurrent++ = save.tbButton.idCommand;
+
+        TOOLBAR_SendNotify( &save.hdr, infoPtr, TBN_SAVE );
+    }
+
+    ret = RegCreateKeyW( params->hkr, params->pszSubKey, &key );
+    if (ret == ERROR_SUCCESS)
+    {
+        ret = RegSetValueExW( key, params->pszValueName, 0, REG_BINARY, (BYTE *)save.pData, save.cbData );
+        RegCloseKey( key );
+    }
+
+    if (alloced) Free( save.pData );
+    return !ret;
 }
 
 
@@ -4067,6 +4268,7 @@ TOOLBAR_DeleteAllButtons(TOOLBAR_INFO *infoPtr)
 
     for (i = 0; i < infoPtr->nNumButtons; i++)
     {
+        free_string( infoPtr->buttons + i );
         TOOLBAR_TooltipDelTool(infoPtr, &infoPtr->buttons[i]);
     }
 
@@ -4086,6 +4288,7 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave)
     DWORD dwType;
     DWORD dwSize = 0;
     NMTBRESTORE nmtbr;
+    NMHDR hdr;
 
     /* restore toolbar information */
     TRACE("restore from %s %s\n", debugstr_w(lpSave->pszSubKey),
@@ -4118,30 +4321,30 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave)
 
         if (!TOOLBAR_SendNotify(&nmtbr.hdr, infoPtr, TBN_RESTORE))
         {
-            INT i;
+            INT i, count = nmtbr.cButtons;
 
             /* remove all existing buttons as this function is designed to
              * restore the toolbar to a previously saved state */
             TOOLBAR_DeleteAllButtons(infoPtr);
 
-            for (i = 0; i < nmtbr.cButtons; i++)
+            for (i = 0; i < count; i++)
             {
                 nmtbr.iItem = i;
                 nmtbr.tbButton.iBitmap = -1;
                 nmtbr.tbButton.fsState = 0;
                 nmtbr.tbButton.fsStyle = 0;
-                nmtbr.tbButton.idCommand = 0;
-                if (*nmtbr.pCurrent == (DWORD)-1)
+                nmtbr.tbButton.dwData = 0;
+                nmtbr.tbButton.iString = 0;
+
+                if (*nmtbr.pCurrent & 0x80000000)
                 {
                     /* separator */
-                    nmtbr.tbButton.fsStyle = TBSTYLE_SEP;
-                    /* when inserting separators, iBitmap controls its size.
-                       0 sets default size (width) */
-                    nmtbr.tbButton.iBitmap = 0;
+                    nmtbr.tbButton.iBitmap = SEPARATOR_WIDTH;
+                    nmtbr.tbButton.idCommand = 0;
+                    nmtbr.tbButton.fsStyle = BTNS_SEP;
+                    if (*nmtbr.pCurrent != (DWORD)-1)
+                        nmtbr.tbButton.fsState = TBSTATE_HIDDEN;
                 }
-                else if (*nmtbr.pCurrent == (DWORD)-2)
-                    /* hidden button */
-                    nmtbr.tbButton.fsState = TBSTATE_HIDDEN;
                 else
                     nmtbr.tbButton.idCommand = (int)*nmtbr.pCurrent;
 
@@ -4149,21 +4352,51 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave)
                 
                 TOOLBAR_SendNotify(&nmtbr.hdr, infoPtr, TBN_RESTORE);
 
-                /* can't contain real string as we don't know whether
-                 * the client put an ANSI or Unicode string in there */
+                /* All returned ptrs and -1 are ignored */
                 if (!IS_INTRESOURCE(nmtbr.tbButton.iString))
                     nmtbr.tbButton.iString = 0;
 
                 TOOLBAR_InsertButtonT(infoPtr, -1, &nmtbr.tbButton, TRUE);
             }
 
-            /* do legacy notifications */
-            if (infoPtr->iVersion < 5)
+            TOOLBAR_SendNotify( &hdr, infoPtr, TBN_BEGINADJUST );
+            for (i = 0; ; i++)
             {
-                /* FIXME: send TBN_BEGINADJUST */
-                FIXME("send TBN_GETBUTTONINFO for each button\n");
-                /* FIXME: send TBN_ENDADJUST */
+                NMTOOLBARW tb;
+                TBBUTTONINFOW bi;
+                WCHAR buf[128];
+                UINT code = infoPtr->bUnicode ? TBN_GETBUTTONINFOW : TBN_GETBUTTONINFOA;
+                INT idx;
+
+                memset( &tb, 0, sizeof(tb) );
+                tb.iItem = i;
+                tb.cchText = sizeof(buf) / sizeof(buf[0]);
+                tb.pszText = buf;
+
+                /* Use the same struct for both A and W versions since the layout is the same. */
+                if (!TOOLBAR_SendNotify( &tb.hdr, infoPtr, code ))
+                    break;
+
+                idx = TOOLBAR_GetButtonIndex( infoPtr, tb.tbButton.idCommand, FALSE );
+                if (idx == -1) continue;
+
+                /* tb.pszText is ignored - the string comes from tb.tbButton.iString, which may
+                   be an index or a ptr.  Either way it is simply copied.  There is no api to change
+                   the string index, so we set it manually.  The other properties can be set with SetButtonInfo. */
+                free_string( infoPtr->buttons + idx );
+                infoPtr->buttons[idx].iString = tb.tbButton.iString;
+
+                memset( &bi, 0, sizeof(bi) );
+                bi.cbSize = sizeof(bi);
+                bi.dwMask = TBIF_IMAGE | TBIF_STATE | TBIF_STYLE | TBIF_LPARAM;
+                bi.iImage = tb.tbButton.iBitmap;
+                bi.fsState = tb.tbButton.fsState;
+                bi.fsStyle = tb.tbButton.fsStyle;
+                bi.lParam = tb.tbButton.dwData;
+
+                TOOLBAR_SetButtonInfo( infoPtr, tb.tbButton.idCommand, &bi, TRUE );
             }
+            TOOLBAR_SendNotify( &hdr, infoPtr, TBN_ENDADJUST );
 
             /* remove all uninitialised buttons
              * note: loop backwards to avoid having to fixup i on a
@@ -4189,7 +4422,7 @@ TOOLBAR_SaveRestoreW (TOOLBAR_INFO *infoPtr, WPARAM wParam, const TBSAVEPARAMSW
     if (lpSave == NULL) return 0;
 
     if (wParam)
-        return TOOLBAR_Save(lpSave);
+        return TOOLBAR_Save(infoPtr, lpSave);
     else
         return TOOLBAR_Restore(infoPtr, lpSave);
 }
@@ -4207,7 +4440,7 @@ TOOLBAR_SaveRestoreA (TOOLBAR_INFO *infoPtr, WPARAM wParam, const TBSAVEPARAMSA
 
     len = MultiByteToWideChar(CP_ACP, 0, lpSave->pszSubKey, -1, NULL, 0);
     pszSubKey = Alloc(len * sizeof(WCHAR));
-    if (pszSubKey) goto exit;
+    if (!pszSubKey) goto exit;
     MultiByteToWideChar(CP_ACP, 0, lpSave->pszSubKey, -1, pszSubKey, len);
 
     len = MultiByteToWideChar(CP_ACP, 0, lpSave->pszValueName, -1, NULL, 0);
@@ -4324,15 +4557,8 @@ TOOLBAR_SetButtonInfo (TOOLBAR_INFO *infoPtr, INT Id,
     if (lptbbi->dwMask & TBIF_STYLE)
        btnPtr->fsStyle = lptbbi->fsStyle;
 
-    if ((lptbbi->dwMask & TBIF_TEXT) && ((INT_PTR)lptbbi->pszText != -1)) {
-        /* iString is index, zero it to make Str_SetPtr succeed */
-        if (!TOOLBAR_ButtonHasString(btnPtr)) btnPtr->iString = 0;
-
-        if (isW)
-            Str_SetPtrW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText);
-        else
-            Str_SetPtrAtoW ((LPWSTR *)&btnPtr->iString, (LPSTR)lptbbi->pszText);
-    }
+    if (lptbbi->dwMask & TBIF_TEXT)
+        set_stringT( btnPtr, lptbbi->pszText, isW );
 
     /* save the button rect to see if we need to redraw the whole toolbar */
     oldBtnRect = btnPtr->rect;
@@ -4351,6 +4577,7 @@ static LRESULT
 TOOLBAR_SetButtonSize (TOOLBAR_INFO *infoPtr, LPARAM lParam)
 {
     INT cx = (short)LOWORD(lParam), cy = (short)HIWORD(lParam);
+    int top = default_top_margin(infoPtr);
 
     if ((cx < 0) || (cy < 0))
     {
@@ -4373,15 +4600,25 @@ TOOLBAR_SetButtonSize (TOOLBAR_INFO *infoPtr, LPARAM lParam)
      */
     if (cx == 0) cx = 24;
     if (cy == 0) cy = 22;
-    
+
+#ifdef __REACTOS__
+    cx = max(cx, infoPtr->szPadding.cx + infoPtr->nBitmapWidth + infoPtr->themeMargins.cxLeftWidth + infoPtr->themeMargins.cxRightWidth);
+    cy = max(cy, infoPtr->szPadding.cy + infoPtr->nBitmapHeight + infoPtr->themeMargins.cyTopHeight + infoPtr->themeMargins.cyBottomHeight);
+#else
     cx = max(cx, infoPtr->szPadding.cx + infoPtr->nBitmapWidth);
     cy = max(cy, infoPtr->szPadding.cy + infoPtr->nBitmapHeight);
+#endif
 
-    infoPtr->nButtonWidth = cx;
-    infoPtr->nButtonHeight = cy;
-    
-    infoPtr->iTopMargin = default_top_margin(infoPtr);
-    TOOLBAR_LayoutToolbar(infoPtr);
+    if (cx != infoPtr->nButtonWidth || cy != infoPtr->nButtonHeight ||
+        top != infoPtr->iTopMargin)
+    {
+        infoPtr->nButtonWidth = cx;
+        infoPtr->nButtonHeight = cy;
+        infoPtr->iTopMargin = top;
+
+        TOOLBAR_LayoutToolbar( infoPtr );
+        InvalidateRect( infoPtr->hwndSelf, NULL, TRUE );
+    }
     return TRUE;
 }
 
@@ -4452,17 +4689,16 @@ TOOLBAR_SetDisabledImageList (TOOLBAR_INFO *infoPtr, WPARAM wParam, HIMAGELIST h
 
 
 static LRESULT
-TOOLBAR_SetDrawTextFlags (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+TOOLBAR_SetDrawTextFlags (TOOLBAR_INFO *infoPtr, DWORD mask, DWORD flags)
 {
-    DWORD dwTemp;
+    DWORD old_flags;
 
-    TRACE("hwnd = %p, dwMask = 0x%08x, dwDTFlags = 0x%08x\n", infoPtr->hwndSelf, (DWORD)wParam, (DWORD)lParam);
+    TRACE("hwnd = %p, mask = 0x%08x, flags = 0x%08x\n", infoPtr->hwndSelf, mask, flags);
 
-    dwTemp = infoPtr->dwDTFlags;
-    infoPtr->dwDTFlags =
-       (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
+    old_flags = infoPtr->dwDTFlags;
+    infoPtr->dwDTFlags = (old_flags & ~mask) | (flags & mask);
 
-    return (LRESULT)dwTemp;
+    return (LRESULT)old_flags;
 }
 
 /* This function differs a bit from what MSDN says it does:
@@ -4709,6 +4945,44 @@ TOOLBAR_SetMaxTextRows (TOOLBAR_INFO *infoPtr, INT nMaxRows)
     return TRUE;
 }
 
+#ifdef __REACTOS__
+static LRESULT
+TOOLBAR_SetMetrics(TOOLBAR_INFO *infoPtr, TBMETRICS *pMetrics)
+{
+    BOOL changed = FALSE;
+
+    if (!pMetrics)
+        return FALSE;
+
+    /* TODO: check if cbSize is a valid value */
+
+    if (pMetrics->dwMask & TBMF_PAD)
+    {
+        infoPtr->szPadding.cx = pMetrics->cxPad;
+        infoPtr->szPadding.cy = pMetrics->cyPad;
+        changed = TRUE;
+    }
+
+    if (pMetrics->dwMask & TBMF_PAD)
+    {
+        infoPtr->szBarPadding.cx = pMetrics->cxBarPad;
+        infoPtr->szBarPadding.cy = pMetrics->cyBarPad;
+        changed = TRUE;
+    }
+
+    if (pMetrics->dwMask & TBMF_BUTTONSPACING)
+    {
+        infoPtr->szSpacing.cx = pMetrics->cxButtonSpacing;
+        infoPtr->szSpacing.cy = pMetrics->cyButtonSpacing;
+        changed = TRUE;
+    }
+
+    if (changed)
+        TOOLBAR_CalcToolbar(infoPtr);
+
+    return TRUE;
+}
+#endif
 
 /* MSDN gives slightly wrong info on padding.
  * 1. It is not only used on buttons with the BTNS_AUTOSIZE style
@@ -4899,11 +5173,45 @@ TOOLBAR_SetState (TOOLBAR_INFO *infoPtr, INT Id, LPARAM lParam)
     return TRUE;
 }
 
+static inline void unwrap(TOOLBAR_INFO *info)
+{
+    int i;
+
+    for (i = 0; i < info->nNumButtons; i++)
+       info->buttons[i].fsState &= ~TBSTATE_WRAP;
+}
 
 static LRESULT
 TOOLBAR_SetStyle (TOOLBAR_INFO *infoPtr, DWORD style)
 {
+    DWORD dwOldStyle = infoPtr->dwStyle;
+
+    TRACE("new style 0x%08x\n", style);
+
+    if (style & TBSTYLE_LIST)
+        infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS;
+    else
+        infoPtr->dwDTFlags = DT_CENTER | DT_END_ELLIPSIS;
+
     infoPtr->dwStyle = style;
+    TOOLBAR_CheckStyle(infoPtr);
+
+    if ((dwOldStyle ^ style) & TBSTYLE_WRAPABLE)
+    {
+        if (dwOldStyle & TBSTYLE_WRAPABLE)
+            unwrap(infoPtr);
+        TOOLBAR_CalcToolbar(infoPtr);
+    }
+    else if ((dwOldStyle ^ style) & CCS_VERT)
+        TOOLBAR_LayoutToolbar(infoPtr);
+
+    /* only resize if one of the CCS_* styles was changed */
+    if ((dwOldStyle ^ style) & COMMON_STYLES)
+    {
+        TOOLBAR_AutoSize(infoPtr);
+        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
+    }
+
     return 0;
 }
 
@@ -4964,6 +5272,16 @@ TOOLBAR_SetVersion (TOOLBAR_INFO *infoPtr, INT iVersion)
 {
     INT iOldVersion = infoPtr->iVersion;
 
+#ifdef __REACTOS__
+    /* The v6 control doesn't support changing its version */
+    if (iOldVersion == 6)
+        return iOldVersion;
+
+    /* And a control that is not v6 can't be set to be a v6 one */
+    if (iVersion >= 6)
+        return -1;
+#endif
+
     infoPtr->iVersion = iVersion;
 
     if (infoPtr->iVersion >= 5)
@@ -5024,16 +5342,13 @@ TOOLBAR_GetStringW (const TOOLBAR_INFO *infoPtr, WPARAM wParam, LPWSTR str)
     return ret;
 }
 
-/* UNDOCUMENTED MESSAGE: This appears to set some kind of size. Perhaps it
- * is the maximum size of the toolbar? */
-static LRESULT TOOLBAR_Unkwn45D(HWND hwnd, WPARAM wParam, LPARAM lParam)
+static LRESULT TOOLBAR_SetBoundingSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     SIZE * pSize = (SIZE*)lParam;
     FIXME("hwnd=%p, wParam=0x%08lx, size.cx=%d, size.cy=%d stub!\n", hwnd, wParam, pSize->cx, pSize->cy);
     return 0;
 }
 
-
 /* This is an extended version of the TB_SETHOTITEM message. It allows the
  * caller to specify a reason why the hot item changed (rather than just the
  * HICF_OTHER that TB_SETHOTITEM sends). */
@@ -5053,8 +5368,6 @@ TOOLBAR_SetHotItem2 (TOOLBAR_INFO *infoPtr, INT nHotItem, LPARAM lParam)
 
     TOOLBAR_SetHotItemEx(infoPtr, nHotItem, lParam);
 
-    GetFocus();
-
     return (nOldHotItem < 0) ? -1 : (LRESULT)nOldHotItem;
 }
 
@@ -5155,8 +5468,16 @@ TOOLBAR_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
 
     SystemParametersInfoW (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
     infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectW (&logFont);
-    
+
+#ifdef __REACTOS__
+    {
+        HTHEME theme = OpenThemeData (hwnd, themeClass);
+        if (theme)
+            GetThemeMargins(theme, NULL, TP_BUTTON, TS_NORMAL, TMT_CONTENTMARGINS, NULL, &infoPtr->themeMargins);
+    }
+#else
     OpenThemeData (hwnd, themeClass);
+#endif
 
     TOOLBAR_CheckStyle (infoPtr);
 
@@ -5179,8 +5500,7 @@ TOOLBAR_Destroy (TOOLBAR_INFO *infoPtr)
 
     /* delete button data */
     for (i = 0; i < infoPtr->nNumButtons; i++)
-        if (TOOLBAR_ButtonHasString(&infoPtr->buttons[i]))
-            Free ((LPWSTR)infoPtr->buttons[i].iString);
+        free_string( infoPtr->buttons + i );
     Free (infoPtr->buttons);
 
     /* delete strings */
@@ -5408,95 +5728,92 @@ TOOLBAR_LButtonDown (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     nHit = TOOLBAR_InternalHitTest (infoPtr, &pt, &button);
 
     if (button)
+    {
         btnPtr = &infoPtr->buttons[nHit];
 
-    if (button && bDragKeyPressed && (infoPtr->dwStyle & CCS_ADJUSTABLE))
-    {
-        infoPtr->nButtonDrag = nHit;
-        SetCapture (infoPtr->hwndSelf);
-        
-        /* If drag cursor has not been loaded, load it.
-         * Note: it doesn't need to be freed */
-        if (!hCursorDrag)
-            hCursorDrag = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_MOVEBUTTON);
-        SetCursor(hCursorDrag);
-    }
-    else if (button)
-    {
-       RECT arrowRect;
-       infoPtr->nOldHit = nHit;
-
-       CopyRect(&arrowRect, &btnPtr->rect);
-       arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
-
-       /* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
-       if ((btnPtr->fsState & TBSTATE_ENABLED) && 
-            ((btnPtr->fsStyle & BTNS_WHOLEDROPDOWN) ||
-             ((btnPtr->fsStyle & BTNS_DROPDOWN) &&
-              ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
-              (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))))
-       {
-           LRESULT res;
+        if (bDragKeyPressed && (infoPtr->dwStyle & CCS_ADJUSTABLE))
+        {
+            infoPtr->nButtonDrag = nHit;
+            SetCapture (infoPtr->hwndSelf);
+
+            /* If drag cursor has not been loaded, load it.
+             * Note: it doesn't need to be freed */
+            if (!hCursorDrag)
+                hCursorDrag = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_MOVEBUTTON);
+            SetCursor(hCursorDrag);
+        }
+        else
+        {
+            RECT arrowRect;
+            infoPtr->nOldHit = nHit;
 
-           /* draw in pressed state */
-           if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)
-               btnPtr->fsState |= TBSTATE_PRESSED;
-           else
-               btnPtr->bDropDownPressed = TRUE;
-           RedrawWindow(infoPtr->hwndSelf,&btnPtr->rect,0,
-                       RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
-
-           memset(&nmtb, 0, sizeof(nmtb));
-           nmtb.iItem = btnPtr->idCommand;
-           nmtb.rcButton = btnPtr->rect;
-           res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
-                                 TBN_DROPDOWN);
-           TRACE("TBN_DROPDOWN responded with %ld\n", res);
-
-            if (res != TBDDRET_TREATPRESSED)
+            arrowRect = btnPtr->rect;
+            arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
+
+            /* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
+            if ((btnPtr->fsState & TBSTATE_ENABLED) &&
+                 ((btnPtr->fsStyle & BTNS_WHOLEDROPDOWN) ||
+                  ((btnPtr->fsStyle & BTNS_DROPDOWN) &&
+                   ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
+                   (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))))
             {
-                MSG msg;
+                LRESULT res;
 
-                /* redraw button in unpressed state */
-               if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)
-                           btnPtr->fsState &= ~TBSTATE_PRESSED;
-                       else
-                           btnPtr->bDropDownPressed = FALSE;
-                InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
+                /* draw in pressed state */
+                if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)
+                    btnPtr->fsState |= TBSTATE_PRESSED;
+                else
+                    btnPtr->bDropDownPressed = TRUE;
+                RedrawWindow(infoPtr->hwndSelf, &btnPtr->rect, 0, RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
 
-                /* find and set hot item */
-                GetCursorPos(&pt);
-                ScreenToClient(infoPtr->hwndSelf, &pt);
-                nHit = TOOLBAR_InternalHitTest(infoPtr, &pt, &button);
-                if (!infoPtr->bAnchor || button)
-                    TOOLBAR_SetHotItemEx(infoPtr, button ? nHit : TOOLBAR_NOWHERE, HICF_MOUSE | HICF_LMOUSE);
-                
-                /* remove any left mouse button down or double-click messages
-                 * so that we can get a toggle effect on the button */
-                while (PeekMessageW(&msg, infoPtr->hwndSelf, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE) ||
-                       PeekMessageW(&msg, infoPtr->hwndSelf, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, PM_REMOVE))
-                    ;
+                memset(&nmtb, 0, sizeof(nmtb));
+                nmtb.iItem = btnPtr->idCommand;
+                nmtb.rcButton = btnPtr->rect;
+                res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_DROPDOWN);
+                TRACE("TBN_DROPDOWN responded with %ld\n", res);
 
-               return 0;
+                if (res != TBDDRET_TREATPRESSED)
+                {
+                    MSG msg;
+
+                    /* redraw button in unpressed state */
+                    if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)
+                        btnPtr->fsState &= ~TBSTATE_PRESSED;
+                    else
+                        btnPtr->bDropDownPressed = FALSE;
+                    InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
+
+                    /* find and set hot item */
+                    GetCursorPos(&pt);
+                    ScreenToClient(infoPtr->hwndSelf, &pt);
+                    nHit = TOOLBAR_InternalHitTest(infoPtr, &pt, &button);
+                    if (!infoPtr->bAnchor || button)
+                        TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE);
+
+                    /* remove any left mouse button down or double-click messages
+                     * so that we can get a toggle effect on the button */
+                    while (PeekMessageW(&msg, infoPtr->hwndSelf, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE) ||
+                           PeekMessageW(&msg, infoPtr->hwndSelf, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, PM_REMOVE))
+                        ;
+
+                    return 0;
+                }
+                /* otherwise drop through and process as pushed */
             }
-           /* otherwise drop through and process as pushed */
-               }
-       infoPtr->bCaptured = TRUE;
-       infoPtr->nButtonDown = nHit;
-       infoPtr->bDragOutSent = FALSE;
+            infoPtr->bCaptured = TRUE;
+            infoPtr->nButtonDown = nHit;
+            infoPtr->bDragOutSent = FALSE;
 
-       btnPtr->fsState |= TBSTATE_PRESSED;
+            btnPtr->fsState |= TBSTATE_PRESSED;
 
-        TOOLBAR_SetHotItemEx(infoPtr, button ? nHit : TOOLBAR_NOWHERE, HICF_MOUSE | HICF_LMOUSE);
+            TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE);
 
-        if (btnPtr->fsState & TBSTATE_ENABLED)
-           InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
-       UpdateWindow(infoPtr->hwndSelf);
-       SetCapture (infoPtr->hwndSelf);
-    }
+            if (btnPtr->fsState & TBSTATE_ENABLED)
+                InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
+            UpdateWindow(infoPtr->hwndSelf);
+            SetCapture (infoPtr->hwndSelf);
+        }
 
-    if (button)
-    {
         memset(&nmtb, 0, sizeof(nmtb));
         nmtb.iItem = btnPtr->idCommand;
         TOOLBAR_SendNotify((NMHDR *)&nmtb, infoPtr, TBN_BEGINDRAG);
@@ -5883,7 +6200,11 @@ TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
 
 
 static LRESULT
+#ifdef __REACTOS__
+TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, const CREATESTRUCTW *lpcs, int iVersion)
+#else
 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, const CREATESTRUCTW *lpcs)
+#endif
 {
     TOOLBAR_INFO *infoPtr;
     DWORD styleadd = 0;
@@ -5895,7 +6216,6 @@ TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, const CREATESTRUCTW *lpcs)
     /* paranoid!! */
     infoPtr->dwStructSize = sizeof(TBBUTTON);
     infoPtr->nRows = 1;
-    infoPtr->nWidth = 0;
 
     /* initialize info structure */
     infoPtr->nButtonWidth = 23;
@@ -5918,13 +6238,22 @@ TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, const CREATESTRUCTW *lpcs)
     infoPtr->dwDTFlags = (lpcs->style & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS: DT_CENTER | DT_END_ELLIPSIS;
     infoPtr->bAnchor = FALSE; /* no anchor highlighting */
     infoPtr->bDragOutSent = FALSE;
+#ifdef __REACTOS__
+    infoPtr->iVersion = iVersion;
+#else
     infoPtr->iVersion = 0;
+#endif
     infoPtr->hwndSelf = hwnd;
     infoPtr->bDoRedraw = TRUE;
     infoPtr->clrBtnHighlight = CLR_DEFAULT;
     infoPtr->clrBtnShadow = CLR_DEFAULT;
     infoPtr->szPadding.cx = DEFPAD_CX;
     infoPtr->szPadding.cy = DEFPAD_CY;
+#ifdef __REACTOS__
+    infoPtr->szSpacing.cx = DEFSPACE_CX;
+    infoPtr->szSpacing.cy = DEFSPACE_CY;
+    memset(&infoPtr->themeMargins, 0 , sizeof(infoPtr->themeMargins));
+#endif
     infoPtr->iListGap = DEFLISTGAP;
     infoPtr->iTopMargin = default_top_margin(infoPtr);
     infoPtr->dwStyle = lpcs->style;
@@ -6320,30 +6649,7 @@ static LRESULT
 TOOLBAR_StyleChanged (TOOLBAR_INFO *infoPtr, INT nType, const STYLESTRUCT *lpStyle)
 {
     if (nType == GWL_STYLE)
-    {
-        DWORD dwOldStyle = infoPtr->dwStyle;
-
-        if (lpStyle->styleNew & TBSTYLE_LIST)
-            infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS;
-        else
-            infoPtr->dwDTFlags = DT_CENTER | DT_END_ELLIPSIS;
-
-        TRACE("new style 0x%08x\n", lpStyle->styleNew);
-
-        infoPtr->dwStyle = lpStyle->styleNew;
-        TOOLBAR_CheckStyle (infoPtr);
-
-        if ((dwOldStyle ^ lpStyle->styleNew) & (TBSTYLE_WRAPABLE | CCS_VERT))
-            TOOLBAR_LayoutToolbar(infoPtr);
-
-        /* only resize if one of the CCS_* styles was changed */
-        if ((dwOldStyle ^ lpStyle->styleNew) & COMMON_STYLES)
-        {
-            TOOLBAR_AutoSize (infoPtr);
-    
-            InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
-        }
-    }
+        return TOOLBAR_SetStyle(infoPtr, lpStyle->styleNew);
 
     return 0;
 }
@@ -6357,8 +6663,22 @@ TOOLBAR_SysColorChange (void)
     return 0;
 }
 
-
+#ifdef __REACTOS__
 /* update theme after a WM_THEMECHANGED message */
+static LRESULT theme_changed (TOOLBAR_INFO *infoPtr)
+{
+    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
+    CloseThemeData (theme);
+    OpenThemeData (infoPtr->hwndSelf, themeClass);
+    theme = GetWindowTheme (infoPtr->hwndSelf);
+    if (theme)
+        GetThemeMargins(theme, NULL, TP_BUTTON, TS_NORMAL, TMT_CONTENTMARGINS, NULL, &infoPtr->themeMargins);
+    else
+        memset(&infoPtr->themeMargins, 0 ,sizeof(infoPtr->themeMargins));
+
+    return 0;
+}
+#else
 static LRESULT theme_changed (HWND hwnd)
 {
     HTHEME theme = GetWindowTheme (hwnd);
@@ -6366,7 +6686,7 @@ static LRESULT theme_changed (HWND hwnd)
     OpenThemeData (hwnd, themeClass);
     return 0;
 }
-
+#endif
 
 static LRESULT WINAPI
 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -6471,6 +6791,10 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
        case TB_GETMAXSIZE:
            return TOOLBAR_GetMaxSize (infoPtr, (LPSIZE)lParam);
+#ifdef __REACTOS__
+       case TB_GETMETRICS:
+           return TOOLBAR_GetMetrics (infoPtr, (TBMETRICS*)lParam);
+#endif
 
 /*     case TB_GETOBJECT:                      */ /* 4.71 */
 
@@ -6612,6 +6936,11 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        case TB_SETMAXTEXTROWS:
            return TOOLBAR_SetMaxTextRows (infoPtr, wParam);
 
+#ifdef __REACTOS__
+       case TB_SETMETRICS:
+           return TOOLBAR_SetMetrics (infoPtr, (TBMETRICS*)lParam);
+#endif
+
        case TB_SETPADDING:
            return TOOLBAR_SetPadding (infoPtr, lParam);
 
@@ -6633,8 +6962,8 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        case TB_SETUNICODEFORMAT:
            return TOOLBAR_SetUnicodeFormat (infoPtr, wParam);
 
-       case TB_UNKWN45D:
-           return TOOLBAR_Unkwn45D(hwnd, wParam, lParam);
+       case TB_SETBOUNDINGSIZE:
+           return TOOLBAR_SetBoundingSize(hwnd, wParam, lParam);
 
        case TB_SETHOTITEM2:
            return TOOLBAR_SetHotItem2 (infoPtr, wParam, lParam);
@@ -6709,6 +7038,7 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
            return TOOLBAR_MouseLeave (infoPtr);
 
        case WM_CAPTURECHANGED:
+           if (hwnd == (HWND)lParam) return 0;
            return TOOLBAR_CaptureChanged(infoPtr);
 
        case WM_NCACTIVATE:
@@ -6718,7 +7048,11 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
            return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
 
        case WM_NCCREATE:
+#ifdef __REACTOS__
+           return TOOLBAR_NCCreate (hwnd, wParam, (CREATESTRUCTW*)lParam, 0);
+#else
            return TOOLBAR_NCCreate (hwnd, wParam, (CREATESTRUCTW*)lParam);
+#endif
 
        case WM_NCPAINT:
            return TOOLBAR_NCPaint (hwnd, wParam, lParam);
@@ -6750,9 +7084,12 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
        case WM_SYSCOLORCHANGE:
            return TOOLBAR_SysColorChange ();
-            
-        case WM_THEMECHANGED:
+    case WM_THEMECHANGED:
+#ifdef __REACTOS__
+            return theme_changed (infoPtr);
+#else
             return theme_changed (hwnd);
+#endif
 
 /*     case WM_WININICHANGE: */
 
@@ -6800,6 +7137,40 @@ TOOLBAR_Unregister (void)
     UnregisterClassW (TOOLBARCLASSNAMEW, NULL);
 }
 
+#ifdef __REACTOS__
+static LRESULT WINAPI
+ToolbarV6WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    if (uMsg == WM_NCCREATE)
+        return TOOLBAR_NCCreate (hwnd, wParam, (CREATESTRUCTW*)lParam, 6);
+    else
+        return ToolbarWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+VOID
+TOOLBARv6_Register (void)
+{
+    WNDCLASSW wndClass;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
+    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.lpfnWndProc   = ToolbarV6WindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
+    wndClass.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
+    wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+    wndClass.lpszClassName = TOOLBARCLASSNAMEW;
+
+    RegisterClassW (&wndClass);
+}
+
+VOID
+TOOLBARv6_Unregister (void)
+{
+    UnregisterClassW (TOOLBARCLASSNAMEW, NULL);
+}
+#endif
+
 static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id)
 {
     HIMAGELIST himlold;