Commit c952f08b authored by Frank Richter's avatar Frank Richter Committed by Alexandre Julliard

Add theming support for the tab control.

parent 6b3b110d
...@@ -73,6 +73,8 @@ ...@@ -73,6 +73,8 @@
#include "winnls.h" #include "winnls.h"
#include "commctrl.h" #include "commctrl.h"
#include "comctl32.h" #include "comctl32.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "wine/debug.h" #include "wine/debug.h"
#include <math.h> #include <math.h>
...@@ -153,6 +155,8 @@ typedef struct ...@@ -153,6 +155,8 @@ typedef struct
#define TAB_HOTTRACK_TIMER 1 #define TAB_HOTTRACK_TIMER 1
#define TAB_HOTTRACK_TIMER_INTERVAL 100 /* milliseconds */ #define TAB_HOTTRACK_TIMER_INTERVAL 100 /* milliseconds */
static const WCHAR themeClass[] = { 'T','a','b',0 };
/****************************************************************************** /******************************************************************************
* Prototypes * Prototypes
*/ */
...@@ -658,6 +662,22 @@ TAB_DrawLoneItemInterior(TAB_INFO* infoPtr, int iItem) ...@@ -658,6 +662,22 @@ TAB_DrawLoneItemInterior(TAB_INFO* infoPtr, int iItem)
ReleaseDC(infoPtr->hwnd, hdc); ReleaseDC(infoPtr->hwnd, hdc);
} }
/* update a tab after hottracking - invalidate it or just redraw the interior,
* based on whether theming is used or not */
static inline void hottrack_refresh (TAB_INFO* infoPtr, int tabIndex)
{
if (tabIndex == -1) return;
if (GetWindowTheme (infoPtr->hwnd))
{
RECT rect;
TAB_InternalGetItemRect(infoPtr, tabIndex, &rect, NULL);
InvalidateRect (infoPtr->hwnd, &rect, FALSE);
}
else
TAB_DrawLoneItemInterior(infoPtr, tabIndex);
}
/****************************************************************************** /******************************************************************************
* TAB_HotTrackTimerProc * TAB_HotTrackTimerProc
* *
...@@ -697,7 +717,7 @@ TAB_HotTrackTimerProc ...@@ -697,7 +717,7 @@ TAB_HotTrackTimerProc
/* Redraw iHotTracked to look normal */ /* Redraw iHotTracked to look normal */
INT iRedraw = infoPtr->iHotTracked; INT iRedraw = infoPtr->iHotTracked;
infoPtr->iHotTracked = -1; infoPtr->iHotTracked = -1;
TAB_DrawLoneItemInterior(infoPtr, iRedraw); hottrack_refresh (infoPtr, iRedraw);
/* Kill this timer */ /* Kill this timer */
KillTimer(hwnd, TAB_HOTTRACK_TIMER); KillTimer(hwnd, TAB_HOTTRACK_TIMER);
...@@ -738,7 +758,8 @@ TAB_RecalcHotTrack ...@@ -738,7 +758,8 @@ TAB_RecalcHotTrack
if (out_redrawEnter != NULL) if (out_redrawEnter != NULL)
*out_redrawEnter = -1; *out_redrawEnter = -1;
if (GetWindowLongW(infoPtr->hwnd, GWL_STYLE) & TCS_HOTTRACK) if ((GetWindowLongW(infoPtr->hwnd, GWL_STYLE) & TCS_HOTTRACK)
|| GetWindowTheme (infoPtr->hwnd))
{ {
POINT pt; POINT pt;
UINT flags; UINT flags;
...@@ -816,10 +837,8 @@ TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) ...@@ -816,10 +837,8 @@ TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
** status. */ ** status. */
TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter); TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter);
if (redrawLeave != -1) hottrack_refresh (infoPtr, redrawLeave);
TAB_DrawLoneItemInterior(infoPtr, redrawLeave); hottrack_refresh (infoPtr, redrawEnter);
if (redrawEnter != -1)
TAB_DrawLoneItemInterior(infoPtr, redrawEnter);
return 0; return 0;
} }
...@@ -1438,7 +1457,8 @@ TAB_EraseTabInterior ...@@ -1438,7 +1457,8 @@ TAB_EraseTabInterior
} }
else /* !TCS_BUTTONS */ else /* !TCS_BUTTONS */
{ {
FillRect(hdc, &rTemp, hbr); if (!GetWindowTheme (infoPtr->hwnd))
FillRect(hdc, &rTemp, hbr);
} }
/* Cleanup */ /* Cleanup */
...@@ -1600,9 +1620,10 @@ TAB_DrawItemInterior ...@@ -1600,9 +1620,10 @@ TAB_DrawItemInterior
* Setup for text output * Setup for text output
*/ */
oldBkMode = SetBkMode(hdc, TRANSPARENT); oldBkMode = SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, (((iItem == infoPtr->iHotTracked) && !(lStyle & TCS_FLATBUTTONS)) | if (!GetWindowTheme (infoPtr->hwnd))
(TAB_GetItem(infoPtr, iItem)->dwState & TCIS_HIGHLIGHTED)) ? SetTextColor(hdc, (((iItem == infoPtr->iHotTracked) && !(lStyle & TCS_FLATBUTTONS)) |
comctl32_color.clrHighlight : comctl32_color.clrBtnText); (TAB_GetItem(infoPtr, iItem)->dwState & TCIS_HIGHLIGHTED)) ?
comctl32_color.clrHighlight : comctl32_color.clrBtnText);
/* /*
* if owner draw, tell the owner to draw * if owner draw, tell the owner to draw
...@@ -1879,6 +1900,7 @@ static void TAB_DrawItem( ...@@ -1879,6 +1900,7 @@ static void TAB_DrawItem(
INT clRight = 0; INT clRight = 0;
INT clBottom = 0; INT clBottom = 0;
COLORREF bkgnd, corner; COLORREF bkgnd, corner;
HTHEME theme;
/* /*
* Get the rectangle for the item. * Get the rectangle for the item.
...@@ -1955,7 +1977,53 @@ static void TAB_DrawItem( ...@@ -1955,7 +1977,53 @@ static void TAB_DrawItem(
*/ */
fillRect = r; fillRect = r;
if(lStyle & TCS_VERTICAL) /* Draw themed tabs - but only if they are at the top.
* Windows draws even side or bottom tabs themed, with wacky results.
* However, since in Wine apps may get themed that did not opt in via
* a manifest avoid theming when we know the result will be wrong */
if ((theme = GetWindowTheme (infoPtr->hwnd))
&& ((lStyle & (TCS_VERTICAL | TCS_BOTTOM)) == 0))
{
const static int partIds[8] = {
/* Normal item */
TABP_TABITEM,
TABP_TABITEMLEFTEDGE,
TABP_TABITEMRIGHTEDGE,
TABP_TABITEMBOTHEDGE,
/* Selected tab */
TABP_TOPTABITEM,
TABP_TOPTABITEMLEFTEDGE,
TABP_TOPTABITEMRIGHTEDGE,
TABP_TOPTABITEMBOTHEDGE,
};
int partIndex = 0;
int stateId = TIS_NORMAL;
/* selected and unselected tabs have different parts */
if (iItem == infoPtr->iSelected)
partIndex += 4;
/* The part also differs on the position of a tab on a line.
* "Visually" determining the position works well enough. */
if(selectedRect.left == 0)
partIndex += 1;
if(selectedRect.right == clRight)
partIndex += 2;
if (iItem == infoPtr->iSelected)
stateId = TIS_SELECTED;
else if (iItem == infoPtr->iHotTracked)
stateId = TIS_HOT;
else if (iItem == infoPtr->uFocus)
stateId = TIS_FOCUSED;
/* Adjust rectangle for bottommost row */
if (TAB_GetItem(infoPtr, iItem)->rect.top == infoPtr->uNumRows-1)
r.bottom += 3;
DrawThemeBackground (theme, hdc, partIds[partIndex], stateId, &r, NULL);
GetThemeBackgroundContentRect (theme, hdc, partIds[partIndex], stateId, &r, &r);
}
else if(lStyle & TCS_VERTICAL)
{ {
/* These are for adjusting the drawing of a Selected tab */ /* These are for adjusting the drawing of a Selected tab */
/* The initial values are for the normal case of non-Selected */ /* The initial values are for the normal case of non-Selected */
...@@ -2176,6 +2244,7 @@ static void TAB_DrawBorder (TAB_INFO *infoPtr, HDC hdc) ...@@ -2176,6 +2244,7 @@ static void TAB_DrawBorder (TAB_INFO *infoPtr, HDC hdc)
{ {
RECT rect; RECT rect;
DWORD lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE); DWORD lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
HTHEME theme = GetWindowTheme (infoPtr->hwnd);
GetClientRect (infoPtr->hwnd, &rect); GetClientRect (infoPtr->hwnd, &rect);
...@@ -2198,7 +2267,10 @@ static void TAB_DrawBorder (TAB_INFO *infoPtr, HDC hdc) ...@@ -2198,7 +2267,10 @@ static void TAB_DrawBorder (TAB_INFO *infoPtr, HDC hdc)
TRACE("border=(%ld,%ld)-(%ld,%ld)\n", TRACE("border=(%ld,%ld)-(%ld,%ld)\n",
rect.left, rect.top, rect.right, rect.bottom); rect.left, rect.top, rect.right, rect.bottom);
DrawEdge(hdc, &rect, EDGE_RAISED, BF_SOFT|BF_RECT); if (theme)
DrawThemeBackground (theme, hdc, TABP_PANE, 0, &rect, NULL);
else
DrawEdge(hdc, &rect, EDGE_RAISED, BF_SOFT|BF_RECT);
} }
/****************************************************************************** /******************************************************************************
...@@ -2936,6 +3008,8 @@ static LRESULT TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) ...@@ -2936,6 +3008,8 @@ static LRESULT TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
} }
} }
OpenThemeData (infoPtr->hwnd, themeClass);
/* /*
* We need to get text information so we need a DC and we need to select * We need to get text information so we need a DC and we need to select
* a font. * a font.
...@@ -2993,10 +3067,21 @@ TAB_Destroy (TAB_INFO *infoPtr) ...@@ -2993,10 +3067,21 @@ TAB_Destroy (TAB_INFO *infoPtr)
if (infoPtr->iHotTracked >= 0) if (infoPtr->iHotTracked >= 0)
KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
CloseThemeData (GetWindowTheme (infoPtr->hwnd));
Free (infoPtr); Free (infoPtr);
return 0; return 0;
} }
/* update theme after a WM_THEMECHANGED message */
static LRESULT theme_changed (TAB_INFO* infoPtr)
{
HTHEME theme = GetWindowTheme (infoPtr->hwnd);
CloseThemeData (theme);
OpenThemeData (infoPtr->hwnd, themeClass);
return 0;
}
static LRESULT TAB_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam) static LRESULT TAB_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
{ {
if (!wParam) if (!wParam)
...@@ -3176,6 +3261,9 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ...@@ -3176,6 +3261,9 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
COMCTL32_RefreshSysColors(); COMCTL32_RefreshSysColors();
return 0; return 0;
case WM_THEMECHANGED:
return theme_changed (infoPtr);
case WM_KILLFOCUS: case WM_KILLFOCUS:
case WM_SETFOCUS: case WM_SETFOCUS:
TAB_FocusChanging(infoPtr); TAB_FocusChanging(infoPtr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment