[UXTHEME] -Get rid of the hack that partly draws the menu bar in uxtheme. This was...
[reactos.git] / reactos / dll / win32 / uxtheme / nonclient.c
index ad9365f..962c5cb 100644 (file)
@@ -13,20 +13,19 @@ HFONT hMenuFontBold = NULL;
 
 void InitMenuFont(VOID)
 {
-  NONCLIENTMETRICS ncm;
+    NONCLIENTMETRICS ncm;
 
     ncm.cbSize = sizeof(NONCLIENTMETRICS); 
 
-    if(!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+    if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
     {
-      return ;
+        return;
     }
 
     hMenuFont = CreateFontIndirect(&ncm.lfMenuFont);
 
     ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
     hMenuFontBold = CreateFontIndirect(&ncm.lfMenuFont);
-
 }
 
 static BOOL 
@@ -59,31 +58,33 @@ UserHasWindowEdge(DWORD Style, DWORD ExStyle)
         return FALSE;
     if (Style & WS_THICKFRAME)
         return TRUE;
+    Style &= WS_CAPTION;
     if (Style == WS_DLGFRAME || Style == WS_CAPTION)
         return TRUE;
    return FALSE;
 }
 
-HICON
-UserGetWindowIcon(HWND hwnd)
+static HICON
+UserGetWindowIcon(PDRAW_CONTEXT pcontext)
 {
-    HICON hIcon = 0;
+    HICON hIcon = NULL;
 
-    SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
+    SendMessageTimeout(pcontext->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);
+        SendMessageTimeout(pcontext->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);
+        SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
 
     if (!hIcon)
-        hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM);
+        hIcon = (HICON)GetClassLong(pcontext->hWnd, GCL_HICONSM);
 
     if (!hIcon)
-        hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
+        hIcon = (HICON)GetClassLong(pcontext->hWnd, GCL_HICON);
 
-    if(!hIcon)
+    // See also win32ss/user/ntuser/nonclient.c!NC_IconForWindow
+    if (!hIcon && !(pcontext->wi.dwExStyle & WS_EX_DLGMODALFRAME))
         hIcon = LoadIconW(NULL, (LPCWSTR)IDI_WINLOGO);
 
     return hIcon;
@@ -98,12 +99,6 @@ WCHAR *UserGetWindowCaption(HWND hwnd)
     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)
@@ -135,7 +130,7 @@ HRESULT WINAPI ThemeDrawCaptionText(HTHEME hTheme, HDC hdc, int iPartId, int iSt
     
     oldTextColor = SetTextColor(hdc, textColor);
     oldBkMode = SetBkMode(hdc, TRANSPARENT);
-    DrawTextW(hdc, pszText, iCharCount, &rt, dwTextFlags);
+    DrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags, pRect);
     SetBkMode(hdc, oldBkMode);
     SetTextColor(hdc, oldTextColor);
 
@@ -155,9 +150,8 @@ ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
     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->theme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL, L"WINDOW");
+    pcontext->scrolltheme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL, L"SCROLLBAR");
 
     pcontext->CaptionHeight = pcontext->wi.cyWindowBorders;
     pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
@@ -179,8 +173,6 @@ ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext)
     CloseThemeData (pcontext->theme);
     CloseThemeData (pcontext->scrolltheme);
 
-    SetPropW(pcontext->hWnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), pcontext->hPrevTheme);
-
     if(pcontext->hRgn != NULL)
     {
         DeleteObject(pcontext->hRgn);
@@ -218,9 +210,7 @@ ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext,
 {
     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);
+    SIZE ButtonSize;
 
     switch(buttonId)
     {
@@ -249,7 +239,7 @@ ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext,
                 iStateId = BUTTON_DISABLED;
         }
  
-        iPartId = WP_MINBUTTON;
+        iPartId = pcontext->wi.dwStyle & WS_MINIMIZE ? WP_RESTOREBUTTON : WP_MINBUTTON;
         break;
 
     default:
@@ -257,6 +247,11 @@ ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext,
         return;
     }
 
