[uxtheme]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Mon, 19 Sep 2011 12:51:42 +0000 (12:51 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Mon, 19 Sep 2011 12:51:42 +0000 (12:51 +0000)
- Merge from the themes branch

svn path=/trunk/; revision=53748

1  2 
reactos/dll/win32/uxtheme/CMakeLists.txt
reactos/dll/win32/uxtheme/draw.c
reactos/dll/win32/uxtheme/msstyles.c
reactos/dll/win32/uxtheme/ncscrollbar.c
reactos/dll/win32/uxtheme/ncthm.h
reactos/dll/win32/uxtheme/nonclient.c
reactos/dll/win32/uxtheme/system.c
reactos/dll/win32/uxtheme/themehooks.c
reactos/dll/win32/uxtheme/uxtheme.rbuild
reactos/dll/win32/uxtheme/uxtheme.spec
reactos/dll/win32/uxtheme/uxthemedll.h

index 8d7631f,0000000..ff0b710
mode 100644,000000..100644
--- /dev/null
@@@ -1,28 -1,0 +1,31 @@@
 +
 +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
 +add_definitions(-D__WINESRC__)
 +set_rc_compiler()
 +
 +spec2def(uxtheme.dll uxtheme.spec)
 +
 +list(APPEND SOURCE
 +    buffer.c
 +    draw.c
 +    main.c
 +    metric.c
 +    msstyles.c
++    ncscrollbar.c
++    nonclient.c
 +    property.c
 +    stylemap.c
 +    system.c
++    themehooks.c
 +    uxini.c
 +    version.rc
 +    ${CMAKE_CURRENT_BINARY_DIR}/uxtheme_stubs.c
 +    ${CMAKE_CURRENT_BINARY_DIR}/uxtheme.def)
 +
 +add_library(uxtheme SHARED ${SOURCE})
 +set_module_type(uxtheme win32dll)
 +target_link_libraries(uxtheme wine)
 +add_delay_importlibs(uxtheme msimg32)
 +add_importlibs(uxtheme user32 advapi32 gdi32 msvcrt kernel32 ntdll)
 +add_cd_file(TARGET uxtheme DESTINATION reactos/system32 FOR all)
 +add_importlib_target(uxtheme.spec)
@@@ -1731,6 -1731,166 +1731,166 @@@ HRESULT WINAPI GetThemeBackgroundExtent
      return S_OK;
  }
  
