Add theming for the up/down control.

diff --git a/dlls/comctl32/updown.c b/dlls/comctl32/updown.c
index 5cdc23a..d889881 100644
--- a/dlls/comctl32/updown.c
+++ b/dlls/comctl32/updown.c
@@ -40,6 +40,8 @@
 #include "winnls.h"
 #include "commctrl.h"
 #include "comctl32.h"
+#include "uxtheme.h"
+#include "tmschema.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
@@ -75,7 +77,8 @@
 #define DEFAULT_ADDBOT       0 /* amount to extend below the buddy window */
 #define DEFAULT_BUDDYBORDER  2 /* Width/height of the buddy border */
 #define DEFAULT_BUDDYSPACER  2 /* Spacer between the buddy and the ctrl */
-
+#define DEFAULT_BUDDYBORDER_THEMED  1 /* buddy border when theming is enabled */
+#define DEFAULT_BUDDYSPACER_THEMED  0 /* buddy spacer when theming is enabled */
 
 /* Work constants */
 
@@ -175,6 +178,9 @@
  */
 static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
 {
+    HTHEME theme = GetWindowTheme (infoPtr->Self);
+    const int border = theme ? DEFAULT_BUDDYBORDER_THEMED : DEFAULT_BUDDYBORDER;
+    const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER;
     GetClientRect (infoPtr->Self, rect);
 
     /*
@@ -183,17 +189,17 @@
      */
     if (UPDOWN_HasBuddyBorder(infoPtr)) {
         if (infoPtr->dwStyle & UDS_ALIGNLEFT)
-            rect->left += DEFAULT_BUDDYBORDER;
+            rect->left += border;
         else
-            rect->right -= DEFAULT_BUDDYBORDER;
+            rect->right -= border;
 
-        InflateRect(rect, 0, -DEFAULT_BUDDYBORDER);
+        InflateRect(rect, 0, -border);
     }
 
     /* now figure out if we need a space away from the buddy */
-    if ( IsWindow(infoPtr->Buddy) ) {
-	if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= DEFAULT_BUDDYSPACER;
-	else rect->left += DEFAULT_BUDDYSPACER;
+    if (IsWindow(infoPtr->Buddy) ) {
+	if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer;
+	else rect->left += spacer;
     }
 
     /*
@@ -206,11 +212,11 @@
         if (arrow & FLAG_INCR)
             rect->left = rect->left + len/2;
         if (arrow & FLAG_DECR)
-            rect->right =  rect->left + len/2 - 1;
+            rect->right =  rect->left + len/2 - (theme ? 0 : 1);
     } else {
         int len = rect->bottom - rect->top + 1; /* compute the height */
         if (arrow & FLAG_INCR)
-            rect->bottom =  rect->top + len/2 - 1;
+            rect->bottom =  rect->top + len/2 - (theme ? 0 : 1);
         if (arrow & FLAG_DECR)
             rect->top =  rect->top + len/2;
     }
@@ -219,10 +225,10 @@
 /***********************************************************************
  *           UPDOWN_GetArrowFromPoint
  * Returns the rectagle (for the up or down arrow) that contains pt.
- * If it returns the up rect, it returns TRUE.
- * If it returns the down rect, it returns FALSE.
+ * If it returns the up rect, it returns FLAG_INCR.
+ * If it returns the down rect, it returns FLAG_DECR.
  */
-static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt)
+static INT UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt)
 {
     UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR);
     if(PtInRect(rect, pt)) return FLAG_INCR;
@@ -342,42 +348,85 @@
 }
 
 /***********************************************************************
+ * UPDOWN_DrawBuddyBackground
+ *
+ * Draw buddy background for visual integration.
+ */
+static BOOL UPDOWN_DrawBuddyBackground (UPDOWN_INFO *infoPtr, HDC hdc)
+{
+    RECT br;
+    HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy);
+    if (!buddyTheme) return FALSE;
+
+    GetClientRect (infoPtr->Buddy, &br);
+    MapWindowPoints (infoPtr->Buddy, infoPtr->Self, (POINT*)&br, 2);
+    /* FIXME: take disabled etc. into account */
+    DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL);
+    return TRUE;
+}
+
+/***********************************************************************
  * UPDOWN_Draw
  *
  * Draw the arrows. The background need not be erased.
  */
 static LRESULT UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
 {
-    BOOL pressed, hot;
+    BOOL uPressed, uHot, dPressed, dHot;
     RECT rect;
+    HTHEME theme = GetWindowTheme (infoPtr->Self);
+    int uPart = 0, uState = 0, dPart = 0, dState = 0;
+    BOOL needBuddyBg = FALSE;
+
+    uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
+    uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
+    dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
+    dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
+    if (theme) {
+        uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP;
+        uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED 
+            : (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL));
+        dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN;
+        dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED 
+            : (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL));
+        needBuddyBg = IsWindow (infoPtr->Buddy)
+            && (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState)
+              || IsThemeBackgroundPartiallyTransparent (theme, dPart, dState));
+    }
 
     /* Draw the common border between ourselves and our buddy */