+    GetThemePartSize(pcontext->theme, pcontext->hDC, iPartId, 0, NULL, TS_MIN, &ButtonSize);
+
+    ButtonHeight = GetSystemMetrics( pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMSIZE : SM_CYSIZE);
+    ButtonWidth = MulDiv(ButtonSize.cx, ButtonHeight, ButtonSize.cy);
+
     ButtonHeight -= 4;
     ButtonWidth -= 4;
 
@@ -289,10 +284,7 @@ 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 ;
-
+    /* Calculate the area of the caption */
     rcCurrent.top = rcCurrent.left = 0;
     rcCurrent.right = pcontext->wi.rcWindow.right - pcontext->wi.rcWindow.left;
     rcCurrent.bottom = pcontext->CaptionHeight;
@@ -312,7 +304,7 @@ ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext, DWORD htHot, DWORD htDown)
                            ThemeGetButtonState(HTHELP, htHot, htDown, pcontext->Active));
 }
 
-/* Used from WM_NCPAINT and WM_NCACTIVATE handlers*/
+/* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
 static void 
 ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
 {
@@ -321,11 +313,19 @@ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
     HICON hIcon;
     WCHAR *CaptionText;
 
-    hIcon = UserGetWindowIcon(pcontext->hWnd);
+    // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
+    // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
+    if ((pcontext->wi.dwStyle & WS_SYSMENU) && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW))
+        hIcon = UserGetWindowIcon(pcontext);
+    else
+        hIcon = NULL;
+
     CaptionText = UserGetWindowCaption(pcontext->hWnd);
 
     /* Get the caption part and state id */
-    if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)
+    if (pcontext->wi.dwStyle & WS_MINIMIZE)
+        iPart = WP_MINCAPTION;
+    else if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)
         iPart = WP_SMALLCAPTION;
     else if (pcontext->wi.dwStyle & WS_MAXIMIZE)
         iPart = WP_MAXCAPTION;
@@ -334,9 +334,9 @@ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
 
     iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
 
-    /* Draw the caption background*/
+    /* Draw the caption background */
     rcPart = *prcCurrent;
-    rcPart.bottom = pcontext->CaptionHeight;
+    rcPart.bottom = rcPart.top + pcontext->CaptionHeight;
     prcCurrent->top = rcPart.bottom;
     DrawThemeBackground(pcontext->theme, pcontext->hDC,iPart,iState,&rcPart,NULL);
 
@@ -358,7 +358,7 @@ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
     rcPart.top += 3 ;
 
     /* Draw the icon */
-    if(hIcon && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW))
+    if (hIcon)
     {
         int IconHeight = GetSystemMetrics(SM_CYSMICON);
         int IconWidth = GetSystemMetrics(SM_CXSMICON);
@@ -369,9 +369,9 @@ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
     rcPart.right -= 4;
 
     /* Draw the caption */
-    if(CaptionText)
+    if (CaptionText)
     {
-        /*FIXME: Use DrawThemeTextEx*/
+        /* FIXME: Use DrawThemeTextEx */
         ThemeDrawCaptionText(pcontext->theme, 
                              pcontext->hDC, 
                              iPart,
@@ -380,7 +380,7 @@ ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
                              lstrlenW(CaptionText), 
                              DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 
                              0, 
-                             &rcPart , 
+                             &rcPart,
                              pcontext->Active);
         HeapFree(GetProcessHeap(), 0, CaptionText);
     }
@@ -400,7 +400,7 @@ ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
 
     /* Draw the left border */
     rcPart = *prcCurrent;
-    rcPart.right = pcontext->wi.cxWindowBorders ;
+    rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ;
     prcCurrent->left = rcPart.right;
     DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL);
 
@@ -442,16 +442,16 @@ DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
                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, 
+        PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1
                prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