+ static HBITMAP UXTHEME_DrawThemePartToDib(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCRECT pRect)
+ {
+     HDC hdcMem;
+     BITMAPINFO bmi = {0};
+     HBITMAP hbmp, hbmpOld;
+     HBRUSH hbrBack;
+     hdcMem = CreateCompatibleDC(0);
+     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
+     bmi.bmiHeader.biWidth = pRect->right;
+     bmi.bmiHeader.biHeight = -pRect->bottom;
+     bmi.bmiHeader.biPlanes = 1;
+     bmi.bmiHeader.biBitCount = 32;
+     hbmp = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS , NULL, 0, 0);
+     hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmp);
+     
+     /* FIXME: use an internal function that doesn't do transparent blt */
+     hbrBack = CreateSolidBrush(RGB(255,0,255));
+     FillRect(hdcMem, pRect, hbrBack);
+     DrawThemeBackground(hTheme, hdcMem, iPartId, iStateId, pRect, NULL);
+     DeleteObject(hbrBack);
+     SelectObject(hdcMem, hbmpOld);
+     DeleteObject(hdcMem);
+     return hbmp;
+ }
+ #define PT_IN_RECT(lprc,x,y) ( x >= lprc->left && x < lprc->right && \
+                                y >= lprc->top  && y < lprc->bottom)
+ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent, LPCRECT pRect)
+ {
+     int x, y, xstart;
+     int cMaxRgnRects, cRgnDataSize, cRgnRects;
+ #ifdef EXTCREATEREGION_WORKS
+     RECT* prcCurrent;
+     PRGNDATA prgnData;
+ #else
+     HRGN hrgnTemp;
+ #endif
+     ULONG clrTransparent, *pclrCurrent;
+     HRGN hrgnRet;
+     pclrCurrent = (PULONG)pBuffer;
+     clrTransparent = *(PULONG)pclrTransparent;
+     /* Create a region and pre-allocate memory enough for 3 spaces in one row*/
+     cRgnRects = 0;
+     cMaxRgnRects = 4* (pRect->bottom-pRect->top);
+     cRgnDataSize = sizeof(RGNDATA) + cMaxRgnRects * sizeof(RECT);
+ #ifdef EXTCREATEREGION_WORKS
+     /* Allocate the region data */
+     prgnData = (PRGNDATA)HeapAlloc(GetProcessHeap(), 0, cRgnDataSize);
+     prcCurrent = (PRECT)prgnData->Buffer;
+ #else
+     hrgnRet = CreateRectRgn(0,0,0,0);
+ #endif
+     
+     /* Calculate the region rects */
+     y=0;
+     /* Scan each line of the bitmap */
+     while(y<pRect->bottom)
+     {
+         x=0;
+         /* Scan each pixel */
+         while (x<pRect->right)
+         {
+             /* Check if the pixel is not transparent and it is in the requested rect */
+             if(*pclrCurrent != clrTransparent && PT_IN_RECT(pRect,x,y))
+             {
+                 xstart = x;
+                 /* Find the end of the opaque row of pixels */
+                 while (x<pRect->right)
+                 {
+                     if(*pclrCurrent == clrTransparent || !PT_IN_RECT(pRect,x,y))
+                         break;
+                     x++;
+                     pclrCurrent++;
+                 }
+ #ifdef EXTCREATEREGION_WORKS
+                 /* Add the scaned line to the region */
+                 SetRect(prcCurrent, xstart, y,x,y+1);
+                 prcCurrent++;
+                 cRgnRects++;
+                 /* Increase the size of the buffer if it is full */
+                 if(cRgnRects == cMaxRgnRects)
+                 {
+                     cMaxRgnRects *=2;
+                     cRgnDataSize = sizeof(RGNDATA) + cMaxRgnRects * sizeof(RECT);
+                     prgnData = (PRGNDATA)HeapReAlloc(GetProcessHeap(), 
+                                                      0, 
+                                                      prgnData, 
+                                                      cRgnDataSize);
+                     prcCurrent = (RECT*)prgnData->Buffer + cRgnRects;
+                 }
+ #else
+                 hrgnTemp = CreateRectRgn(xstart, y,x,y+1);
+                 CombineRgn(hrgnRet, hrgnRet, hrgnTemp, RGN_OR );
+                 DeleteObject(hrgnTemp);
+ #endif
+             }
+             else
+             {
+                 x++;
+                 pclrCurrent++;
+             }
+         }
+         y++;
+     }
+ #ifdef EXTCREATEREGION_WORKS
+     /* Fill the region data header */
+     prgnData->rdh.dwSize = sizeof(prgnData->rdh);
+     prgnData->rdh.iType = RDH_RECTANGLES;
+     prgnData->rdh.nCount = cRgnRects;
+     prgnData->rdh.nRgnSize = cRgnDataSize;
+     prgnData->rdh.rcBound = *pRect;
+     /* Create the region*/
+     hrgnRet = ExtCreateRegion (NULL, cRgnDataSize, prgnData);
+     /* Free the region data*/
+     HeapFree(GetProcessHeap(),0,prgnData);
+ #endif
+     /* return the region*/
+     return hrgnRet;
+ }
+ HRESULT UXTHEME_GetImageBackBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCRECT pRect, HRGN *pRegion)
+ {
+     HBITMAP hbmp;
+     DIBSECTION dib;
+     RGBQUAD clrTransparent = {0xFF,0x0, 0xFF,0x0};
+     /* Draw the theme part to a dib */
+     hbmp = UXTHEME_DrawThemePartToDib(hTheme, hdc, iPartId, iStateId, pRect);
+     /* Retrieve the info of the dib section */
+     GetObject(hbmp, sizeof (DIBSECTION), &dib);
+     /* Convert the bits of the dib section to a region */
+     *pRegion = UXTHEME_RegionFromDibBits((RGBQUAD*)dib.dsBm.bmBits, &clrTransparent, pRect);
+     /* Free the temp bitmap */
+     DeleteObject(hbmp);
+     return S_OK;
+ }
  /***********************************************************************
   *      GetThemeBackgroundRegion                            (UXTHEME.@)
   *
@@@ -1752,8 -1912,7 +1912,7 @@@ HRESULT WINAPI GetThemeBackgroundRegion
  
      GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
      if(bgtype == BT_IMAGEFILE) {
-         FIXME("Images not handled yet\n");
-         hr = ERROR_CALL_NOT_IMPLEMENTED;
+         hr = UXTHEME_GetImageBackBackgroundRegion(hTheme, hdc, iPartId, iStateId, pRect, pRegion);
      }
      else if(bgtype == BT_BORDERFILL) {
          *pRegion = CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
@@@ -1257,6 -1257,13 +1257,13 @@@ static HRESULT MSSTYLES_GetFont (LPCWST
          *lpValEnd = lpCur;
          return E_PROP_ID_UNSUPPORTED;
      }
+     if(pointSize > 0)
+     {
+         HDC hdc = GetDC(0);
+         pointSize = -MulDiv(pointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+         ReleaseDC(0, hdc);
+     }
      pFont->lfHeight = pointSize;
      pFont->lfWeight = FW_REGULAR;
      pFont->lfCharSet = DEFAULT_CHARSET;
@@@ -1278,8 -1285,6 +1285,6 @@@ HRESULT MSSTYLES_GetPropertyFont(PTHEME
  
      ZeroMemory(pFont, sizeof(LOGFONTW));
      hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont);
-     if (SUCCEEDED (hr))
-         pFont->lfHeight = -MulDiv(pFont->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  
      return hr;
  }
index 0000000,f8f729f..f8f729f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,676 +1,676 @@@
+ /*
+  * COPYRIGHT:       See COPYING in the top level directory
+  * PROJECT:         ReactOS uxtheme.dll
+  * FILE:            dll/win32/uxtheme/ncscrollbar.c
+  * PURPOSE:         uxtheme scrollbar support
+  * PROGRAMMER:      Giannis Adamopoulos
+  *                  This file is heavily based on code from the wine project:
+  *                  Copyright 1993 Martin Ayotte
+  *                  Copyright 1994, 1996 Alexandre Julliard
+  */
+  
+ #include <windows.h>
+ #include "undocuser.h"
+ #include "vfwmsgs.h"
+ #include "uxtheme.h"
+ #include <tmschema.h>
+ #include <Windowsx.h>
+ #include "ncthm.h"
+ #include <assert.h>
+ #include "wine/debug.h"
+ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
+ static BOOL SCROLL_trackVertical;
+ static enum SCROLL_HITTEST SCROLL_trackHitTest;
+ /* Is the moving thumb being displayed? */
+ static BOOL SCROLL_MovingThumb = FALSE;
+ static HWND SCROLL_TrackingWin = 0;
+ static INT  SCROLL_TrackingBar = 0;
+ static INT  SCROLL_TrackingPos = 0;
+ static INT  SCROLL_TrackingVal = 0;
+ void static ScreenToWindow( HWND hWnd, POINT* pt)
+ {
+     RECT rcWnd;
+     GetWindowRect(hWnd, &rcWnd);
+     pt->x -= rcWnd.left;
+     pt->y -= rcWnd.top;
+ }
+ static BOOL SCROLL_IsVertical(HWND hwnd, INT nBar)
+ {
+     switch(nBar)
+     {
+     case SB_HORZ:
+         return FALSE;
+     case SB_VERT:
+         return TRUE;
+     default:
+         assert(FALSE);
+         return FALSE;
+     }
+ }
+ static LONG SCROLL_getObjectId(INT nBar)
+ {
+     switch(nBar)
+     {
+     case SB_HORZ:
+         return OBJID_HSCROLL;
+     case SB_VERT:
+         return OBJID_VSCROLL;
+     default:
+         assert(FALSE);
+         return 0;
+     }
+ }
+ /***********************************************************************
+  *           SCROLL_PtInRectEx
+  */
+ static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
+ {
+     RECT rect = *lpRect;
+     int scrollbarWidth;
+     /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
+      * still be considered in the scrollbar. */
+     if (vertical)
+     {
+         scrollbarWidth = lpRect->right - lpRect->left;
+         rect.left -= scrollbarWidth*8;
+         rect.right += scrollbarWidth*8;
+         rect.top -= scrollbarWidth*2;
+         rect.bottom += scrollbarWidth*2;
+     }
+     else
+     {
+         scrollbarWidth = lpRect->bottom - lpRect->top;
+         rect.left -= scrollbarWidth*2;
+         rect.right += scrollbarWidth*2;
+         rect.top -= scrollbarWidth*8;
+         rect.bottom += scrollbarWidth*8;
+     }
+     return PtInRect( &rect, pt );
+ }
+ /***********************************************************************
+  *           SCROLL_HitTest
+  *
+  * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
+  */
+ static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, SCROLLBARINFO* psbi, BOOL vertical,
+                                            POINT pt, BOOL bDragging )
+ {
+     if ( (bDragging && !SCROLL_PtInRectEx( &psbi->rcScrollBar, pt, vertical )) ||
+            (!PtInRect( &psbi->rcScrollBar, pt )) ) 
+     {
+          return SCROLL_NOWHERE;
+     }
+     if (vertical)
+     {
+         if (pt.y < psbi->rcScrollBar.top + psbi->dxyLineButton) 
+             return SCROLL_TOP_ARROW;
+         if (pt.y >= psbi->rcScrollBar.bottom - psbi->dxyLineButton) 
+             return SCROLL_BOTTOM_ARROW;
+         if (!psbi->xyThumbTop) 
+             return SCROLL_TOP_RECT;
+         pt.y -= psbi->rcScrollBar.top;
+         if (pt.y < psbi->xyThumbTop) 
+             return SCROLL_TOP_RECT;
+         if (pt.y >= psbi->xyThumbTop + psbi->dxyLineButton) 
+             return SCROLL_BOTTOM_RECT;
+     }
+     else  /* horizontal */
+     {
+         if (pt.x < psbi->rcScrollBar.left + psbi->dxyLineButton)
+             return SCROLL_TOP_ARROW;
+         if (pt.x >= psbi->rcScrollBar.right - psbi->dxyLineButton) 
+             return SCROLL_BOTTOM_ARROW;
+         if (!psbi->xyThumbTop) 
+             return SCROLL_TOP_RECT;
+         pt.x -= psbi->rcScrollBar.left;
+         if (pt.x < psbi->xyThumbTop) 
+             return SCROLL_TOP_RECT;
+         if (pt.x >= psbi->xyThumbTop + psbi->dxyLineButton) 
+             return SCROLL_BOTTOM_RECT;
+     }
+     return SCROLL_THUMB;
+ }
+ static void SCROLL_ThemeDrawPart(PDRAW_CONTEXT pcontext, int iPartId,int iStateId,  SCROLLBARINFO* psbi, int htCurrent, int htDown, int htHot, RECT* r)
+ {
+     if(psbi->rgstate[htCurrent] & STATE_SYSTEM_UNAVAILABLE)
+         iStateId += BUTTON_DISABLED - BUTTON_NORMAL;
+     else if (htHot == htCurrent)
+         iStateId += BUTTON_HOT - BUTTON_NORMAL;
+     else if (htDown == htCurrent)
+         iStateId += BUTTON_PRESSED - BUTTON_NORMAL;
+     DrawThemeBackground(pcontext->scrolltheme, pcontext->hDC, iPartId, iStateId, r, NULL);
+ }
+ /***********************************************************************
+  *           SCROLL_DrawArrows
+  *
+  * Draw the scroll bar arrows.
+  */
+ static void SCROLL_DrawArrows( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi, 
+                                BOOL vertical, int htDown, int htHot )
+ {
+     RECT r;
+     int iStateId;
+     r = psbi->rcScrollBar;
+     if( vertical )
+     {
+         r.bottom = r.top + psbi->dxyLineButton;
+         iStateId = ABS_UPNORMAL;
+     }
+     else
+     {
+         r.right = r.left + psbi->dxyLineButton;
+         iStateId = ABS_LEFTNORMAL;
+     }
+     
+     SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_TOP_ARROW, htDown, htHot, &r);
+     
+     r = psbi->rcScrollBar;
+     if( vertical )
+     {
+         r.top = r.bottom - psbi->dxyLineButton;
+         iStateId = ABS_DOWNNORMAL;
+     }
+     else
+     {
+         iStateId = ABS_RIGHTNORMAL;
+         r.left = r.right - psbi->dxyLineButton;
+     }
+     SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_BOTTOM_ARROW, htDown, htHot, &r);
+ }
+ static void SCROLL_DrawInterior( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi,
+                                   INT thumbPos, BOOL vertical,
+                                   int htDown, int htHot )
+ {
+     RECT r, rcPart;
+     r = psbi->rcScrollBar;
+     if (vertical)
+     {
+         r.top    += psbi->dxyLineButton;
+         r.bottom -= (psbi->dxyLineButton);
+     }
+     else
+     {
+         r.left  += psbi->dxyLineButton;
+         r.right -= psbi->dxyLineButton;
+     }
+     /* Draw the scroll rectangles and thumb */
+     if (!thumbPos)  /* No thumb to draw */
+     {
+         rcPart = r;
+         SCROLL_ThemeDrawPart(pcontext, vertical ? SBP_UPPERTRACKVERT: SBP_UPPERTRACKHORZ , BUTTON_NORMAL, psbi, SCROLL_THUMB, 0, 0, &rcPart);
+         return;
+     }
+     if (vertical)
+     { 
+         rcPart = r;
+         rcPart.bottom = rcPart.top + thumbPos - psbi->dxyLineButton;
+         SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart);
+         r.top = rcPart.bottom;
+         rcPart = r;
+         rcPart.top += psbi->dxyLineButton;
+         SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart); 
+         r.bottom = rcPart.top;
+         SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 
+         SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 
+     }
+     else  /* horizontal */
+     {
+         rcPart = r;
+         rcPart.right = rcPart.left + thumbPos - psbi->dxyLineButton;
+         SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart);
+         r.left = rcPart.right;
+         rcPart = r;
+         rcPart.left += psbi->dxyLineButton;
+         SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart);
+         r.right = rcPart.left;
+         SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
+         SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
+     }
+ }
+ static void SCROLL_DrawMovingThumb( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi,  BOOL vertical)
+ {
+   INT pos = SCROLL_TrackingPos;
+   INT max_size;
+   if( vertical )
+       max_size = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
+   else
+     max_size = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
+   max_size -= (psbi->dxyLineButton -SCROLL_ARROW_THUMB_OVERLAP) + psbi->dxyLineButton;
+   if( pos < (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP) )
+     pos = (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP);
+   else if( pos > max_size )
+     pos = max_size;
+   SCROLL_DrawInterior(pcontext, psbi, pos, vertical, SCROLL_THUMB, 0);  
+   SCROLL_MovingThumb = !SCROLL_MovingThumb;
+ }
+ void 
+ ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT nBar, POINT* pt)
+ {
+     SCROLLINFO si;
+     SCROLLBARINFO sbi;
+     BOOL vertical;
+     enum SCROLL_HITTEST htHot = SCROLL_NOWHERE;
+     /* Retrieve scrollbar info */
+     sbi.cbSize = sizeof(sbi);
+     si.cbSize = sizeof(si);
+     si.fMask = SIF_ALL ;
+     GetScrollInfo(pcontext->hWnd, nBar, &si);
+     GetScrollBarInfo(pcontext->hWnd, SCROLL_getObjectId(nBar), &sbi);
+     vertical = SCROLL_IsVertical(pcontext->hWnd, nBar);
+     if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE  && 
+        sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE  )
+     {
+         sbi.xyThumbTop = 0;
+     }
+ #ifndef ROS_SUCKS
+     /* The scrollbar rect is in screen coordinates */
+ //    OffsetRect(&sbi.rcScrollBar, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
+ #endif
+     if(pt)
+     {
+         ScreenToWindow(pcontext->hWnd, pt);
+         htHot = SCROLL_HitTest(pcontext->hWnd, &sbi, vertical, *pt, FALSE);
+     }
+     
+     if (((nBar == SB_VERT) && !(pcontext->wi.dwStyle & WS_VSCROLL)) ||
+         ((nBar == SB_HORZ) && !(pcontext->wi.dwStyle & WS_HSCROLL))) return;
+     /* do not draw if the scrollbar rectangle is empty */
+     if(IsRectEmpty(&sbi.rcScrollBar)) return;
+     /* Draw the scrollbar */
+     SCROLL_DrawArrows( pcontext, &sbi, vertical, 0, htHot );
+       SCROLL_DrawInterior( pcontext, &sbi, sbi.xyThumbTop, vertical, 0, htHot );
+ }
+ /***********************************************************************
+  *           SCROLL_ClipPos
+  */
+ static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
+ {
+     if( pt.x < lpRect->left )
+           pt.x = lpRect->left;
+     else
+         if( pt.x > lpRect->right )
+       pt.x = lpRect->right;
+     if( pt.y < lpRect->top )
+           pt.y = lpRect->top;
+     else
+     if( pt.y > lpRect->bottom )
+           pt.y = lpRect->bottom;
+     return pt;
+ }
+ /***********************************************************************
+  *           SCROLL_GetThumbVal
+  *
+  * Compute the current scroll position based on the thumb position in pixels
+  * from the top of the scroll-bar.
+  */
+ static UINT SCROLL_GetThumbVal( SCROLLINFO *psi, RECT *rect,
+                                   BOOL vertical, INT pos )
+ {
+     INT thumbSize;
+     INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
+     INT range;
+     if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
+         return psi->nMin;
+     if (psi->nPage)
+     {
+         thumbSize = MulDiv(pixels,psi->nPage,(psi->nMax-psi->nMin+1));
+         if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
+     }
+     else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
+     if ((pixels -= thumbSize) <= 0) return psi->nMin;
+     pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
+     if (pos > pixels) pos = pixels;
+     if (!psi->nPage)
+         range = psi->nMax - psi->nMin;
+     else
+         range = psi->nMax - psi->nMin - psi->nPage + 1;
+     return psi->nMin + MulDiv(pos, range, pixels);
+ }
+ static void 
+ SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
+ {
+       /* Previous mouse position for timer events */
+     static POINT prevPt;
+       /* Thumb position when tracking started. */
+     static UINT trackThumbPos;
+       /* Position in the scroll-bar of the last button-down event. */
+     static INT lastClickPos;
+       /* Position in the scroll-bar of the last mouse event. */
+     static INT lastMousePos;
+     enum SCROLL_HITTEST hittest;
+     HWND hwndOwner, hwndCtl;
+     BOOL vertical;
+     SCROLLINFO si;
+     SCROLLBARINFO sbi;
+     DRAW_CONTEXT context;
+     si.cbSize = sizeof(si);
+     sbi.cbSize = sizeof(sbi);
+     si.fMask = SIF_ALL;
+     GetScrollInfo(hwnd, nBar, &si);
+     GetScrollBarInfo(hwnd, SCROLL_getObjectId(nBar), &sbi);
+     vertical = SCROLL_IsVertical(hwnd, nBar);
+     if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE  && 
+        sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE  )
+     {
+         return;
+     }
+     ThemeInitDrawContext(&context, hwnd, 0);
+ #ifndef ROS_SUCKS
+     /* The scrollbar rect is in screen coordinates */
+ //    OffsetRect(&sbi.rcScrollBar, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
+ #endif
+     if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN))
+                 return;
+     
+     hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd;
+     hwndCtl   = (nBar == SB_CTL) ? hwnd : 0;
+     switch(msg)
+     {
+       case WM_LBUTTONDOWN:  /* Initialise mouse tracking */
+           HideCaret(hwnd);  /* hide caret while holding down LBUTTON */
+           SCROLL_trackVertical = vertical;
+           SCROLL_trackHitTest  = hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE );
+           lastClickPos  = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left);
+           lastMousePos  = lastClickPos;
+           trackThumbPos = sbi.xyThumbTop;
+           prevPt = pt;
+           SetCapture( hwnd );
+           break;
+       case WM_MOUSEMOVE:
+           hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, TRUE );
+           prevPt = pt;
+           break;
+       case WM_LBUTTONUP:
+           hittest = SCROLL_NOWHERE;
+           ReleaseCapture();
+           /* if scrollbar has focus, show back caret */
+           if (hwnd==GetFocus()) 
+               ShowCaret(hwnd);
+           break;
+       case WM_SYSTIMER:
+           pt = prevPt;
+           hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE );
+           break;
+       default:
+           return;  /* Should never happen */
+     }
+     //TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
+     //      hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest );
+     switch(SCROLL_trackHitTest)
+     {
+     case SCROLL_NOWHERE:  /* No tracking in progress */
+         break;
+     case SCROLL_TOP_ARROW:
+         if (hittest == SCROLL_trackHitTest)
+         {
+             SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 );
+             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
+             {
+                 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                 SB_LINEUP, (LPARAM)hwndCtl );
+               }
+         SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+                             SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+         }
+         else
+         {
+             SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 );
+             KillSystemTimer( hwnd, SCROLL_TIMER );
+         }
+         break;
+     case SCROLL_TOP_RECT:
+         SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0);
+         if (hittest == SCROLL_trackHitTest)
+         {
+             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
+             {
+                 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                 SB_PAGEUP, (LPARAM)hwndCtl );
+             }
+             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+                               SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+         }
+         else KillSystemTimer( hwnd, SCROLL_TIMER );
+         break;
+     case SCROLL_THUMB:
+         if (msg == WM_LBUTTONDOWN)
+         {
+             SCROLL_TrackingWin = hwnd;
+             SCROLL_TrackingBar = nBar;
+             SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
+             SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, 
+                                                      vertical, SCROLL_TrackingPos );
+               if (!SCROLL_MovingThumb)
+                       SCROLL_DrawMovingThumb(&context, &sbi, vertical);
+         }
+         else if (msg == WM_LBUTTONUP)
+         {
+               if (SCROLL_MovingThumb)
+                       SCROLL_DrawMovingThumb(&context, &sbi, vertical);
+             SCROLL_DrawInterior(  &context, &sbi, sbi.xyThumbTop, vertical, 0, SCROLL_trackHitTest );
+         }
+         else  /* WM_MOUSEMOVE */
+         {
+             INT pos;
+             if (!SCROLL_PtInRectEx( &sbi.rcScrollBar, pt, vertical )) 
+                 pos = lastClickPos;
+             else
+             {
+                 pt = SCROLL_ClipPos( &sbi.rcScrollBar, pt );
+                 pos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left);
+             }
+             if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) )
+             {
+                 if (SCROLL_MovingThumb)
+                     SCROLL_DrawMovingThumb( &context, &sbi, vertical);
+                 lastMousePos = pos;
+                 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
+                 SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar,
+                                                          vertical,
+                                                          SCROLL_TrackingPos );
+                 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
+                                 (LPARAM)hwndCtl );
+                 if (!SCROLL_MovingThumb)
+                     SCROLL_DrawMovingThumb( &context, &sbi, vertical);
+             }
+         }
+         break;
+     case SCROLL_BOTTOM_RECT:
+         if (hittest == SCROLL_trackHitTest)
+         {
+             SCROLL_DrawInterior(  &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0 );
+             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
+             {
+                 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                 SB_PAGEDOWN, (LPARAM)hwndCtl );
+             }
+             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+                               SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+         }
+         else
+         {
+             SCROLL_DrawInterior(  &context, &sbi, sbi.xyThumbTop, vertical, 0, 0 );
+             KillSystemTimer( hwnd, SCROLL_TIMER );
+         }
+         break;
+     case SCROLL_BOTTOM_ARROW:
+         if (hittest == SCROLL_trackHitTest)
+         {
+             SCROLL_DrawArrows(  &context, &sbi, vertical, SCROLL_trackHitTest, 0 );
+             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
+             {
+                 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                 SB_LINEDOWN, (LPARAM)hwndCtl );
+               }
+         SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+                             SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+         }
+         else
+         {
+             SCROLL_DrawArrows(  &context, &sbi, vertical, 0, 0 );
+             KillSystemTimer( hwnd, SCROLL_TIMER );
+         }
+         break;
+     }
+     if (msg == WM_LBUTTONDOWN)
+     {
+         if (hittest == SCROLL_THUMB)
+         {
+             UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical,
+                                  trackThumbPos + lastMousePos - lastClickPos );
+             SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                             MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl );
+         }
+     }
+     if (msg == WM_LBUTTONUP)
+     {
+         hittest = SCROLL_trackHitTest;
+         SCROLL_trackHitTest = SCROLL_NOWHERE;  /* Terminate tracking */
+         if (hittest == SCROLL_THUMB)
+         {
+             UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical,
+                                  trackThumbPos + lastMousePos - lastClickPos );
+             SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                             MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl );
+         }
+         /* SB_ENDSCROLL doesn't report thumb position */
+         SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                           SB_ENDSCROLL, (LPARAM)hwndCtl );
+         /* Terminate tracking */
+         SCROLL_TrackingWin = 0;
+     }
+     ThemeCleanupDrawContext(&context);
+ }
+ static void 
+ SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt )
+ {
+     MSG msg;
+     ScreenToWindow(hwnd, &pt);
+     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
+     do
+     {
+         if (!GetMessageW( &msg, 0, 0, 0 )) break;
+         if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue;
+         if (msg.message == WM_LBUTTONUP ||
+             msg.message == WM_MOUSEMOVE ||
+             (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER))
+         {
+             pt.x = GET_X_LPARAM(msg.lParam);
+             pt.y = GET_Y_LPARAM(msg.lParam);
+             ClientToScreen(hwnd, &pt);
+             ScreenToWindow(hwnd, &pt);
+             SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
+         }
+         else
+         {
+             TranslateMessage( &msg );
+             DispatchMessageW( &msg );
+         }
+         if (!IsWindow( hwnd ))
+         {
+             ReleaseCapture();
+             break;
+         }
+     } while (msg.message != WM_LBUTTONUP && GetCapture() == hwnd);
+ }
+ void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
+ {
+     INT scrollbar;
+     
+     if ((wParam & 0xfff0) == SC_HSCROLL)
+     {
+         if ((wParam & 0x0f) != HTHSCROLL) return;
+         scrollbar = SB_HORZ;
+     }
+     else  /* SC_VSCROLL */
+     {
+         if ((wParam & 0x0f) != HTVSCROLL) return;
+         scrollbar = SB_VERT;
+     }
+     SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
+ }
index 0000000,4b9e76b..4b9e76b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,106 +1,106 @@@
+ typedef struct _WND_CONTEXT
+ {
+     BOOL HasAppDefinedRgn;
+     BOOL HasThemeRgn;
+     BOOL UpdatingRgn;
+ } WND_CONTEXT, *PWND_CONTEXT;
+ typedef struct _DRAW_CONTEXT
+ {
+     HWND hWnd;
+     HDC hDC;
+     HTHEME theme; 
+     HTHEME scrolltheme;
+     HTHEME hPrevTheme;
+     WINDOWINFO wi;
+     BOOL Active; /* wi.dwWindowStatus isn't correct for mdi child windows */
+     HRGN hRgn;
+     int CaptionHeight;
+     /* for double buffering */
+     HDC hDCScreen;
+     HBITMAP hbmpOld;
+ } DRAW_CONTEXT, *PDRAW_CONTEXT;
+ typedef enum 
+ {
+     CLOSEBUTTON,
+     MAXBUTTON,
+     MINBUTTON,
+     HELPBUTTON
+ } CAPTIONBUTTON;
+ /*
+ The following values specify all possible vutton states
+ Note that not all of them are documented but it is easy to 
+ find them by opening a theme file
+ */
+ typedef enum {
+     BUTTON_NORMAL = 1 ,
+     BUTTON_HOT ,
+     BUTTON_PRESSED ,
+     BUTTON_DISABLED ,
+     BUTTON_INACTIVE
+ } THEME_BUTTON_STATES;
+   /* Scroll-bar hit testing */
+ enum SCROLL_HITTEST
+ {
+     SCROLL_NOWHERE,      /* Outside the scroll bar */
+     SCROLL_TOP_ARROW,    /* Top or left arrow */
+     SCROLL_TOP_RECT,     /* Rectangle between the top arrow and the thumb */
+     SCROLL_THUMB,        /* Thumb rectangle */
+     SCROLL_BOTTOM_RECT,  /* Rectangle between the thumb and the bottom arrow */
+     SCROLL_BOTTOM_ARROW  /* Bottom or right arrow */
+ };
+ #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
+             ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE))  || \
+              ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
+              (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
+              (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
+ #define HAS_MENU(hwnd,style)  ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
+ #define BUTTON_GAP_SIZE 2
+ #define MENU_BAR_ITEMS_SPACE (12)
+ #define SCROLL_TIMER   0                /* Scroll timer id */
+   /* Overlap between arrows and thumb */
+ #define SCROLL_ARROW_THUMB_OVERLAP 0
+   /* Delay (in ms) before first repetition when holding the button down */
+ #define SCROLL_FIRST_DELAY   200
+   /* Delay (in ms) between scroll repetitions */
+ #define SCROLL_REPEAT_DELAY  50
+ /* Minimum size of the thumb in pixels */
+ #define SCROLL_MIN_THUMB 6
+ /* Minimum size of the rectangle between the arrows */
+ #define SCROLL_MIN_RECT  4
+ void 
+ ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT Bar, POINT* pt);
+ VOID
+ NC_TrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt);
+ void
+ ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
+                      HWND hWnd,
+                      HRGN hRgn);
+ void
+ ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext);
+ PWND_CONTEXT 
+ ThemeGetWndContext(HWND hWnd);
+ extern ATOM atWindowTheme;
+ extern ATOM atWndContrext;
index 0000000,ffcbb36..ffcbb36
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1088 +1,1088 @@@
+ /*
+  * COPYRIGHT:       See COPYING in the top level directory
+  * PROJECT:         ReactOS uxtheme.dll
+  * FILE:            dll/win32/uxtheme/nonclient.c
+  * PURPOSE:         uxtheme non client area management
+  * PROGRAMMER:      Giannis Adamopoulos
+  */
+  
+ #include <windows.h>
+ #include <windowsx.h>
+ #include "undocuser.h"
+ #include "vfwmsgs.h"
+ #include "uxtheme.h"
+ #include <tmschema.h>
+ #include "ncthm.h"
+ #include "wine/debug.h"
+ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
+ HFONT hMenuFont = NULL;
+ HFONT hMenuFontBold = NULL;
+ void InitMenuFont(VOID)
+ {
+   NONCLIENTMETRICS ncm;
+     ncm.cbSize = sizeof(NONCLIENTMETRICS); 
+     if(!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+     {
+       return ;
+     }
+     hMenuFont = CreateFontIndirect(&ncm.lfMenuFont);
+     ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+     hMenuFontBold = CreateFontIndirect(&ncm.lfMenuFont);
+ }
+ static BOOL 
+ IsWindowActive(HWND hWnd, DWORD ExStyle)
+ {
+     BOOL ret;
+     if (ExStyle & WS_EX_MDICHILD)
+     {
+         ret = IsChild(GetForegroundWindow(), hWnd);
+         if (ret)
+             ret = (hWnd == (HWND)SendMessageW(GetParent(hWnd), WM_MDIGETACTIVE, 0, 0));
+     }
+     else
+     {
+         ret = (GetForegroundWindow() == hWnd);
+     }
+     return ret;
+ }
+ static BOOL 
+ UserHasWindowEdge(DWORD Style, DWORD ExStyle)
+ {
+     if (Style & WS_MINIMIZE)
+         return TRUE;
+     if (ExStyle & WS_EX_DLGMODALFRAME)
+         return TRUE;
+     if (ExStyle & WS_EX_STATICEDGE)
+         return FALSE;
+     if (Style & WS_THICKFRAME)
+         return TRUE;
+     if (Style == WS_DLGFRAME || Style == WS_CAPTION)
+         return TRUE;
+    return FALSE;
+ }
+ HICON
+ UserGetWindowIcon(HWND hwnd)
+ {
+     HICON hIcon = 0;
+     SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
+     if (!hIcon)
+         SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
+     if (!hIcon)
+         SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
+     if (!hIcon)
+         hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM);
+     if (!hIcon)
+         hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
+     if(!hIcon)
+         hIcon = LoadIcon(NULL, IDI_WINLOGO);
+     return hIcon;
+ }
+ WCHAR *UserGetWindowCaption(HWND hwnd)
+ {
+     INT len = 512;
+     WCHAR *text;
+     text = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, len  * sizeof(WCHAR));
+     if (text) InternalGetWindowText(hwnd, text, len);
+     return text;
+ }
+ static void 
+ ThemeDrawTitle(PDRAW_CONTEXT context, RECT* prcCurrent)
+ {
+ }
+ HRESULT WINAPI ThemeDrawCaptionText(HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
+                              LPCWSTR pszText, int iCharCount, DWORD dwTextFlags,
+                              DWORD dwTextFlags2, const RECT *pRect, BOOL Active)
+ {
+     HRESULT hr;
+     HFONT hFont = NULL;
+     HGDIOBJ oldFont = NULL;
+     LOGFONTW logfont;
+     COLORREF textColor;
+     COLORREF oldTextColor;
+     int oldBkMode;
+     RECT rt;
+     
+     hr = GetThemeSysFont(0,TMT_CAPTIONFONT,&logfont);
+     if(SUCCEEDED(hr)) {
+         hFont = CreateFontIndirectW(&logfont);
+     }
+     CopyRect(&rt, pRect);
+     if(hFont)
+         oldFont = SelectObject(hdc, hFont);
+         
+     if(dwTextFlags2 & DTT_GRAYED)
+         textColor = GetSysColor(COLOR_GRAYTEXT);
+     else if (!Active)
+         textColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
+     else
+         textColor = GetSysColor(COLOR_CAPTIONTEXT);
+     
+     oldTextColor = SetTextColor(hdc, textColor);
+     oldBkMode = SetBkMode(hdc, TRANSPARENT);
+     DrawTextW(hdc, pszText, iCharCount, &rt, dwTextFlags);
+     SetBkMode(hdc, oldBkMode);
+     SetTextColor(hdc, oldTextColor);
+     if(hFont) {
+         SelectObject(hdc, oldFont);
+         DeleteObject(hFont);
+     }
+     return S_OK;
+ }
+ void
+ ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
+                      HWND hWnd,
+                      HRGN hRgn)
+ {
+     pcontext->wi.cbSize = sizeof(pcontext->wi);
+     GetWindowInfo(hWnd, &pcontext->wi);
+     pcontext->hWnd = hWnd;
+     pcontext->Active = IsWindowActive(hWnd, pcontext->wi.dwExStyle);
+     pcontext->hPrevTheme = GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWindowTheme));
+     pcontext->theme = OpenThemeData(pcontext->hWnd,  L"WINDOW");
+     pcontext->scrolltheme = OpenThemeData(pcontext->hWnd,  L"SCROLLBAR");
+     pcontext->CaptionHeight = pcontext->wi.cyWindowBorders;
+     pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
+     if(hRgn <= (HRGN)1)
+     {
+         hRgn = CreateRectRgnIndirect(&pcontext->wi.rcWindow);
+     }
+     pcontext->hRgn = hRgn;
+     pcontext->hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
+ }
+ void
+ ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext)
+ {
+     ReleaseDC(pcontext->hWnd ,pcontext->hDC);
+     CloseThemeData (pcontext->theme);
+     CloseThemeData (pcontext->scrolltheme);
+     SetPropW(pcontext->hWnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), pcontext->hPrevTheme);
+     if(pcontext->hRgn != NULL)
+     {
+         DeleteObject(pcontext->hRgn);
+     }
+ }
+ static void 
+ ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext, int cx, int cy)
+ {
+     HBITMAP hbmp;
+     pcontext->hDCScreen = pcontext->hDC;
+     pcontext->hDC = CreateCompatibleDC(pcontext->hDCScreen);
+     hbmp = CreateCompatibleBitmap(pcontext->hDCScreen, cx, cy); 
+     pcontext->hbmpOld = (HBITMAP)SelectObject(pcontext->hDC, hbmp);
+ }
+ static void
+ ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext, int x, int y, int cx, int cy)
+ {
+     HBITMAP hbmp;
+     BitBlt(pcontext->hDCScreen, 0, 0, cx, cy, pcontext->hDC, x, y, SRCCOPY);
+     hbmp = (HBITMAP) SelectObject(pcontext->hDC, pcontext->hbmpOld);
+     DeleteObject(pcontext->hDC);
+     DeleteObject(hbmp);
+     pcontext->hDC = pcontext->hDCScreen;
+ }
+ static void 
+ ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext, 
+                        RECT* prcCurrent, 
+                        CAPTIONBUTTON buttonId, 
+                        INT iStateId)
+ {
+     RECT rcPart;
+     INT ButtonWidth, ButtonHeight, iPartId;
+     
+     ButtonHeight = GetSystemMetrics( pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMSIZE : SM_CYSIZE);
+     ButtonWidth = GetSystemMetrics( pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CXSMSIZE : SM_CXSIZE);
+     switch(buttonId)
+     {
+     case CLOSEBUTTON:
+         iPartId = pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
+         break;
+     case MAXBUTTON:
+         if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
+         {
+             if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
+                 return;
+             else
+                 iStateId = BUTTON_DISABLED;
+         }
+         iPartId = pcontext->wi.dwStyle & WS_MAXIMIZE ? WP_RESTOREBUTTON : WP_MAXBUTTON;
+         break;
+     case MINBUTTON:
+         if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
+         {
+             if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
+                 return;
+             else
+                 iStateId = BUTTON_DISABLED;
+         }
+  
+         iPartId = WP_MINBUTTON;
+         break;
+     default:
+         //FIXME: Implement Help Button 
+         return;
+     }
+     ButtonHeight -= 4;
+     ButtonWidth -= 4;
+     /* Calculate the position */
+     rcPart.top = prcCurrent->top;
+     rcPart.right = prcCurrent->right;
+     rcPart.bottom = rcPart.top + ButtonHeight ;
+     rcPart.left = rcPart.right - ButtonWidth ;
+     prcCurrent->right -= ButtonWidth + BUTTON_GAP_SIZE;
+     DrawThemeBackground(pcontext->theme, pcontext->hDC, iPartId, iStateId, &rcPart, NULL);
+ }
+ static DWORD
+ ThemeGetButtonState(DWORD htCurrect, DWORD htHot, DWORD htDown, BOOL Active)
+ {
+     if (htHot == htCurrect)
+         return BUTTON_HOT;
+     if (!Active)
+         return BUTTON_INACTIVE;
+     if (htDown == htCurrect)
+         return BUTTON_PRESSED;
+     return BUTTON_NORMAL;
+ }
+ /* Used only from mouse event handlers */
+ static void 
+ ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext, DWORD htHot, DWORD htDown)
+ {
+     RECT rcCurrent;
+     /* Check if the window has caption buttons */
+     if (!((pcontext->wi.dwStyle & WS_CAPTION) && (pcontext->wi.dwStyle & WS_SYSMENU)))
+         return ;
+     rcCurrent.top = rcCurrent.left = 0;
+     rcCurrent.right = pcontext->wi.rcWindow.right - pcontext->wi.rcWindow.left;
+     rcCurrent.bottom = pcontext->CaptionHeight;
+     
+     /* Add a padding around the objects of the caption */
+     InflateRect(&rcCurrent, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE, 
+                             -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE);
+     /* Draw the buttons */
+     ThemeDrawCaptionButton(pcontext, &rcCurrent, CLOSEBUTTON, 
+                            ThemeGetButtonState(HTCLOSE, htHot, htDown, pcontext->Active));
+     ThemeDrawCaptionButton(pcontext, &rcCurrent, MAXBUTTON,  
+                            ThemeGetButtonState(HTMAXBUTTON, htHot, htDown, pcontext->Active));
+     ThemeDrawCaptionButton(pcontext, &rcCurrent, MINBUTTON,
+                            ThemeGetButtonState(HTMINBUTTON, htHot, htDown, pcontext->Active));
+     ThemeDrawCaptionButton(pcontext, &rcCurrent, HELPBUTTON,
+                            ThemeGetButtonState(HTHELP, htHot, htDown, pcontext->Active));
+ }
+ /* Used from WM_NCPAINT and WM_NCACTIVATE handlers*/
+ static void 
+ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+ {
+     RECT rcPart;
+     int iPart, iState;
+     HICON hIcon;
+     WCHAR *CaptionText;
+     hIcon = UserGetWindowIcon(pcontext->hWnd);
+     CaptionText = UserGetWindowCaption(pcontext->hWnd);
+     /* Get the caption part and state id */
+     if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)
+         iPart = WP_SMALLCAPTION;
+     else if (pcontext->wi.dwStyle & WS_MAXIMIZE)
+         iPart = WP_MAXCAPTION;
+     else
+         iPart = WP_CAPTION;
+     iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
+     /* Draw the caption background*/
+     rcPart = *prcCurrent;
+     rcPart.bottom = pcontext->CaptionHeight;
+     prcCurrent->top = rcPart.bottom;
+     DrawThemeBackground(pcontext->theme, pcontext->hDC,iPart,iState,&rcPart,NULL);
+     /* Add a padding around the objects of the caption */
+     InflateRect(&rcPart, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE, 
+                          -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE);
+     /* Draw the caption buttons */
+     if (pcontext->wi.dwStyle & WS_SYSMENU)
+     {
+         iState = pcontext->Active ? BUTTON_NORMAL : BUTTON_INACTIVE;
+         ThemeDrawCaptionButton(pcontext, &rcPart, CLOSEBUTTON, iState);
+         ThemeDrawCaptionButton(pcontext, &rcPart, MAXBUTTON, iState);
+         ThemeDrawCaptionButton(pcontext, &rcPart, MINBUTTON, iState);
+         ThemeDrawCaptionButton(pcontext, &rcPart, HELPBUTTON, iState);
+     }
+     
+     rcPart.top += 3 ;
+     /* Draw the icon */
+     if(hIcon && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW))
+     {
+         int IconHeight = GetSystemMetrics(SM_CYSMICON);
+         int IconWidth = GetSystemMetrics(SM_CXSMICON);
+         DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, IconHeight, 0, NULL, DI_NORMAL);
+         rcPart.left += IconWidth + 4;
+     }
+     rcPart.right -= 4;
+     /* Draw the caption */
+     if(CaptionText)
+     {
+         /*FIXME: Use DrawThemeTextEx*/
+         ThemeDrawCaptionText(pcontext->theme, 
+                              pcontext->hDC, 
+                              iPart,
+                              iState, 
+                              CaptionText, 
+                              lstrlenW(CaptionText), 
+                              DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 
+                              0, 
+                              &rcPart , 
+                              pcontext->Active);
+         HeapFree(GetProcessHeap(), 0, CaptionText);
+     }
+ }
+ static void 
+ ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+ {
+     RECT rcPart;
+     int iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
+     /* Draw the bottom border */
+     rcPart = *prcCurrent;
+     rcPart.top = rcPart.bottom - pcontext->wi.cyWindowBorders;
+     prcCurrent->bottom = rcPart.top;
+     DrawThemeBackground(pcontext->theme, pcontext->hDC, WP_FRAMEBOTTOM, iState, &rcPart, NULL);
+     /* Draw the left border */
+     rcPart = *prcCurrent;
+     rcPart.right = pcontext->wi.cxWindowBorders ;
+     prcCurrent->left = rcPart.right;
+     DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL);
+     /* Draw the right border */
+     rcPart = *prcCurrent;
+     rcPart.left = rcPart.right - pcontext->wi.cxWindowBorders;
+     prcCurrent->right = rcPart.left;
+     DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMERIGHT, iState, &rcPart, NULL);
+ }
+ static void 
+ DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
+ {
+     /* Draw outer edge */
+     if (UserHasWindowEdge(context->wi.dwStyle, context->wi.dwExStyle))
+     {
+         DrawEdge(context->hDC, prcCurrent, EDGE_RAISED, BF_RECT | BF_ADJUST);
+     } 
+     else if (context->wi.dwExStyle & WS_EX_STATICEDGE)
+     {
+         DrawEdge(context->hDC, prcCurrent, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
+     }
+     /* Firstly the "thick" frame */
+     if ((context->wi.dwStyle & WS_THICKFRAME) && !(context->wi.dwStyle & WS_MINIMIZE))
+     {
+         INT Width =
+             (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
+             GetSystemMetrics(SM_CXBORDER);
+         INT Height =
+             (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
+             GetSystemMetrics(SM_CYBORDER);
+         SelectObject(context->hDC, GetSysColorBrush(
+                      context->Active ? COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER));
+         /* Draw frame */
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 
+                prcCurrent->right - prcCurrent->left, Height, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 
+                Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom, 
+                prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->right, prcCurrent->top, 
+                -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
+         InflateRect(prcCurrent, -Width, -Height);
+     }
+     /* Now the other bit of the frame */
+     if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || context->wi.dwExStyle & WS_EX_DLGMODALFRAME)
+     {
+         INT Width = GetSystemMetrics(SM_CXBORDER);
+         INT Height = GetSystemMetrics(SM_CYBORDER);
+         SelectObject(context->hDC, GetSysColorBrush(
+             (context->wi.dwExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
+             (context->wi.dwExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
+             (context->wi.dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
+             COLOR_WINDOWFRAME));
+         /* Draw frame */
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 
+                prcCurrent->right - prcCurrent->left, Height, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 
+                Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom, 
+                prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
+         PatBlt(context->hDC, prcCurrent->right, prcCurrent->top, 
+               -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
+         InflateRect(prcCurrent, -Width, -Height);
+     }
+     if (context->wi.dwExStyle & WS_EX_CLIENTEDGE)
+     {
+         DrawEdge(context->hDC, prcCurrent, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+     }
+ }
+ static void
+ ThemeDrawMenuItem(PDRAW_CONTEXT pcontext, HMENU Menu, int imenu)
+ {
+     PWCHAR Text;
+     BOOL flat_menu = FALSE;
+     MENUITEMINFOW Item;
+     RECT Rect,rcCalc;
+     WCHAR wstrItemText[20];
+     register int i = 0;
+     HFONT FontOld = NULL;
+     UINT uFormat = DT_CENTER | DT_VCENTER | DT_SINGLELINE;
+     Item.cbSize = sizeof(MENUITEMINFOW);
+     Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
+     Item.dwTypeData = wstrItemText;
+     Item.cch = 20;
+     if (!GetMenuItemInfoW(Menu, imenu, TRUE, &Item))
+         return;
+     if(Item.fType & MF_SEPARATOR)
+         return;
+     if(Item.cch >= 20)
+     {
+         Item.cch++;
+         Item.dwTypeData = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, Item.cch  * sizeof(WCHAR));
+         Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
+         GetMenuItemInfoW(Menu, imenu, TRUE, &Item);
+     }
+     if(Item.cch == 0)
+         return;
+     flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
+     GetMenuItemRect(pcontext->hWnd, Menu, imenu, &Rect);
+ #ifdef __REACTOS__
+     OffsetRect(&Rect, -pcontext->wi.rcClient.left, -pcontext->wi.rcClient.top);
+ #else
+     OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
+ #endif
+     
+     SetBkColor(pcontext->hDC, GetSysColor(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
+     SetTextColor(pcontext->hDC, GetSysColor(Item.fState & MF_GRAYED ? COLOR_GRAYTEXT : COLOR_MENUTEXT));
+     if (0 != (Item.fState & MFS_DEFAULT))
+     {
+         FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFontBold);
+     }
+     Rect.left += MENU_BAR_ITEMS_SPACE / 2;
+     Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+     Text = (PWCHAR) Item.dwTypeData;
+     if(Text)
+     {
+         for (i = 0; L'\0' != Text[i]; i++)
+         {
+             if (L'\t' == Text[i] || L'\b' == Text[i])
+             {
+                 break;
+             }
+         }
+     }
+     SetBkMode(pcontext->hDC, OPAQUE);
+     if (0 != (Item.fState & MF_GRAYED))
+     {
+         if (0 == (Item.fState & MF_HILITE))
+         {
+             ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
+             SetTextColor(pcontext->hDC, RGB(0xff, 0xff, 0xff));
+             DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
+             --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
+         }
+         SetTextColor(pcontext->hDC, RGB(0x80, 0x80, 0x80));
+         SetBkMode(pcontext->hDC, TRANSPARENT);
+     }
+     
+     DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
+     /* Exclude from the clip region the area drawn by DrawText */
+     SetRect(&rcCalc, 0,0,0,0);
+     DrawTextW(pcontext->hDC, Text, i, &rcCalc, uFormat | DT_CALCRECT);
+     InflateRect( &Rect, 0, -(rcCalc.bottom+1)/2);
+     ExcludeClipRect(pcontext->hDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
+     if (NULL != FontOld)
+     {
+         SelectObject(pcontext->hDC, FontOld);
+     }
+ }
+ void WINAPI
+ ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, PRECT prcCurrent)
+ {
+     HMENU Menu;
+     MENUBARINFO MenuBarInfo;
+     int i;
+     HFONT FontOld = NULL;
+     BOOL flat_menu;
+     RECT Rect;
+     HPEN oldPen ;
+     if (!hMenuFont)
+         InitMenuFont();
+     flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
+     MenuBarInfo.cbSize = sizeof(MENUBARINFO);
+     if (! GetMenuBarInfo(pcontext->hWnd, OBJID_MENU, 0, &MenuBarInfo))
+         return;
+     Menu = GetMenu(pcontext->hWnd);
+     if (GetMenuItemCount(Menu) == 0)
+         return;
+     Rect = MenuBarInfo.rcBar;
+     OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
+     /* Draw a line under the menu*/
+     oldPen = (HPEN)SelectObject(pcontext->hDC, GetStockObject(DC_PEN));
+     SetDCPenColor(pcontext->hDC, GetSysColor(COLOR_3DFACE));
+     MoveToEx(pcontext->hDC, Rect.left, Rect.bottom, NULL);
+     LineTo(pcontext->hDC, Rect.right, Rect.bottom);
+     SelectObject(pcontext->hDC, oldPen);
+     /* Draw menu items */
+     FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFont);
+     for (i = 0; i < GetMenuItemCount(Menu); i++)
+     {
+         ThemeDrawMenuItem(pcontext, Menu, i);
+     }
+     SelectObject(pcontext->hDC, FontOld);
+     /* Fill the menu background area that isn't painted yet*/
+     FillRect(pcontext->hDC, &Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
+ }
+ static void 
+ ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+ {
+     if(!(pcontext->wi.dwStyle & WS_VISIBLE))
+         return;
+     if(pcontext->wi.dwStyle & WS_MINIMIZE)
+     {
+         ThemeDrawTitle(pcontext, prcCurrent);
+         return;
+     }
+     if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION)
+     {
+         ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight);
+         ThemeDrawCaption(pcontext, prcCurrent);
+         ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight);
+         ThemeDrawBorders(pcontext, prcCurrent);
+     }
+     else
+     {
+         DrawClassicFrame(pcontext, prcCurrent);
+     }
+     if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle))
+         ThemeDrawMenuBar(pcontext, prcCurrent);
+     
+     if(pcontext->wi.dwStyle & WS_HSCROLL)
+         ThemeDrawScrollBar(pcontext, SB_HORZ , NULL);
+     if(pcontext->wi.dwStyle & WS_VSCROLL)
+         ThemeDrawScrollBar(pcontext, SB_VERT, NULL);
+ }
+ /*
+     Message handlers
+  */
+ static LRESULT 
+ ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)
+ {
+     DRAW_CONTEXT context;
+     RECT rcCurrent;
+     ThemeInitDrawContext(&context, hWnd, hRgn);
+     rcCurrent = context.wi.rcWindow;
+     OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
+     ThemePaintWindow(&context, &rcCurrent);
+     ThemeCleanupDrawContext(&context);
+     return 0;
+ }
+ static LRESULT 
+ ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt)
+ {
+     DRAW_CONTEXT context;
+     TRACKMOUSEEVENT tme;
+     tme.cbSize = sizeof(TRACKMOUSEEVENT);
+     tme.dwFlags = TME_QUERY;
+     tme.hwndTrack  = hWnd;
+     TrackMouseEvent(&tme);
+         if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
+     {
+         tme.hwndTrack  = hWnd;
+         tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
+         TrackMouseEvent(&tme);
+     }
+     ThemeInitDrawContext(&context, hWnd, 0);
+     ThemeDrawCaptionButtons(&context, ht, 0);
+    if(context.wi.dwStyle & WS_HSCROLL)
+         ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
+     if(context.wi.dwStyle & WS_VSCROLL)
+         ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
+     ThemeCleanupDrawContext(&context);
+     return 0;
+ }
+ static LRESULT 
+ ThemeHandleNcMouseLeave(HWND hWnd)
+ {
+     DRAW_CONTEXT context;
+     ThemeInitDrawContext(&context, hWnd, 0);
+     ThemeDrawCaptionButtons(&context, 0, 0);
+    if(context.wi.dwStyle & WS_HSCROLL)
+         ThemeDrawScrollBar(&context, SB_HORZ, NULL);
+     if(context.wi.dwStyle & WS_VSCROLL)
+         ThemeDrawScrollBar(&context, SB_VERT, NULL);
+     ThemeCleanupDrawContext(&context);
+     return 0;
+ }
+ static VOID
+ ThemeHandleButton(HWND hWnd, WPARAM wParam)
+ {
+     MSG Msg;
+     BOOL Pressed = TRUE, OldState;
+     WPARAM SCMsg, ht;
+     ULONG Style;
+     DRAW_CONTEXT context;
+     Style = GetWindowLongW(hWnd, GWL_STYLE);
+     switch (wParam)
+     {
+         case HTCLOSE:
+             if (!(Style & WS_SYSMENU))
+                 return;
+             SCMsg = SC_CLOSE;
+             break;
+         case HTMINBUTTON:
+             if (!(Style & WS_MINIMIZEBOX))
+                 return;
+             SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
+             break;
+         case HTMAXBUTTON:
+             if (!(Style & WS_MAXIMIZEBOX))
+                 return;
+             SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
+             break;
+         default :
+             return;
+     }
+     ThemeInitDrawContext(&context, hWnd, 0);
+     ThemeDrawCaptionButtons(&context, 0,  wParam);
+     SetCapture(hWnd);
+     for (;;)
+     {
+         if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
+             break;
+         if (Msg.message == WM_LBUTTONUP)
+             break;
+         if (Msg.message != WM_MOUSEMOVE)
+             continue;
+         OldState = Pressed;
+         ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y));
+         Pressed = (ht == wParam);
+         ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
+     }
+     ThemeDrawCaptionButtons(&context, 0, 0);
+     ThemeCleanupDrawContext(&context);
+     ReleaseCapture();
+     if (Pressed)
+         SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
+ }
+ static LRESULT
+ DefWndNCHitTest(HWND hWnd, POINT Point)
+ {
+     RECT WindowRect;
+     POINT ClientPoint;
+     WINDOWINFO wi;
+     GetWindowInfo(hWnd, &wi);
+     if (!PtInRect(&wi.rcWindow, Point))
+     {
+         return HTNOWHERE;
+     }
+     WindowRect = wi.rcWindow;
+     if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle))
+     {
+         LONG XSize, YSize;
+         InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders);
+         XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
+         YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
+         if (!PtInRect(&WindowRect, Point))
+         {
+             BOOL ThickFrame;
+             ThickFrame = (wi.dwStyle & WS_THICKFRAME);
+             if (Point.y < WindowRect.top)
+             {
+                 if(wi.dwStyle & WS_MINIMIZE)
+                     return HTCAPTION;
+                 if(!ThickFrame)
+                     return HTBORDER;
+                 if (Point.x < (WindowRect.left + XSize))
+                     return HTTOPLEFT;
+                 if (Point.x >= (WindowRect.right - XSize))
+                     return HTTOPRIGHT;
+                 return HTTOP;
+             }
+             if (Point.y >= WindowRect.bottom)
+             {
+                 if(wi.dwStyle & WS_MINIMIZE)
+                     return HTCAPTION;
+                 if(!ThickFrame)
+                     return HTBORDER;
+                 if (Point.x < (WindowRect.left + XSize))
+                     return HTBOTTOMLEFT;
+                 if (Point.x >= (WindowRect.right - XSize))
+                     return HTBOTTOMRIGHT;
+                 return HTBOTTOM;
+             }
+             if (Point.x < WindowRect.left)
+             {
+                 if(wi.dwStyle & WS_MINIMIZE)
+                     return HTCAPTION;
+                 if(!ThickFrame)
+                     return HTBORDER;
+                 if (Point.y < (WindowRect.top + YSize))
+                     return HTTOPLEFT;
+                 if (Point.y >= (WindowRect.bottom - YSize))
+                     return HTBOTTOMLEFT;
+                 return HTLEFT;
+             }
+             if (Point.x >= WindowRect.right)
+             {
+                 if(wi.dwStyle & WS_MINIMIZE)
+                     return HTCAPTION;
+                 if(!ThickFrame)
+                     return HTBORDER;
+                 if (Point.y < (WindowRect.top + YSize))
+                     return HTTOPRIGHT;
+                 if (Point.y >= (WindowRect.bottom - YSize))
+                     return HTBOTTOMRIGHT;
+                 return HTRIGHT;
+             }
+         }
+     }
+     else
+     {
+         if (wi.dwExStyle & WS_EX_STATICEDGE)
+             InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
+                                      -GetSystemMetrics(SM_CYBORDER));
+         if (!PtInRect(&WindowRect, Point))
+             return HTBORDER;
+     }
+     if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION)
+     {
+         if (wi.dwExStyle & WS_EX_TOOLWINDOW)
+             WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
+         else
+             WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
+         if (!PtInRect(&WindowRect, Point))
+         {
+             INT ButtonWidth;
+             if (wi.dwExStyle & WS_EX_TOOLWINDOW)
+                 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE);
+             else
+                 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
+             ButtonWidth -= 4;
+             ButtonWidth+= BUTTON_GAP_SIZE;
+             if (wi.dwStyle & WS_SYSMENU)
+             {
+                 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
+                 {
+                     WindowRect.right -= ButtonWidth;
+                 }
+                 else
+                 {
+                     if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
+                         WindowRect.left += ButtonWidth;
+                     WindowRect.right -= ButtonWidth;
+                 }
+             }
+             if (Point.x < WindowRect.left)
+                 return HTSYSMENU;
+             if (WindowRect.right <= Point.x)
+                 return HTCLOSE;
+             if (wi.dwStyle & WS_MAXIMIZEBOX || wi.dwStyle & WS_MINIMIZEBOX)
+                 WindowRect.right -= ButtonWidth;
+             if (Point.x >= WindowRect.right)
+                 return HTMAXBUTTON;
+             if (wi.dwStyle & WS_MINIMIZEBOX)
+                 WindowRect.right -= ButtonWidth;
+             if (Point.x >= WindowRect.right)
+                 return HTMINBUTTON;
+             return HTCAPTION;
+         }
+     }
+     if(!(wi.dwStyle & WS_MINIMIZE))
+     {
+         HMENU menu;
+         ClientPoint = Point;
+         ScreenToClient(hWnd, &ClientPoint);
+         GetClientRect(hWnd, &wi.rcClient);
+         if (PtInRect(&wi.rcClient, ClientPoint))
+         {
+             return HTCLIENT;
+         }
+         if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD))
+         {
+             if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
+                 return HTMENU;
+         }
+         if (wi.dwExStyle & WS_EX_CLIENTEDGE)
+         {
+             InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
+                         -2 * GetSystemMetrics(SM_CYBORDER));
+         }
+         if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) &&
+             (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
+         {
+             RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
+             HWND Parent = GetParent(hWnd);
+             TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
+             if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+                 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
+             else
+                 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
+             if (PtInRect(&TempRect, Point))
+                 return HTVSCROLL;
+             TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
+             if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+                 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
+             else
+                 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
+             if (PtInRect(&TempRect2, Point))
+                 return HTHSCROLL;
+             TempRect.top = TempRect2.top;
+             TempRect.bottom = TempRect2.bottom;
+             if(Parent)
+                 GetClientRect(Parent, &ParentRect);
+             if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle,
+                       GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect))
+             {
+                 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+                     return HTBOTTOMLEFT;
+                 else
+                     return HTBOTTOMRIGHT;
+             }
+         }
+         else
+         {
+             if (wi.dwStyle & WS_VSCROLL)
+             {
+                 RECT TempRect = WindowRect;
+                 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+                     TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
+                 else
+                     TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
+                 if (PtInRect(&TempRect, Point))
+                     return HTVSCROLL;
+             } 
+             else if (wi.dwStyle & WS_HSCROLL)
+             {
+                 RECT TempRect = WindowRect;
+                 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
+                 if (PtInRect(&TempRect, Point))
+                     return HTHSCROLL;
+             }
+         }
+     }
+     return HTNOWHERE;
+ }
+ LRESULT CALLBACK 
+ ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc)
+ {
+     switch(Msg)
+     {
+     case WM_NCPAINT:
+         return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
+     case WM_NCACTIVATE:
+         ThemeHandleNCPaint(hWnd, (HRGN)1);
+         return TRUE;
+     case WM_NCMOUSEMOVE:
+     {
+         POINT Point;
+         Point.x = GET_X_LPARAM(lParam);
+         Point.y = GET_Y_LPARAM(lParam);
+         return ThemeHandleNcMouseMove(hWnd, wParam, &Point);
+     }
+     case WM_NCMOUSELEAVE:
+         return ThemeHandleNcMouseLeave(hWnd);
+     case WM_NCLBUTTONDOWN:
+         switch (wParam)
+         {
+             case HTMINBUTTON:
+             case HTMAXBUTTON:
+             case HTCLOSE:
+             {
+                 ThemeHandleButton(hWnd, wParam);
+                 return 0;
+             }
+             default:
+                 return DefWndProc(hWnd, Msg, wParam, lParam);
+         }
+     case WM_NCHITTEST:
+     {
+         POINT Point;
+         Point.x = GET_X_LPARAM(lParam);
+         Point.y = GET_Y_LPARAM(lParam);
+         return DefWndNCHitTest(hWnd, Point);
+     }
+     case WM_SYSCOMMAND:
+     {
+         if((wParam & 0xfff0) == SC_VSCROLL ||
+            (wParam & 0xfff0) == SC_HSCROLL)
+         {
+             POINT Pt;
+             Pt.x = (short)LOWORD(lParam);
+             Pt.y = (short)HIWORD(lParam);
+             NC_TrackScrollBar(hWnd, wParam, Pt);
+         }
+         else
+         {
+             return DefWndProc(hWnd, Msg, wParam, lParam);
+         }
+     }
+     case WM_NCUAHDRAWCAPTION:
+     case WM_NCUAHDRAWFRAME:
+         /* FIXME: how should these be handled? */
+         return 0;
+     default:
+         return DefWndProc(hWnd, Msg, wParam, lParam);
+     }
+ }
  #include "vfwmsgs.h"
  #include "uxtheme.h"
  #include "tmschema.h"
