1 #include "CUIColorButton.h"
2 #include "CUIDialog.h"
3 #include <TCFoundation/TCUserDefaults.h>
4 
5 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
6 #define new DEBUG_CLIENTBLOCK
7 #endif
8 
9 bool CUIColorButton::sm_haveColorChangedId = false;
10 UINT CUIColorButton::sm_colorChangedId = 0;
11 
CUIColorButton(HWND hWnd,const char * defaultColorsUDKey,int r,int g,int b)12 CUIColorButton::CUIColorButton(
13 	HWND hWnd,
14 	const char *defaultColorsUDKey,
15 	int r /*= 0*/,
16 	int g /*= 0*/,
17 	int b /*= 0*/):
18 m_oldWindowProc(NULL),
19 m_hTheme(NULL),
20 m_hBrush(NULL),
21 m_mouseOver(false),
22 m_r(r),
23 m_g(g),
24 m_b(b),
25 m_defaultColorsUDKey(defaultColorsUDKey)
26 {
27 	hWindow = hWnd;
28 	SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)this);
29 	m_oldWindowProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,
30 		(LONG_PTR)staticWindowProc);
31 	CUIDialog *dialog = CUIDialog::fromHandle(GetParent(hWnd));
32 	if (dialog != NULL)
33 	{
34 		dialog->addControl(hWnd);
35 	}
36 	if (CUIThemes::isThemeLibLoaded())
37 	{
38 		m_hTheme = CUIThemes::openThemeData(hWnd, L"Button");
39 	}
40 	updateBrush();
41 	m_defaultColors.resize(16);
42 	m_defaultColors = TCUserDefaults::longVectorForKey(
43 		m_defaultColorsUDKey.c_str(), m_defaultColors, false);
44 	SetWindowLong(hWnd, GWL_STYLE,
45 		GetWindowLong(hWnd, GWL_STYLE) | BS_OWNERDRAW);
46 }
47 
~CUIColorButton(void)48 CUIColorButton::~CUIColorButton(void)
49 {
50 }
51 
updateBrush(void)52 void CUIColorButton::updateBrush(void)
53 {
54 	if (m_hBrush != NULL)
55 	{
56 		DeleteObject(m_hBrush);
57 	}
58 	m_hBrush = CreateSolidBrush(RGB(m_r, m_g, m_b));
59 }
60 
setColor(int r,int g,int b)61 void CUIColorButton::setColor(int r, int g, int b)
62 {
63 	m_r = r;
64 	m_g = g;
65 	m_b = b;
66 	updateBrush();
67 }
68 
getColor(int & r,int & g,int & b)69 void CUIColorButton::getColor(int &r, int &g, int &b)
70 {
71 	r = m_r;
72 	g = m_g;
73 	b = m_b;
74 }
75 
dealloc(void)76 void CUIColorButton::dealloc(void)
77 {
78 	if (m_hTheme != NULL)
79 	{
80 		CUIThemes::closeThemeData(m_hTheme);
81 	}
82 	if (m_hBrush != NULL)
83 	{
84 		DeleteObject(m_hBrush);
85 	}
86 	CUIWindow::dealloc();
87 }
88 
doMyDrawItem(WPARAM,LPDRAWITEMSTRUCT drawItem,LRESULT & lResult)89 bool CUIColorButton::doMyDrawItem(
90 	WPARAM /*controlId*/,
91 	LPDRAWITEMSTRUCT drawItem,
92 	LRESULT &lResult)
93 {
94 	HDC diHdc = drawItem->hDC;
95 	RECT itemRect = drawItem->rcItem;
96 	RECT origItemRect = itemRect;
97 	bool bIsPressed = (drawItem->itemState & ODS_SELECTED) != 0;
98 	bool bIsFocused = (drawItem->itemState & ODS_FOCUS) != 0;
99 	bool bDrawFocusRect = (drawItem->itemState & ODS_NOFOCUSRECT) == 0;
100 	RECT colorBoxRect;
101 
102 	SetBkMode(diHdc, TRANSPARENT);
103 	// Prepare draw... paint button background
104 	if (m_hTheme != NULL)
105 	{
106 		DWORD state = (bIsPressed) ? PBS_PRESSED : PBS_NORMAL;
107 
108 		if (state == PBS_NORMAL)
109 		{
110 			if (bIsFocused)
111 			{
112 				state = PBS_DEFAULTED;
113 			}
114 			if (m_mouseOver)
115 			{
116 				state = PBS_HOT;
117 			}
118 		}
119 		CUIThemes::drawThemeBackground(m_hTheme, diHdc, BP_PUSHBUTTON, state,
120 			&itemRect, NULL);
121 	}
122 	else
123 	{
124 		if (bIsFocused)
125 		{
126 			HBRUSH br = CreateSolidBrush(RGB(0,0,0));
127 			FrameRect(diHdc, &itemRect, br);
128 			InflateRect(&itemRect, -1, -1);
129 			DeleteObject(br);
130 		} // if
131 
132 		COLORREF crColor = GetSysColor(COLOR_BTNFACE);
133 
134 		HBRUSH	brBackground = CreateSolidBrush(crColor);
135 
136 		FillRect(diHdc, &itemRect, brBackground);
137 
138 		DeleteObject(brBackground);
139 
140 		// Draw pressed button
141 		if (bIsPressed)
142 		{
143 			HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
144 			FrameRect(diHdc, &itemRect, brBtnShadow);
145 			DeleteObject(brBtnShadow);
146 		}
147 
148 		else // ...else draw non pressed button
149 		{
150 			UINT uState = DFCS_BUTTONPUSH |
151                   (m_mouseOver ? DFCS_HOT : 0) |
152                   ((bIsPressed) ? DFCS_PUSHED : 0);
153 
154 			DrawFrameControl(diHdc, &itemRect, DFC_BUTTON, uState);
155 		} // else
156 	}
157 
158 	// Draw the focus rect
159 	if (bIsFocused && bDrawFocusRect)
160 	{
161 		RECT focusRect = itemRect;
162 
163 		// Do NOT scale
164 		InflateRect(&focusRect, -3, -3);
165 		DrawFocusRect(diHdc, &focusRect);
166 	}
167 
168 	// Draw the color box
169 	if (m_hTheme != NULL)
170 	{
171 		int margin = scalePoints(3);
172 		CUIThemes::getThemeBackgroundContentRect(m_hTheme, NULL,
173 			BP_PUSHBUTTON, PBS_HOT, &origItemRect, &colorBoxRect);
174 		InflateRect(&colorBoxRect, -margin, -margin);
175 	}
176 	else
177 	{
178 		int margin = scalePoints(5);
179 		colorBoxRect = origItemRect;
180 		InflateRect(&colorBoxRect, -margin, -margin);
181 	}
182 	FillRect(diHdc, &colorBoxRect, m_hBrush);
183 	if (m_hTheme != NULL)
184 	{
185 		CUIThemes::drawThemeEdge(m_hTheme, diHdc, BP_PUSHBUTTON, PBS_PRESSED,
186 			&colorBoxRect, EDGE_SUNKEN, BF_SOFT | BF_RECT, NULL);
187 	}
188 	else
189 	{
190 		DrawEdge(diHdc, &colorBoxRect, EDGE_SUNKEN, BF_BOTTOMLEFT | BF_TOPRIGHT);
191 	}
192 	lResult = TRUE;
193 	return true;
194 }
195 
windowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)196 LRESULT CUIColorButton::windowProc(
197 	HWND hWnd,
198 	UINT message,
199 	WPARAM wParam,
200 	LPARAM lParam)
201 {
202 	if (message == CUIDialog::getMessageForwardId())
203 	{
204 		CUIDialog::ControlMessage *cm = (CUIDialog::ControlMessage *)lParam;
205 
206 		switch (cm->msg)
207 		{
208 		case WM_DRAWITEM:
209 			cm->processed = doMyDrawItem(cm->wParam,
210 				(LPDRAWITEMSTRUCT)cm->lParam, cm->lResult);
211 			break;
212 		case WM_COMMAND:
213 			cm->processed = doMyCommand(HIWORD(cm->wParam), cm->lResult);
214 			break;
215 		}
216 		return 0;
217 	}
218 	else
219 	{
220 		switch (message)
221 		{
222 		case WM_MOUSEMOVE:
223 			CUIWindow::windowProc(hWnd, message, wParam, lParam);
224 			break;
225 		case WM_DESTROY:
226 			doMyDestroy();
227 			break;
228 		case WM_MOUSELEAVE:
229 			doMyMouseLeave();
230 			break;
231 		}
232 	}
233 	return CallWindowProc(m_oldWindowProc, hWnd, message, wParam, lParam);
234 }
235 
doMyCommand(int code,LRESULT & lResult)236 bool CUIColorButton::doMyCommand(int code, LRESULT &lResult)
237 {
238 	if (code == BN_CLICKED)
239 	{
240 		COLORREF initialColor = RGB(m_r, m_g, m_b);
241 		CHOOSECOLOR chooseColor;
242 		COLORREF customColors[16];
243 		size_t i;
244 
245 		memset(customColors, 0, sizeof(customColors));
246 		for (i = 0; i < 16; i++)
247 		{
248 			customColors[i] = (COLORREF)m_defaultColors[i];
249 		}
250 		memset(&chooseColor, 0, sizeof(chooseColor));
251 		chooseColor.lStructSize = sizeof(chooseColor);
252 		chooseColor.hwndOwner = hWindow;
253 		chooseColor.rgbResult = initialColor;
254 		chooseColor.lpCustColors = customColors;
255 		chooseColor.Flags = CC_ANYCOLOR | CC_RGBINIT;
256 		if (ChooseColor(&chooseColor))
257 		{
258 			if (chooseColor.rgbResult != initialColor)
259 			{
260 				NMHDR notification;
261 				bool customChanged = false;
262 
263 				m_r = GetRValue(chooseColor.rgbResult);
264 				m_g = GetGValue(chooseColor.rgbResult);
265 				m_b = GetBValue(chooseColor.rgbResult);
266 				for (i = 0; i < 16; i++)
267 				{
268 					if (m_defaultColors[i] != (long)customColors[i])
269 					{
270 						customChanged = true;
271 					}
272 					m_defaultColors[i] = (long)customColors[i];
273 				}
274 				if (customChanged)
275 				{
276 					TCUserDefaults::setLongVectorForKey(m_defaultColors,
277 						m_defaultColorsUDKey.c_str(), false);
278 				}
279 				updateBrush();
280 				InvalidateRect(hWindow, NULL, TRUE);
281 				notification.hwndFrom = hWindow;
282 				notification.idFrom = (WPARAM)GetWindowLong(hWindow, GWL_ID);
283 				notification.code = CCBN_COLOR_CHANGED;
284 				SendMessage(GetParent(hWindow), WM_NOTIFY,
285 					(WPARAM)notification.idFrom, (LPARAM)&notification);
286 			}
287 		}
288 		lResult = 0;
289 		return true;
290 	}
291 	return false;
292 }
293 
doMyDestroy(void)294 void CUIColorButton::doMyDestroy(void)
295 {
296 	if (m_mouseOver)
297 	{
298 		trackMouseEvent(TME_CANCEL);
299 	}
300 }
301 
doMyMouseLeave(void)302 void CUIColorButton::doMyMouseLeave(void)
303 {
304 	InvalidateRect(hWindow, NULL, TRUE);
305 	m_mouseOver = false;
306 }
307 
trackMouseEvent(DWORD dwFlags,DWORD dwHoverTime)308 void CUIColorButton::trackMouseEvent(DWORD dwFlags, DWORD dwHoverTime /*= 0*/)
309 {
310 	TRACKMOUSEEVENT tme;
311 
312 	m_mouseOver = true;
313 	memset(&tme, 0, sizeof(tme));
314 	tme.cbSize = sizeof(tme);
315 	tme.dwFlags = dwFlags;
316 	tme.hwndTrack = hWindow;
317 	tme.dwHoverTime = dwHoverTime;
318 	_TrackMouseEvent(&tme);
319 }
320 
doMouseMove(WPARAM,int,int)321 LRESULT CUIColorButton::doMouseMove(WPARAM, int /*x*/, int /*y*/)
322 {
323 	if (!m_mouseOver)
324 	{
325 		m_mouseOver = true;
326 		trackMouseEvent(TME_LEAVE);
327 		InvalidateRect(hWindow, NULL, TRUE);
328 	}
329 	return 0;
330 }
331 
332 // Note: static method
registerColorChangedId(void)333 void CUIColorButton::registerColorChangedId(void)
334 {
335 	if (!sm_haveColorChangedId)
336 	{
337 		sm_colorChangedId = RegisterWindowMessage(_UC("CUIColorButton::ColorChanged"));
338 		sm_haveColorChangedId = true;
339 	}
340 }
341 
342 // Note: static method
getColorChangedId(void)343 UINT CUIColorButton::getColorChangedId(void)
344 {
345 	registerColorChangedId();
346 	return sm_colorChangedId;
347 }
348