-        PatBlt(context->hDC, prcCurrent->right, prcCurrent->top, 
+        PatBlt(context->hDC, prcCurrent->right - 1, 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)
+    if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || (context->wi.dwExStyle & WS_EX_DLGMODALFRAME))
     {
         INT Width = GetSystemMetrics(SM_CXBORDER);
         INT Height = GetSystemMetrics(SM_CYBORDER);
@@ -467,9 +467,9 @@ DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
                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, 
+        PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1
                prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
-        PatBlt(context->hDC, prcCurrent->right, prcCurrent->top, 
+        PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top, 
               -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
 
         InflateRect(prcCurrent, -Width, -Height);
@@ -481,166 +481,19 @@ DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
     }
 }
 
-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)
+ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent, BOOL bDoDoubleBuffering)
 {
     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);
+        if (bDoDoubleBuffering)
+            ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight);
         ThemeDrawCaption(pcontext, prcCurrent);
-        ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight);
+        if (bDoDoubleBuffering)
+            ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight);
         ThemeDrawBorders(pcontext, prcCurrent);
     }
     else
@@ -648,9 +501,12 @@ ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
         DrawClassicFrame(pcontext, prcCurrent);
     }
 
+    if(pcontext->wi.dwStyle & WS_MINIMIZE)
+        return;
+
     if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle))
-        ThemeDrawMenuBar(pcontext, prcCurrent);
-    
+        PaintMenuBar(pcontext->hWnd, pcontext->hDC, prcCurrent->left, prcCurrent->right, prcCurrent->top, pcontext->Active);
+
     if(pcontext->wi.dwStyle & WS_HSCROLL)
         ThemeDrawScrollBar(pcontext, SB_HORZ , NULL);
 
@@ -659,7 +515,7 @@ ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
 }
 
 /*
   Message handlers
* Message handlers
  */
 
 static LRESULT 
@@ -673,7 +529,7 @@ ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)
     rcCurrent = context.wi.rcWindow;
     OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
 
-    ThemePaintWindow(&context, &rcCurrent);
+    ThemePaintWindow(&context, &rcCurrent, TRUE);
     ThemeCleanupDrawContext(&context);
 
     return 0;
@@ -684,12 +540,25 @@ ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt)
 {
     DRAW_CONTEXT context;
     TRACKMOUSEEVENT tme;
+    DWORD style;
+    PWND_CONTEXT pcontext;
+
+    /* First of all check if we have something to do here */
+    style = GetWindowLongW(hWnd, GWL_STYLE);
+    if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
+        return 0;
 
+    /* Get theme data for this window */
+    pcontext = ThemeGetWndContext(hWnd);
+    if (pcontext == NULL)
+        return 0;
+
+    /* Begin tracking in the non client area if we are not tracking yet */
     tme.cbSize = sizeof(TRACKMOUSEEVENT);
     tme.dwFlags = TME_QUERY;
     tme.hwndTrack  = hWnd;
     TrackMouseEvent(&tme);
-        if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
+    if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
     {
         tme.hwndTrack  = hWnd;
         tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
@@ -697,16 +566,27 @@ ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt)
     }
 
     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_SYSMENU)
+    {
+        if (HT_ISBUTTON(ht) || HT_ISBUTTON(pcontext->lastHitTest))
+            ThemeDrawCaptionButtons(&context, ht, 0);
+    }
 
-    if(context.wi.dwStyle & WS_VSCROLL)
-        ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
+   if (context.wi.dwStyle & WS_HSCROLL)
+   {
+       if (ht == HTHSCROLL || pcontext->lastHitTest == HTHSCROLL)
+           ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
+   }
 
+    if (context.wi.dwStyle & WS_VSCROLL)
+    {
+        if (ht == HTVSCROLL || pcontext->lastHitTest == HTVSCROLL)
+            ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
+    }
     ThemeCleanupDrawContext(&context);
 
+    pcontext->lastHitTest = ht;
+
     return 0;
 }
 
@@ -714,18 +594,33 @@ static LRESULT
 ThemeHandleNcMouseLeave(HWND hWnd)
 {
     DRAW_CONTEXT context;
+    DWORD style;
+    PWND_CONTEXT pWndContext;
+
+    /* First of all check if we have something to do here */
+    style = GetWindowLongW(hWnd, GWL_STYLE);
+    if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
+        return 0;
+
+    /* Get theme data for this window */
+    pWndContext = ThemeGetWndContext(hWnd);
+    if (pWndContext == NULL)
+        return 0;
 
     ThemeInitDrawContext(&context, hWnd, 0);
-    ThemeDrawCaptionButtons(&context, 0, 0);
+    if (context.wi.dwStyle & WS_SYSMENU && HT_ISBUTTON(pWndContext->lastHitTest))
+        ThemeDrawCaptionButtons(&context, 0, 0);
 
-   if(context.wi.dwStyle & WS_HSCROLL)
-        ThemeDrawScrollBar(&context, SB_HORZ, NULL);
+   if (context.wi.dwStyle & WS_HSCROLL && pWndContext->lastHitTest == HTHSCROLL)
+        ThemeDrawScrollBar(&context, SB_HORZ,  NULL);
 
-    if(context.wi.dwStyle & WS_VSCROLL)
+    if (context.wi.dwStyle & WS_VSCROLL && pWndContext->lastHitTest == HTVSCROLL)
         ThemeDrawScrollBar(&context, SB_VERT, NULL);
 
     ThemeCleanupDrawContext(&context);
 
+    pWndContext->lastHitTest = HTNOWHERE;
+
     return 0;
 }
 
@@ -733,17 +628,19 @@ static VOID
 ThemeHandleButton(HWND hWnd, WPARAM wParam)
 {
     MSG Msg;
-    BOOL Pressed = TRUE; // , OldState;
+    BOOL Pressed = TRUE;
     WPARAM SCMsg, ht;
     ULONG Style;
     DRAW_CONTEXT context;
+    PWND_CONTEXT pWndContext;
 
     Style = GetWindowLongW(hWnd, GWL_STYLE);
+    if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU)))
+        return ;
+
     switch (wParam)
     {
         case HTCLOSE:
-            if (!(Style & WS_SYSMENU))
-                return;
             SCMsg = SC_CLOSE;
             break;
         case HTMINBUTTON:
@@ -760,11 +657,19 @@ ThemeHandleButton(HWND hWnd, WPARAM wParam)
             return;
     }
 
+    /* Get theme data for this window */
+    pWndContext = ThemeGetWndContext(hWnd);
+    if (pWndContext == NULL)
+        return;
+
     ThemeInitDrawContext(&context, hWnd, 0);
     ThemeDrawCaptionButtons(&context, 0,  wParam);
+    pWndContext->lastHitTest = wParam;
 
     SetCapture(hWnd);
 
+    ht = wParam;
+
     for (;;)
     {
         if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
@@ -776,14 +681,19 @@ ThemeHandleButton(HWND hWnd, WPARAM wParam)
         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);
+        /* Only draw the buttons if the hit test changed */
+        if (ht != pWndContext->lastHitTest &&
+            (HT_ISBUTTON(ht) || HT_ISBUTTON(pWndContext->lastHitTest)))
+        {
+            ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
+            pWndContext->lastHitTest = ht;
+        }
     }
 
-    ThemeDrawCaptionButtons(&context, 0, 0);
+    ThemeDrawCaptionButtons(&context, ht, 0);
     ThemeCleanupDrawContext(&context);
 
     ReleaseCapture();
@@ -800,6 +710,7 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
     POINT ClientPoint;
     WINDOWINFO wi;
 
+    wi.cbSize = sizeof(wi);
     GetWindowInfo(hWnd, &wi);
 
     if (!PtInRect(&wi.rcWindow, Point))
@@ -888,7 +799,6 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
 
         if (!PtInRect(&WindowRect, Point))
         {
-
             INT ButtonWidth;
 
             if (wi.dwExStyle & WS_EX_TOOLWINDOW)
@@ -897,7 +807,7 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
                 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
 
             ButtonWidth -= 4;
-            ButtonWidth+= BUTTON_GAP_SIZE;
+            ButtonWidth += BUTTON_GAP_SIZE;
 
             if (wi.dwStyle & WS_SYSMENU)
             {
@@ -907,7 +817,13 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
                 }
                 else
                 {
-                    if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
+                    // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
+                    // FIXME: The real test should check whether there is
+                    // an icon for the system window, and if so, do the
+                    // rect.left increase.
+                    // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
+                    // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
+                    // the test better.
                         WindowRect.left += ButtonWidth;
                     WindowRect.right -= ButtonWidth;
                 }
@@ -1021,9 +937,19 @@ ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndPr
     {
     case WM_NCPAINT:
         return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
+    //
+    // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
+    //
     case WM_NCUAHDRAWCAPTION:
+    //
+    // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
+    //
     case WM_NCUAHDRAWFRAME:
     case WM_NCACTIVATE:
+
+        if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) != WS_CAPTION)
+            return TRUE;
+
         ThemeHandleNCPaint(hWnd, (HRGN)1);
         return TRUE;
     case WM_NCMOUSEMOVE:
@@ -1075,3 +1001,71 @@ ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndPr
         return DefWndProc(hWnd, Msg, wParam, lParam);
     }
 }
+
+HRESULT WINAPI DrawNCPreview(HDC hDC, 
+                             DWORD DNCP_Flag,
+                             LPRECT prcPreview, 
+                             LPCWSTR pszThemeFileName, 
+                             LPCWSTR pszColorName,
+                             LPCWSTR pszSizeName,
+                             PNONCLIENTMETRICSW pncMetrics,
+                             COLORREF* lpaRgbValues)
+{
+    WNDCLASSEXW DummyPreviewWindowClass;
+    HWND hwndDummy;
+    HRESULT hres;
+    HTHEMEFILE hThemeFile;
+    DRAW_CONTEXT context;
+    RECT rcCurrent;
+
+    /* FIXME: We also need to implement drawing the rest of the preview windows 
+     *        and make use of the ncmetrics and colors passed as parameters */
+
+    /* Create a dummy window that will be used to trick the paint funtions */
+    memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass));
+    DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass);
+    DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass";
+    DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+    DummyPreviewWindowClass.hInstance = hDllInst;
+    DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW;
+    if (!RegisterClassExW(&DummyPreviewWindowClass))
+        return E_FAIL;
+
+    hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL);
+    if (!hwndDummy)
+        return E_FAIL;
+
+    hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0);
+    if (FAILED(hres))
+        return hres;
+
+    /* Initialize the special draw context for the preview */
+    context.hDC = hDC;
+    context.hWnd = hwndDummy;
+    context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0);
+    if (!context.theme)
+        return E_FAIL;
+    context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0);
+    if (!context.theme)
+        return E_FAIL;
+    context.Active = TRUE;
+    context.wi.cbSize = sizeof(context.wi);
+    if (!GetWindowInfo(hwndDummy, &context.wi))
+        return E_FAIL;
+    context.wi.dwStyle |= WS_VISIBLE;
+    context.CaptionHeight = context.wi.cyWindowBorders;
+    context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
+    context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow);
+
+    /* Paint the window on the preview hDC */
+    rcCurrent = context.wi.rcWindow;
+    ThemePaintWindow(&context, &rcCurrent, FALSE);
+    context.hDC = NULL;
+    ThemeCleanupDrawContext(&context);
+
+    /* Cleanup */
+    DestroyWindow(hwndDummy);
+    UnregisterClassW(L"DummyPreviewWindowClass", hDllInst);
+
+    return S_OK;
+}