+ #include "uxundoc.h"
  
  #include "uxthemedll.h"
  #include "msstyles.h"
+ #include "ncthm.h"
  
  #include "wine/debug.h"
  
@@@ -61,9 -63,10 +63,10 @@@ HINSTANCE hDllInst
  ATOM atDialogThemeEnabled;
  
  static DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
static ATOM atWindowTheme;
+ ATOM atWindowTheme;
  static ATOM atSubAppName;
  static ATOM atSubIdList;
+ ATOM atWndContrext;
  
  static BOOL bThemeActive = FALSE;
  static WCHAR szCurrentTheme[MAX_PATH];
@@@ -79,7 -82,7 +82,7 @@@ static BOOL CALLBACK UXTHEME_broadcast_
  }
  
  /* Broadcast a message to *all* windows, including children */
static BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
+ BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
  {
      if (hWnd == NULL)
      {
@@@ -140,7 -143,6 +143,6 @@@ static DWORD query_reg_path (HKEY hKey
      }
    }
  
-   RegCloseKey(hKey);
    return dwRet;
  }
  
   *
   * Set the current active theme from the registry
   */
static void UXTHEME_LoadTheme(void)
void UXTHEME_LoadTheme(BOOL bLoad)
  {
      HKEY hKey;
      DWORD buffsize;
      WCHAR tmp[10];
      PTHEME_FILE pt;
  
-     /* Get current theme configuration */
-     if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
-         TRACE("Loading theme config\n");
-         buffsize = sizeof(tmp)/sizeof(tmp[0]);
-         if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
-             bThemeActive = (tmp[0] != '0');
-         }
-         else {
-             bThemeActive = FALSE;
-             TRACE("Failed to get ThemeActive: %d\n", GetLastError());
+     if(bLoad == TRUE) 
+     {
+         /* Get current theme configuration */
+         if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
+             TRACE("Loading theme config\n");
+             buffsize = sizeof(tmp)/sizeof(tmp[0]);
+             if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
+                 bThemeActive = (tmp[0] != '0');
+             }
+             else {
+                 bThemeActive = FALSE;
+                 TRACE("Failed to get ThemeActive: %d\n", GetLastError());
+             }
+             buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
+             if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
+                 szCurrentColor[0] = '\0';
+             buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
+             if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
+                 szCurrentSize[0] = '\0';
+             if (query_reg_path (hKey, szDllName, szCurrentTheme))
+                 szCurrentTheme[0] = '\0';
+             RegCloseKey(hKey);
          }
