forked from SomeSupport/eMule
-
Notifications
You must be signed in to change notification settings - Fork 97
/
ButtonsTabCtrl.cpp
205 lines (178 loc) · 7.26 KB
/
ButtonsTabCtrl.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//this file is part of eMule
//Copyright (C)2002-2008 Merkur ( strEmail.Format("%s@%s", "devteam", "emule-project.net") / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "ButtonsTabCtrl.h"
#include "OtherFunctions.h"
#include "MenuCmds.h"
#include "UserMsgs.h"
#include "VisualStylesXP.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// _WIN32_WINNT >= 0x0501 (XP only)
#define _WM_THEMECHANGED 0x031A
#define _ON_WM_THEMECHANGED() \
{ _WM_THEMECHANGED, 0, 0, 0, AfxSig_l, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(void) > (_OnThemeChanged)) \
},
///////////////////////////////////////////////////////////////////////////////
// CButtonsTabCtrl
IMPLEMENT_DYNAMIC(CButtonsTabCtrl, CTabCtrl)
BEGIN_MESSAGE_MAP(CButtonsTabCtrl, CTabCtrl)
ON_WM_CREATE()
_ON_WM_THEMECHANGED()
END_MESSAGE_MAP()
CButtonsTabCtrl::CButtonsTabCtrl()
{
}
CButtonsTabCtrl::~CButtonsTabCtrl()
{
}
void CButtonsTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CRect rect(lpDIS->rcItem);
int nTabIndex = lpDIS->itemID;
if (nTabIndex < 0)
return;
TCHAR szLabel[256];
TC_ITEM tci;
tci.mask = TCIF_TEXT;
tci.pszText = szLabel;
tci.cchTextMax = _countof(szLabel);
if (!GetItem(nTabIndex, &tci))
return;
szLabel[_countof(szLabel) - 1] = _T('\0');
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if (!pDC)
return;
CRect rcFullItem(lpDIS->rcItem);
bool bSelected = (lpDIS->itemState & ODS_SELECTED) != 0;
///////////////////////////////////////////////////////////////////////////////////////
// Adding support for XP Styles (Vista Themes) for owner drawn tab controls simply
// does *not* work under Vista. Maybe it works under XP (did not try), but that is
// meaningless because under XP a owner drawn tab control is already rendered *with*
// the proper XP Styles. So, for XP there is no need to care about the theme API at all.
//
// However, under Vista, a tab control which has the TCS_OWNERDRAWFIXED
// style gets additional 3D-borders which are applied by Vista *after* WM_DRAWITEM
// was processed. Thus, there is no known workaround available to prevent Vista from
// adding those old fashioned 3D-borders. We can render the tab control items within
// the WM_DRAWITEM handler in whatever style we want, but Vista will in each case
// overwrite the borders of each tab control item with old fashioned 3D-borders...
//
// To complete this experience, tab controls also do not support NMCUSTOMDRAW. So, the
// only known way to customize a tab control is by using TCS_OWNERDRAWFIXED which does
// however not work properly under Vista.
//
// The "solution" which is currently implemented to prevent Vista from drawing those
// 3D-borders is by using "ExcludeClipRect" to reduce the drawing area which is used
// by Windows after WM_DRAWITEM was processed. This "solution" is very sensitive to
// the used rectangles and offsets in general. Incrementing/Decrementing one of the
// "rcItem", "rcFullItem", etc. rectangles makes the entire "solution" flawed again
// because some borders would become visible again.
//
HTHEME hTheme = NULL;
int iPartId = BP_PUSHBUTTON;
int iStateId = PBS_NORMAL;
bool bVistaHotTracked = false;
bool bVistaThemeActive = theApp.IsVistaThemeActive();
if (bVistaThemeActive)
{
// To determine if the current item is in 'hot tracking' mode, we need to evaluate
// the current foreground color - there is no flag which would indicate this state
// more safely. This applies only for Vista and for tab controls which have the
// TCS_OWNERDRAWFIXED style.
bVistaHotTracked = pDC->GetTextColor() == GetSysColor(COLOR_HOTLIGHT);
hTheme = g_xpStyle.OpenThemeData(m_hWnd, L"BUTTON");
if (hTheme)
{
rcFullItem.InflateRect(2, 2); // get the real tab item rect
if (bSelected)
iStateId = PBS_PRESSED;
else
iStateId = bVistaHotTracked ? PBS_HOT : PBS_NORMAL;
// Not very smart, but this is needed (in addition to the DrawThemeBackground and the clipping)
// to fix a minor glitch in both of the bottom side corners.
CRect rcTopBorder(rcFullItem.left, rcFullItem.top, rcFullItem.right, rcFullItem.top + 2);
pDC->FillSolidRect(&rcTopBorder, GetSysColor(COLOR_BTNFACE));
if (g_xpStyle.IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId))
g_xpStyle.DrawThemeParentBackground(m_hWnd, *pDC, &rcFullItem);
g_xpStyle.DrawThemeBackground(hTheme, *pDC, iPartId, iStateId, &rcFullItem, NULL);
}
}
// Following background clearing is needed for:
// WinXP/Vista (when used without an application theme)
// Vista (when used with an application theme but without a theme for the tab control)
if ( (!g_xpStyle.IsThemeActive() || !g_xpStyle.IsAppThemed())
|| (hTheme == NULL && bVistaThemeActive) )
pDC->FillSolidRect(&lpDIS->rcItem, GetSysColor(COLOR_BTNFACE));
int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
COLORREF crOldColor = CLR_NONE;
if (bVistaHotTracked)
crOldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
rect.top += 2;
// Vista: Tab control has troubles with determining the width of a tab if the
// label contains one '&' character. To get around this, we use the old code which
// replaces one '&' character with two '&' characters and we do not specify DT_NOPREFIX
// here when drawing the text.
//
// Vista: "DrawThemeText" can not be used in case we need a certain foreground color. Thus we always us
// "DrawText" to always get the same font and metrics (just for safety).
pDC->DrawText(szLabel, rect, DT_SINGLELINE | DT_TOP | DT_CENTER /*| DT_NOPREFIX*/);
if (crOldColor != CLR_NONE)
pDC->SetTextColor(crOldColor);
pDC->SetBkMode(iOldBkMode);
if (hTheme)
{
pDC->ExcludeClipRect(&rcFullItem);
g_xpStyle.CloseThemeData(hTheme);
}
}
void CButtonsTabCtrl::PreSubclassWindow()
{
CTabCtrl::PreSubclassWindow();
InternalInit();
}
int CButtonsTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTabCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
InternalInit();
return 0;
}
void CButtonsTabCtrl::InternalInit()
{
if (theApp.IsVistaThemeActive()) {
ModifyStyle(0, TCS_OWNERDRAWFIXED);
ModifyStyle(0, TCS_HOTTRACK);
}
}
LRESULT CButtonsTabCtrl::_OnThemeChanged()
{
// Owner drawn tab control seems to have troubles with updating itself due to an XP theme change..
bool bIsOwnerDrawn = (GetStyle() & TCS_OWNERDRAWFIXED) != 0;
if (bIsOwnerDrawn)
ModifyStyle(TCS_OWNERDRAWFIXED, 0); // Reset control style to not-owner drawn
Default(); // Process original WM_THEMECHANGED message
if (bIsOwnerDrawn)
ModifyStyle(0, TCS_OWNERDRAWFIXED); // Apply owner drawn style again
return 0;
}