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)¬ification);
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