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, 00, nIconOut, 00);
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, 000);
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, 000);
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 
Posted on 2007-04-12 11:48 艾凡赫 阅读(849) 评论(0)  编辑 收藏 引用 所属分类: MFC技术

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理