1
2 // This function creates a grayscale icon starting from a given icon.
3 // The resulting icon will have the same size of the original one.
4 //
5 // Parameters:
6 // [IN] hIcon
7 // Handle to the original icon.
8 //
9 // Return value:
10 // If the function succeeds, the return value is the handle to the newly created
11 // grayscale icon.
12 // If the function fails, the return value is NULL.
13 //
14 // Updates:
15 // 26/Nov/2002 Restored 1 BitBlt operation
16 // 03/May/2002 Removed dependancy from m_hWnd
17 // Removed 1 BitBlt operation
18 //
19 HICON CButtonST::CreateGrayscaleIcon(HICON hIcon)
20 {
21 HICON hGrayIcon = NULL;
22 HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
23 BITMAP bmp;
24 HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
25 ICONINFO csII, csGrayII;
26 BOOL bRetValue = FALSE;
27
28 bRetValue = ::GetIconInfo(hIcon, &csII);
29 if (bRetValue == FALSE) return NULL;
30
31 hMainDC = ::GetDC(NULL);
32 hMemDC1 = ::CreateCompatibleDC(hMainDC);
33 hMemDC2 = ::CreateCompatibleDC(hMainDC);
34 if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
35
36 if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
37 {
38 DWORD dwWidth = csII.xHotspot*2;
39 DWORD dwHeight = csII.yHotspot*2;
40
41 csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
42 if (csGrayII.hbmColor)
43 {
44 hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
45 hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
46
47 //::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
48
49 DWORD dwLoopY = 0, dwLoopX = 0;
50 COLORREF crPixel = 0;
51 BYTE byNewPixel = 0;
52
53 for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
54 {
55 for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
56 {
57 crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
58 byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114));
59
60 if (crPixel)
61 ::SetPixel(hMemDC2, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel));
62 else
63 ::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
64 } // for
65 } // for
66
67 ::SelectObject(hMemDC1, hOldBmp1);
68 ::SelectObject(hMemDC2, hOldBmp2);
69
70 csGrayII.hbmMask = csII.hbmMask;
71
72 csGrayII.fIcon = TRUE;
73 hGrayIcon = ::CreateIconIndirect(&csGrayII);
74 } // if
75
76 ::DeleteObject(csGrayII.hbmColor);
77 //::DeleteObject(csGrayII.hbmMask);
78 } // if
79
80 ::DeleteObject(csII.hbmColor);
81 ::DeleteObject(csII.hbmMask);
82 ::DeleteDC(hMemDC1);
83 ::DeleteDC(hMemDC2);
84 ::ReleaseDC(NULL, hMainDC);
85
86 return hGrayIcon;
87 } // End of CreateGrayscaleIcon
88
89 // This function creates a icon that is 25% darker than the original.
90 // The resulting icon will have the same size of the original one.
91 //
92 // Parameters:
93 // [IN] hIcon
94 // Handle to the original icon.
95 //
96 // Return value:
97 // If the function succeeds, the return value is the handle to the newly created
98 // darker icon.
99 // If the function fails, the return value is NULL.
100 //
101 HICON CButtonST::CreateDarkerIcon(HICON hIcon)
102 {
103 HICON hGrayIcon = NULL;
104 HDC hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
105 BITMAP bmp;
106 HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL;
107 ICONINFO csII, csGrayII;
108 BOOL bRetValue = FALSE;
109
110 bRetValue = ::GetIconInfo(hIcon, &csII);
111 if (bRetValue == FALSE) return NULL;
112
113 hMainDC = ::GetDC(NULL);
114 hMemDC1 = ::CreateCompatibleDC(hMainDC);
115 hMemDC2 = ::CreateCompatibleDC(hMainDC);
116 if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
117
118 if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
119 {
120 DWORD dwWidth = csII.xHotspot*2;
121 DWORD dwHeight = csII.yHotspot*2;
122
123 csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
124 if (csGrayII.hbmColor)
125 {
126 hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
127 hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
128
129 //::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
130
131 DWORD dwLoopY = 0, dwLoopX = 0;
132 COLORREF crPixel = 0;
133
134 for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
135 {
136 for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
137 {
138 crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
139
140 if (crPixel)
141 ::SetPixel(hMemDC2, dwLoopX, dwLoopY, DarkenColor(crPixel, 0.25));
142 else
143 ::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
144 } // for
145 } // for
146
147 ::SelectObject(hMemDC1, hOldBmp1);
148 ::SelectObject(hMemDC2, hOldBmp2);
149
150 csGrayII.hbmMask = csII.hbmMask;
151
152 csGrayII.fIcon = TRUE;
153 hGrayIcon = ::CreateIconIndirect(&csGrayII);
154 } // if
155
156 ::DeleteObject(csGrayII.hbmColor);
157 //::DeleteObject(csGrayII.hbmMask);
158 } // if
159
160 ::DeleteObject(csII.hbmColor);
161 ::DeleteObject(csII.hbmMask);
162 ::DeleteDC(hMemDC1);
163 ::DeleteDC(hMemDC2);
164 ::ReleaseDC(NULL, hMainDC);
165
166 return hGrayIcon;
167 } // End of CreateDarkerIcon
168
169 COLORREF CButtonST::DarkenColor(COLORREF crColor, double dFactor)
170 {
171 if (dFactor > 0.0 && dFactor <= 1.0)
172 {
173 BYTE red,green,blue,lightred,lightgreen,lightblue;
174 red = GetRValue(crColor);
175 green = GetGValue(crColor);
176 blue = GetBValue(crColor);
177 lightred = (BYTE)(red-(dFactor * red));
178 lightgreen = (BYTE)(green-(dFactor * green));
179 lightblue = (BYTE)(blue-(dFactor * blue));
180 crColor = RGB(lightred,lightgreen,lightblue);
181 } // if
182
183 return crColor;
184 } // End of DarkenColor
185
186 // This function assigns icons to the button.
187 // Any previous icon or bitmap will be removed.
188 //
189 // Parameters:
190 // [IN] nIconIn
191 // ID number of the icon resource to show when the mouse is over the button.
192 // Pass NULL to remove any icon from the button.
193 // [IN] nCxDesiredIn
194 // Specifies the width, in pixels, of the icon to load.
195 // [IN] nCyDesiredIn
196 // Specifies the height, in pixels, of the icon to load.
197 // [IN] nIconOut
198 // ID number of the icon resource to show when the mouse is outside the button.
199 // Can be NULL.
200 // If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
201 // icon will be automatically created starting from nIconIn and converted to grayscale.
202 // If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
203 // icon will be automatically created 25% darker starting from nIconIn.
204 // [IN] nCxDesiredOut
205 // Specifies the width, in pixels, of the icon to load.
206 // [IN] nCyDesiredOut
207 // Specifies the height, in pixels, of the icon to load.
208 //
209 // Return value:
210 // BTNST_OK
211 // Function executed successfully.
212 // BTNST_INVALIDRESOURCE
213 // Failed loading the specified resource.
214 //
215 DWORD CButtonST::SetIcon(int nIconIn, int nCxDesiredIn, int nCyDesiredIn, int nIconOut, int nCxDesiredOut, int nCyDesiredOut)
216 {
217 HICON hIconIn = NULL;
218 HICON hIconOut = NULL;
219 HINSTANCE hInstResource = NULL;
220
221 // Find correct resource handle
222 hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconIn), RT_GROUP_ICON);
223
224 // Set icon when the mouse is IN the button
225 hIconIn = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconIn), IMAGE_ICON, nCxDesiredIn, nCyDesiredIn, 0);
226
227 // Set icon when the mouse is OUT the button
228 switch (nIconOut)
229 {
230 case NULL:
231 break;
232 case (int)BTNST_AUTO_GRAY:
233 hIconOut = BTNST_AUTO_GRAY;
234 break;
235 case (int)BTNST_AUTO_DARKER:
236 hIconOut = BTNST_AUTO_DARKER;
237 break;
238 default:
239 hIconOut = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconOut), IMAGE_ICON, nCxDesiredOut, nCyDesiredOut, 0);
240 break;
241 } // switch
242
243 return SetIcon(hIconIn, hIconOut);
244 } // End of SetIcon
245
246 // This function assigns icons to the button.
247 // Any previous icon or bitmap will be removed.
248 //
249 // Parameters:
250 // [IN] nIconIn
251 // ID number of the icon resource to show when the mouse is over the button.
252 // Pass NULL to remove any icon from the button.
253 // [IN] nIconOut
254 // ID number of the icon resource to show when the mouse is outside the button.
255 // Can be NULL.
256 // If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
257 // icon will be automatically created starting from nIconIn and converted to grayscale.
258 // If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
259 // icon will be automatically created 25% darker starting from nIconIn.
260 //
261 // Return value:
262 // BTNST_OK
263 // Function executed successfully.
264 // BTNST_INVALIDRESOURCE
265 // Failed loading the specified resource.
266 //
267 DWORD CButtonST::SetIcon(int nIconIn, int nIconOut)
268 {
269 return SetIcon(nIconIn, 0, 0, nIconOut, 0, 0);
270 } // End of SetIcon
271
272 // This function assigns icons to the button.
273 // Any previous icon or bitmap will be removed.
274 //
275 // Parameters:
276 // [IN] hIconIn
277 // Handle fo the icon to show when the mouse is over the button.
278 // Pass NULL to remove any icon from the button.
279 // [IN] hIconOut
280 // Handle to the icon to show when the mouse is outside the button.
281 // Can be NULL.
282 // If this parameter is the special value BTNST_AUTO_GRAY the second
283 // icon will be automatically created starting from hIconIn and converted to grayscale.
284 // If this parameter is the special value BTNST_AUTO_DARKER the second
285 // icon will be automatically created 25% darker starting from hIconIn.
286 //
287 // Return value:
288 // BTNST_OK
289 // Function executed successfully.
290 // BTNST_INVALIDRESOURCE
291 // Failed loading the specified resource.
292 //
293 DWORD CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
294 {
295 BOOL bRetValue;
296 ICONINFO ii;
297
298 // Free any loaded resource
299 FreeResources();
300
301 if (hIconIn)
302 {
303 // Icon when mouse over button?
304 m_csIcons[0].hIcon = hIconIn;
305 // Get icon dimension
306 ::ZeroMemory(&ii, sizeof(ICONINFO));
307 bRetValue = ::GetIconInfo(hIconIn, &ii);
308 if (bRetValue == FALSE)
309 {
310 FreeResources();
311 return BTNST_INVALIDRESOURCE;
312 } // if
313
314 m_csIcons[0].dwWidth = (DWORD)(ii.xHotspot * 2);
315 m_csIcons[0].dwHeight = (DWORD)(ii.yHotspot * 2);
316 ::DeleteObject(ii.hbmMask);
317 ::DeleteObject(ii.hbmColor);
318
319 // Icon when mouse outside button?
320 if (hIconOut)
321 {
322 switch ((int)hIconOut)
323 {
324 case (int)BTNST_AUTO_GRAY:
325 hIconOut = CreateGrayscaleIcon(hIconIn);
326 break;
327 case (int)BTNST_AUTO_DARKER:
328 hIconOut = CreateDarkerIcon(hIconIn);
329 break;
330 } // switch
331
332 m_csIcons[1].hIcon = hIconOut;
333 // Get icon dimension
334 ::ZeroMemory(&ii, sizeof(ICONINFO));
335 bRetValue = ::GetIconInfo(hIconOut, &ii);
336 if (bRetValue == FALSE)
337 {
338 FreeResources();
339 return BTNST_INVALIDRESOURCE;
340 } // if
341
342 m_csIcons[1].dwWidth = (DWORD)(ii.xHotspot * 2);
343 m_csIcons[1].dwHeight = (DWORD)(ii.yHotspot * 2);
344 ::DeleteObject(ii.hbmMask);
345 ::DeleteObject(ii.hbmColor);
346 } // if
347 } // if
348
349 Invalidate();
350
351 return BTNST_OK;
352 } // End of SetIcon
353
354 // This function assigns bitmaps to the button.
355 // Any previous icon or bitmap will be removed.
356 //
357 // Parameters:
358 // [IN] nBitmapIn
359 // ID number of the bitmap resource to show when the mouse is over the button.
360 // Pass NULL to remove any bitmap from the button.
361 // [IN] crTransColorIn
362 // Color (inside nBitmapIn) to be used as transparent color.
363 // [IN] nBitmapOut
364 // ID number of the bitmap resource to show when the mouse is outside the button.
365 // Can be NULL.
366 // [IN] crTransColorOut
367 // Color (inside nBitmapOut) to be used as transparent color.
368 //
369 // Return value:
370 // BTNST_OK
371 // Function executed successfully.
372 // BTNST_INVALIDRESOURCE
373 // Failed loading the specified resource.
374 // BTNST_FAILEDMASK
375 // Failed creating mask bitmap.
376 //
377 DWORD CButtonST::SetBitmaps(int nBitmapIn, COLORREF crTransColorIn, int nBitmapOut, COLORREF crTransColorOut)
378 {
379 HBITMAP hBitmapIn = NULL;
380 HBITMAP hBitmapOut = NULL;
381 HINSTANCE hInstResource = NULL;
382
383 // Find correct resource handle
384 hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nBitmapIn), RT_BITMAP);
385
386 // Load bitmap In
387 hBitmapIn = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapIn), IMAGE_BITMAP, 0, 0, 0);
388
389 // Load bitmap Out
390 switch (nBitmapOut)
391 {
392 case NULL:
393 break;
394 case (int)BTNST_AUTO_GRAY:
395 hBitmapOut = (HBITMAP)BTNST_AUTO_GRAY;
396 break;
397 case (int)BTNST_AUTO_DARKER:
398 hBitmapOut = (HBITMAP)BTNST_AUTO_DARKER;
399 break;
400 default:
401 hBitmapOut = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapOut), IMAGE_BITMAP, 0, 0, 0);
402 break;
403 } // if
404
405 return SetBitmaps(hBitmapIn, crTransColorIn, hBitmapOut, crTransColorOut);
406 } // End of SetBitmaps
407
408 // This function assigns bitmaps to the button.
409 // Any previous icon or bitmap will be removed.
410 //
411 // Parameters:
412 // [IN] hBitmapIn
413 // Handle fo the bitmap to show when the mouse is over the button.
414 // Pass NULL to remove any bitmap from the button.
415 // [IN] crTransColorIn
416 // Color (inside hBitmapIn) to be used as transparent color.
417 // [IN] hBitmapOut
418 // Handle to the bitmap to show when the mouse is outside the button.
419 // Can be NULL.
420 // [IN] crTransColorOut
421 // Color (inside hBitmapOut) to be used as transparent color.
422 //
423 // Return value:
424 // BTNST_OK
425 // Function executed successfully.
426 // BTNST_INVALIDRESOURCE
427 // Failed loading the specified resource.
428 // BTNST_FAILEDMASK
429 // Failed creating mask bitmap.
430 //
431 DWORD CButtonST::SetBitmaps(HBITMAP hBitmapIn, COLORREF crTransColorIn, HBITMAP hBitmapOut, COLORREF crTransColorOut)
432 {
433 int nRetValue = 0;
434 BITMAP csBitmapSize;
435
436 // Free any loaded resource
437 FreeResources();
438
439 if (hBitmapIn)
440 {
441 m_csBitmaps[0].hBitmap = hBitmapIn;
442 m_csBitmaps[0].crTransparent = crTransColorIn;
443 // Get bitmap size
444 nRetValue = ::GetObject(hBitmapIn, sizeof(csBitmapSize), &csBitmapSize);
445 if (nRetValue == 0)
446 {
447 FreeResources();
448 return BTNST_INVALIDRESOURCE;
449 } // if
450 m_csBitmaps[0].dwWidth = (DWORD)csBitmapSize.bmWidth;
451 m_csBitmaps[0].dwHeight = (DWORD)csBitmapSize.bmHeight;
452
453 // Create grayscale/darker bitmap BEFORE mask (of hBitmapIn)
454 switch ((int)hBitmapOut)
455 {
456 case (int)BTNST_AUTO_GRAY:
457 hBitmapOut = CreateGrayscaleBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
458 m_csBitmaps[1].hBitmap = hBitmapOut;
459 crTransColorOut = crTransColorIn;
460 break;
461 case (int)BTNST_AUTO_DARKER:
462 hBitmapOut = CreateDarkerBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
463 m_csBitmaps[1].hBitmap = hBitmapOut;
464 crTransColorOut = crTransColorIn;
465 break;
466 } // switch
467
468 // Create mask for bitmap In
469 m_csBitmaps[0].hMask = CreateBitmapMask(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
470 if (m_csBitmaps[0].hMask == NULL)
471 {
472 FreeResources();
473 return BTNST_FAILEDMASK;
474 } // if
475
476 if (hBitmapOut)
477 {
478 m_csBitmaps[1].hBitmap = hBitmapOut;
479 m_csBitmaps[1].crTransparent = crTransColorOut;
480 // Get bitmap size
481 nRetValue = ::GetObject(hBitmapOut, sizeof(csBitmapSize), &csBitmapSize);
482 if (nRetValue == 0)
483 {
484 FreeResources();
485 return BTNST_INVALIDRESOURCE;
486 } // if
487 m_csBitmaps[1].dwWidth = (DWORD)csBitmapSize.bmWidth;
488 m_csBitmaps[1].dwHeight = (DWORD)csBitmapSize.bmHeight;
489
490 // Create mask for bitmap Out
491 m_csBitmaps[1].hMask = CreateBitmapMask(hBitmapOut, m_csBitmaps[1].dwWidth, m_csBitmaps[1].dwHeight, crTransColorOut);
492 if (m_csBitmaps[1].hMask == NULL)
493 {
494 FreeResources();
495 return BTNST_FAILEDMASK;
496 } // if
497 } // if
498 } // if
499
500 Invalidate();
501
502 return BTNST_OK;
503 } // End of SetBitmaps
504