-         buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
-         if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
-             szCurrentColor[0] = '\0';
-         buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
-         if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
-             szCurrentSize[0] = '\0';
-         if (query_reg_path (hKey, szDllName, szCurrentTheme))
-             szCurrentTheme[0] = '\0';
-         RegCloseKey(hKey);
+         else
+             TRACE("Failed to open theme registry key\n");
      }
      else
-         TRACE("Failed to open theme registry key\n");
+     {
+         bThemeActive = FALSE;
+     }
  
      if(bThemeActive) {
          /* Make sure the theme requested is actually valid */
@@@ -543,8 -552,7 +552,7 @@@ void UXTHEME_InitSystem(HINSTANCE hInst
      atSubAppName         = GlobalAddAtomW(szSubAppName);
      atSubIdList          = GlobalAddAtomW(szSubIdList);
      atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
-     UXTHEME_LoadTheme();
+     atWndContrext        = GlobalAddAtomW(L"ux_WndContext");
  }
  
  /***********************************************************************
@@@ -973,7 -981,7 +981,7 @@@ HRESULT WINAPI GetThemeDefaults(LPCWST
   *     Success: S_OK
   *     Failure: HRESULT error-code
   */
- HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
+ HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, ENUMTHEMEPROC callback,
                            LPVOID lpData)
  {
      WCHAR szDir[MAX_PATH];
@@@ -1171,7 -1179,7 +1179,7 @@@ HRESULT WINAPI EnumThemeSizes(LPWSTR ps
   * any other purpose
   */
  HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
-                                  ParseThemeIniFileProc callback, LPVOID lpData)
+                                  PARSETHEMEINIFILEPROC callback, LPVOID lpData)
  {
      FIXME("%s %s: stub\n", debugstr_w(pszIniFileName), debugstr_w(pszUnknown));
      return ERROR_CALL_NOT_IMPLEMENTED;
index 0000000,94df23a..94df23a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,398 +1,398 @@@
+ /*
+  * COPYRIGHT:       See COPYING in the top level directory
+  * PROJECT:         ReactOS uxtheme.dll
+  * FILE:            dll/win32/uxtheme/themehooks.c
+  * PURPOSE:         uxtheme user api hook functions
+  * PROGRAMMER:      Giannis Adamopoulos
+  */
+  
+ #include <windows.h>
+ #include <undocuser.h>
+ #include "vfwmsgs.h"
+ #include "uxtheme.h"
+ #include "uxthemedll.h"
+ #include "ncthm.h"
+ #include "tmschema.h"
+ #include "wine/debug.h"
+ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
+ extern HINSTANCE hDllInst;
+ LRESULT CALLBACK ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc);
+ USERAPIHOOK user32ApiHook;
+ BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
+ BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
+ PWND_CONTEXT ThemeGetWndContext(HWND hWnd)
+ {
+     PWND_CONTEXT pcontext;
+     pcontext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
+     if(pcontext == NULL)
+     {
+         pcontext = HeapAlloc(GetProcessHeap(), 
+                             HEAP_ZERO_MEMORY, 
+                             sizeof(WND_CONTEXT));
+         if(pcontext == NULL)
+         {
+             return NULL;
+         }
+         
+         SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), pcontext);
+     }
+     return pcontext;
+ }
+ void ThemeDetroyWndContext(HWND hWnd)
+ {
+     PWND_CONTEXT pContext;
+     DWORD ProcessId;
+     /*Do not destroy WND_CONTEXT of a window that belong to another process */
+     GetWindowThreadProcessId(hWnd, &ProcessId);
+     if(ProcessId != GetCurrentProcessId())
+     {
+         return;
+     }
+     pContext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
+     if(pContext == NULL)
+     {
+         return;
+     }
+     if(pContext->HasThemeRgn)
+     {
+         user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
+     }
+     
+     HeapFree(GetProcessHeap(), 0, pContext);
+     SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), NULL);
+ }
+ static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
+ {
+     ThemeDetroyWndContext(hWnd);
+     return TRUE;
+ }
+ static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
+ {
+     if (hWnd == NULL)
+     {
+         EnumWindows (ThemeCleanupWndContext, 0);
+     }
+     else
+     {
+         ThemeDetroyWndContext(hWnd);
+         EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
+     }
+     return TRUE;
+ }
+ void SetThemeRegion(HWND hWnd, PWND_CONTEXT pcontext)
+ {
+     HTHEME hTheme;
+     RECT rcWindow;
+     HRGN hrgn, hrgn1;
+     int CaptionHeight, iPart;
+     WINDOWINFO wi;
+     if(!IsAppThemed())
+     {
+         if(pcontext->HasThemeRgn)
+         {
+             pcontext->HasThemeRgn = FALSE;
+             user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
+         }
+         return;
+     }
+     wi.cbSize = sizeof(wi);
+     GetWindowInfo(hWnd, &wi);
+             
+     if((wi.dwStyle & WS_CAPTION)!=WS_CAPTION)
+     {
+         return;
+     }
+     /* Get the caption part id */
+     if (wi.dwExStyle & WS_EX_TOOLWINDOW)
+         iPart = WP_SMALLCAPTION;
+     else if (wi.dwStyle & WS_MAXIMIZE)
+         iPart = WP_MAXCAPTION;
+     else
+         iPart = WP_CAPTION;
+     pcontext->HasThemeRgn = TRUE;
+     CaptionHeight = wi.cyWindowBorders;
+     CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
+     GetWindowRect(hWnd, &rcWindow);
+     rcWindow.right -= rcWindow.left;
+     rcWindow.bottom = CaptionHeight;
+     rcWindow.top = 0;
+     rcWindow.left = 0;
+     hTheme = OpenThemeData (hWnd, L"WINDOW");
+     GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
+     CloseThemeData(hTheme);
+     GetWindowRect(hWnd, &rcWindow);
+     rcWindow.right -= rcWindow.left;
+     rcWindow.bottom -= rcWindow.top;
+     rcWindow.top = CaptionHeight;
+     rcWindow.left = 0;
+     hrgn1 = CreateRectRgnIndirect(&rcWindow);
+     CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
+     DeleteObject(hrgn1);
+     user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
+ }
+ int OnPostWinPosChanged(HWND hWnd)
+ {
+     PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
+     if(pcontext &&
+         pcontext->HasAppDefinedRgn == FALSE && 
+         pcontext->UpdatingRgn == FALSE)
+     {
+         pcontext->UpdatingRgn = TRUE;
+         SetThemeRegion(hWnd, pcontext);
+         pcontext = ThemeGetWndContext(hWnd);
+         pcontext->UpdatingRgn = FALSE;
+     }
+     return 0;
+ }
+ /**********************************************************************
+  *      Hook Functions
+  */
+ static LRESULT CALLBACK
+ ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+ {      
+     if(!IsThemeActive())
+     {
+         return user32ApiHook.DefWindowProcW(hWnd, 
+                                             Msg, 
+                                             wParam, 
+                                             lParam);
+     }
+     return ThemeWndProc(hWnd, 
+                         Msg, 
+                         wParam, 
+                         lParam, 
+                         user32ApiHook.DefWindowProcW);
+ }
+ static LRESULT CALLBACK
+ ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+ {
+     if(!IsThemeActive())
+     {
+         return user32ApiHook.DefWindowProcA(hWnd, 
+                                             Msg, 
+                                             wParam, 
+                                             lParam);
+     }
+     return ThemeWndProc(hWnd, 
+                         Msg, 
+                         wParam, 
+                         lParam, 
+                         user32ApiHook.DefWindowProcA);
+ }
+ static LRESULT CALLBACK
+ ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
+ {
+     switch(Msg)
+     {
+         case WM_THEMECHANGED:
+             UXTHEME_LoadTheme(TRUE);
+             return 0;
+     }
+     return 0;
+ }
+ static LRESULT CALLBACK
+ ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
+ {
+     switch(Msg)
+     {
+         case WM_WINDOWPOSCHANGED:
+         {
+             return OnPostWinPosChanged(hWnd);
+         }
+         case WM_DESTROY:
+         {
+             ThemeDetroyWndContext(hWnd);
+             return 0;
+         }
+     }
+     return 0;
+ }
+ int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
+ {
+     PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
+     if(pcontext)
+     {
+         pcontext->HasAppDefinedRgn = TRUE;
+         pcontext->HasThemeRgn = FALSE;
+     }
+     return user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
+ }
+ /**********************************************************************
+  *      Exports
+  */
+ BOOL CALLBACK 
+ ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
+ {
+     /* Sanity checks for the caller */
+     if (!puah || State != uahLoadInit)
+     {
+         UXTHEME_LoadTheme(FALSE);
+         ThemeCleanupWndContext(NULL, 0);
+         return TRUE;
+     }
+     /* Store the original functions from user32 */
+     user32ApiHook = *puah;
+     
+     puah->DefWindowProcA = ThemeDefWindowProcA;
+     puah->DefWindowProcW = ThemeDefWindowProcW;
+     puah->PreWndProc = ThemePreWindowProc;
+     puah->PostWndProc = ThemePostWindowProc;
+     puah->PreDefDlgProc = ThemePreWindowProc;
+     puah->PostDefDlgProc = ThemePostWindowProc;
+     puah->DefWndProcArray.MsgBitArray  = gabDWPmessages;
+     puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
+     puah->WndProcArray.MsgBitArray = gabMSGPmessages;
+     puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
+     puah->DlgProcArray.MsgBitArray = gabMSGPmessages;
+     puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
+     puah->SetWindowRgn = ThemeSetWindowRgn;
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
+     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
+     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
+     UXTHEME_LoadTheme(TRUE);
+     return TRUE;
+ }
+ typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
+ typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
+ BOOL WINAPI
+ ThemeHooksInstall()
+ {
+     PVOID lpFunc;
+     OSVERSIONINFO osvi;
+     BOOL ret;
+     lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
+     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+     GetVersionEx(&osvi);
+     if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+     {
+         PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
+         ret = lpfuncxp(hDllInst, ThemeInitApiHook);
+     }
+     else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
+     {
+         PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
+         USERAPIHOOKINFO uah;
+         uah.m_size = sizeof(uah);
+         uah.m_dllname1 = L"uxtheme.dll";
+         uah.m_funname1 = L"ThemeInitApiHook";
+         uah.m_dllname2 = NULL;
+         uah.m_funname2 = NULL;
+         ret = lpfunc2003(&uah);
+     }
+     else
+     {
+         UNIMPLEMENTED;
+         ret = FALSE;
+     }
+     UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
+     return ret;
+ }
+ BOOL WINAPI
+ ThemeHooksRemove()
+ {
+     BOOL ret;
+     ret = UnregisterUserApiHook();
+     UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
+     return ret;
+ }
        <file>main.c</file>
        <file>metric.c</file>
        <file>msstyles.c</file>