-    if (UPDOWN_HasBuddyBorder(infoPtr)) {
-	GetClientRect(infoPtr->Self, &rect);
-	DrawEdge(hdc, &rect, EDGE_SUNKEN,
-		 BF_BOTTOM | BF_TOP |
-		 (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
+    if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) {
+        if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) {
+            GetClientRect(infoPtr->Self, &rect);
+	    DrawEdge(hdc, &rect, EDGE_SUNKEN,
+		     BF_BOTTOM | BF_TOP |
+		     (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
+        }
     }
 
     /* Draw the incr button */
     UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR);
-    pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
-    hot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
-    DrawFrameControl(hdc, &rect, DFC_SCROLL,
-	(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
-        ((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
-	(pressed ? DFCS_PUSHED : 0) |
-	(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
+    if (theme) {
+        DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL);
+    } else {
+        DrawFrameControl(hdc, &rect, DFC_SCROLL,
+            (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
+            ((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) |
+            (uPressed ? DFCS_PUSHED : 0) |
+            (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
+    }
 
     /* Draw the decr button */
     UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR);
-    pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
-    hot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
-    DrawFrameControl(hdc, &rect, DFC_SCROLL,
-	(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
-        ((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
-	(pressed ? DFCS_PUSHED : 0) |
-	(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
+    if (theme) {
+        DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL);
+    } else {
+        DrawFrameControl(hdc, &rect, DFC_SCROLL,
+            (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
+            ((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) |
+            (dPressed ? DFCS_PUSHED : 0) |
+            (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
+    }
 
     return 0;
 }
@@ -653,6 +702,7 @@
     POINT pt = { x, y };
     RECT rect;
     int temp, arrow;
+    TRACKMOUSEEVENT tme;
 
     TRACE("msg %04x point %s\n", msg, wine_dbgstr_point(&pt));
 
@@ -713,7 +763,19 @@
 
             /* If state changed, redraw the control */
             if(temp != infoPtr->Flags)
-		 InvalidateRect (infoPtr->Self, &rect, FALSE);
+		 InvalidateRect (infoPtr->Self, NULL, FALSE);
+
+            /* Set up tracking so the mousein flags can be reset when the 
+             * mouse leaves the control */
+            tme.cbSize = sizeof( tme );
+            tme.dwFlags = TME_LEAVE;
+            tme.hwndTrack = infoPtr->Self;
+            TrackMouseEvent (&tme);
+
+            break;
+        case WM_MOUSELEAVE:
+	    infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
+            InvalidateRect (infoPtr->Self, NULL, FALSE);
             break;
 
 	default:
@@ -729,6 +791,8 @@
 {
     UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd);
     int temp;
+    static const WCHAR themeClass[] = {'S','p','i','n',0};
+    HTHEME theme;
 
     TRACE("hwnd=%p msg=%04x wparam=%08x lparam=%08lx\n", hwnd, message, wParam, lParam);
 
@@ -761,6 +825,8 @@
 	    if (infoPtr->dwStyle & UDS_AUTOBUDDY)
 		UPDOWN_SetBuddy (infoPtr, GetWindow (hwnd, GW_HWNDPREV));
 
+            OpenThemeData (hwnd, themeClass);
+
 	    TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd);
 	    break;
 
@@ -771,6 +837,8 @@
 
 	    Free (infoPtr);
 	    SetWindowLongPtrW (hwnd, 0, 0);
+            theme = GetWindowTheme (hwnd);
+            CloseThemeData (theme);
 	    TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd);
 	    break;
 
@@ -791,6 +859,13 @@
             }
             break;
 
+        case WM_THEMECHANGED:
+            theme = GetWindowTheme (hwnd);
+            CloseThemeData (theme);
+            OpenThemeData (hwnd, themeClass);
+            InvalidateRect (hwnd, NULL, FALSE);
+            break;
+
 	case WM_TIMER:
 	   /* is this the auto-press timer? */
 	   if(wParam == TIMER_AUTOPRESS) {
@@ -849,6 +924,7 @@
 
 	case WM_LBUTTONDOWN:
 	case WM_MOUSEMOVE:
+        case WM_MOUSELEAVE:
 	    if(UPDOWN_IsEnabled(infoPtr))
 		UPDOWN_HandleMouseEvent (infoPtr, message, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
 	    break;