+       <file>ncscrollbar.c</file>
+       <file>nonclient.c</file>
        <file>property.c</file>
        <file>stylemap.c</file>
        <file>system.c</file>
+       <file>themehooks.c</file>
        <file>uxini.c</file>
        <file>version.rc</file>
        <library>wine</library>
@@@ -29,8 -29,8 +29,8 @@@
  31 stub -noname InitUserTheme
  32 stub -noname InitUserRegistry
  33 stub -noname ReestablishServerConnection
- 34 stub -noname ThemeHooksInstall
- 35 stub -noname ThemeHooksRemove
+ 34 stdcall -noname ThemeHooksInstall()
+ 35 stdcall -noname ThemeHooksRemove()
  36 stub -noname RefreshThemeForTS
  43 stub -noname ClassicGetSystemMetrics
  44 stub -noname ClassicSystemParametersInfoA
@@@ -95,3 -95,4 +95,4 @@@
  @ stdcall OpenThemeData(ptr wstr)
  @ stdcall SetThemeAppProperties(long)
  @ stdcall SetWindowTheme(ptr wstr wstr)
+ @ stdcall ThemeInitApiHook(long ptr)
  #ifndef __WINE_UXTHEMEDLL_H
  #define __WINE_UXTHEMEDLL_H
  
- typedef HANDLE HTHEMEFILE;
- /**********************************************************************
-  *              EnumThemeProc
-  *
-  * Callback function for EnumThemes.
-  *
-  * RETURNS
-  *     TRUE to continue enumeration, FALSE to stop
-  *
-  * PARAMS
-  *     lpReserved          Always 0
-  *     pszThemeFileName    Full path to theme msstyles file
-  *     pszThemeName        Display name for theme
-  *     pszToolTip          Tooltip name for theme
-  *     lpReserved2         Always 0
-  *     lpData              Value passed through lpData from EnumThemes
-  */
- typedef BOOL (CALLBACK *EnumThemeProc)(LPVOID lpReserved, LPCWSTR pszThemeFileName,
-                                        LPCWSTR pszThemeName, LPCWSTR pszToolTip, LPVOID lpReserved2,
-                                        LPVOID lpData);
- /**********************************************************************
-  *              ParseThemeIniFileProc
-  *
-  * Callback function for ParseThemeIniFile.
-  *
-  * RETURNS
-  *     TRUE to continue enumeration, FALSE to stop
-  *
-  * PARAMS
-  *     dwType              Entry type
-  *     pszParam1           Use defined by entry type
-  *     pszParam2           Use defined by entry type
-  *     pszParam3           Use defined by entry type
-  *     dwParam             Use defined by entry type
-  *     lpData              Value passed through lpData from ParseThemeIniFile
-  *
-  * NOTES
-  * I don't know what the valid entry types are
-  */
- typedef BOOL (CALLBACK*ParseThemeIniFileProc)(DWORD dwType, LPWSTR pszParam1,
-                                               LPWSTR pszParam2, LPWSTR pszParam3,
-                                               DWORD dwParam, LPVOID lpData);
- /* Structure filled in by EnumThemeColors() and EnumeThemeSizes() with the
-  * various strings for a theme color or size. */
- typedef struct tagTHEMENAMES
- {
-     WCHAR szName[MAX_PATH+1];
-     WCHAR szDisplayName[MAX_PATH+1];
-     WCHAR szTooltip[MAX_PATH+1];
- } THEMENAMES, *PTHEMENAMES;
- /* Declarations for undocumented functions for use internally */
- DWORD WINAPI QueryThemeServices(void);
- HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
-                              LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile,
-                              DWORD unknown);
- HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile);
- HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd);
- HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
-                                 DWORD dwColorNameLen, LPWSTR pszSizeName,
-                                 DWORD dwSizeNameLen);
- HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
-                           LPVOID lpData);
- HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
-                                DWORD dwColorNum, PTHEMENAMES pszColorNames);
- HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
-                               DWORD dwSizeNum, PTHEMENAMES pszColorNames);
- HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
-                                  ParseThemeIniFileProc callback, LPVOID lpData);
  extern void UXTHEME_InitSystem(HINSTANCE hInst);
+ extern void UXTHEME_LoadTheme(BOOL bLoad);
+ extern BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg);
  
  /* No alpha blending */
  #define ALPHABLEND_NONE             0