source: trunk/EraserUI/AlphaImageList.cpp @ 27

Revision 27, 8.8 KB checked in by lowjoel, 7 years ago (diff)

In goes the 3rd party code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*********************************************************************
2* IE-like Menu and Toolbar, version 1.5 (August 3, 2004)
3* Copyright (C) 2002-2003 Michal Mecinski.
4*
5* You may freely use and modify this code, but don't remove
6* this copyright note.
7*
8* THERE IS NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, FOR
9* THIS CODE. THE AUTHOR DOES NOT TAKE THE RESPONSIBILITY
10* FOR ANY DAMAGE RESULTING FROM THE USE OF IT.
11*
12* E-mail: mimec@mimec.org
13* WWW: http://www.mimec.org
14********************************************************************/
15
16#include "stdafx.h"
17#include "AlphaImageList.h"
18#include <shlwapi.h>
19#include <math.h>
20
21#ifdef _DEBUG
22#define new DEBUG_NEW
23#endif
24
25// transparent color in non-32bit bitmaps
26#define AIL_TRANSPARENT     RGB(192,192,192)
27
28
29CAlphaImageList::CAlphaImageList()
30{
31    m_szImg = CSize(-1, -1);
32}
33
34CAlphaImageList::~CAlphaImageList()
35{
36}
37
38
39BOOL CAlphaImageList::Create(int nWidth, int nHeight, int nStyle, int nCnt)
40{
41    m_szImg = CSize(-1, -1);
42
43    m_ilNormal.DeleteImageList();
44    m_ilHot.DeleteImageList();
45    m_ilDisabled.DeleteImageList();
46
47    if (nStyle == AILS_NEW)
48    {
49        // check if comctl32.dll version 6.00 is present
50
51        BOOL bIsComCtl6 = FALSE;
52
53        HMODULE hComCtlDll = LoadLibrary(_T("comctl32.dll"));
54
55        if (hComCtlDll)
56        {
57            typedef HRESULT (CALLBACK *PFNDLLGETVERSION)(DLLVERSIONINFO*);
58
59            PFNDLLGETVERSION pfnDllGetVersion = (PFNDLLGETVERSION)GetProcAddress(hComCtlDll, "DllGetVersion");
60
61            if (pfnDllGetVersion)
62            {
63                DLLVERSIONINFO dvi;
64                ZeroMemory(&dvi, sizeof(dvi));
65                dvi.cbSize = sizeof(dvi);
66
67                HRESULT hRes = (*pfnDllGetVersion)(&dvi);
68
69                if (SUCCEEDED(hRes) && dvi.dwMajorVersion >= 6)
70                    bIsComCtl6 = TRUE;
71            }
72
73            FreeLibrary(hComCtlDll);
74        }
75
76        if (bIsComCtl6)
77            m_nBmpDepth = ILC_COLOR32;  // 32-bit images are supported
78        else
79            m_nBmpDepth = ILC_COLOR24;
80    }
81    else
82        m_nBmpDepth = ILC_COLOR4;   // old style images
83
84    if (!m_ilNormal.Create(nWidth, nHeight, m_nBmpDepth | ILC_MASK, nCnt, 1))
85        return FALSE;
86
87    if (nStyle == AILS_NEW)
88    {
89        if (!m_ilHot.Create(nWidth, nHeight, m_nBmpDepth | ILC_MASK, nCnt, 1))
90            return FALSE;
91        if (!m_ilDisabled.Create(nWidth, nHeight, m_nBmpDepth | ILC_MASK, nCnt, 1))
92            return FALSE;
93    }
94
95    m_szImg = CSize(nWidth, nHeight);
96
97    return TRUE;
98}
99
100
101BOOL CAlphaImageList::AddBitmap(UINT nID)
102{
103    if (m_szImg.cx <= 0)
104        return FALSE;
105
106    // load DIB from resources
107    HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nID), RT_BITMAP);
108    HBITMAP hBmp = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(nID),
109        IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
110
111    if (!hBmp)
112        return FALSE;
113
114    CBitmap bmp;
115    bmp.Attach(hBmp);
116
117    if (m_nBmpDepth == ILC_COLOR4)
118    {
119        // only one image list is needed
120        if (m_ilNormal.Add(&bmp, AIL_TRANSPARENT) < 0)
121            return FALSE;
122    }
123    else
124    {
125        CDC dcSrc;
126        dcSrc.CreateCompatibleDC(NULL);
127
128        struct
129        {
130            BITMAPINFOHEADER header;
131            COLORREF col[256];
132        } bmpi;
133
134        ZeroMemory(&bmpi, sizeof(BITMAPINFOHEADER));
135        bmpi.header.biSize = sizeof(BITMAPINFOHEADER);
136
137        GetDIBits(dcSrc, bmp, 0, 0, NULL, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS);
138
139        int nDepth = bmpi.header.biBitCount;
140
141        if (m_nBmpDepth != ILC_COLOR32 || nDepth != 32)
142        {
143            bmpi.header.biBitCount = 24;    // convert to 24-bit image
144            bmpi.header.biCompression = BI_RGB;
145
146            nDepth = 24;
147        }
148
149        int nLineSize = ((bmpi.header.biWidth * (nDepth==32 ? 4 : 3) + 3) & ~3);
150        int nLineCnt = bmpi.header.biHeight;
151        int nSize = nLineCnt * nLineSize;
152
153        // get source bitmap data
154        BYTE* pData = new BYTE[nSize];
155        GetDIBits(dcSrc, bmp, 0, nLineCnt, pData, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS);
156
157        // create new bitmap
158        BYTE* pDest = NULL;
159        hBmp = CreateDIBSection(dcSrc, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS, (void**)&pDest, NULL, 0);
160
161        if (!hBmp)
162        {
163            delete[] pData;
164            return FALSE;
165        }
166
167        CBitmap bmpDest;
168        bmpDest.Attach(hBmp);
169
170        if (nDepth == 32)
171        {
172            memcpy(pDest, pData, nSize);
173
174            // alpha channel is used as image mask
175            if (m_ilNormal.Add(&bmpDest, (CBitmap*)NULL) < 0)
176            {
177                delete[] pData;
178                return FALSE;
179            }
180
181            // create grayscale image
182            for (int i=0; i<nSize; i+=4)
183            {
184                const double dGamma = 0.5;  // lighten image
185                double dGray = (pData[i+2] * 0.299) + (pData[i+1] * 0.587) + (pData[i+0] * 0.114);
186                pDest[i+0] = pDest[i+1] = pDest[i+2] = (BYTE)(pow(dGray / 255.0, dGamma) * 255.0);
187            }
188
189            if (m_ilDisabled.Add(&bmpDest, (CBitmap*)NULL) < 0)
190            {
191                delete[] pData;
192                return FALSE;
193            }
194
195            // create saturated image
196            for (int i=0; i<nSize; i+=4)
197            {
198                const double dGamma = 1.4;  // darken image
199                pDest[i+0] = (BYTE)(pow(pData[i+0] / 255.0, dGamma) * 255.0);
200                pDest[i+1] = (BYTE)(pow(pData[i+1] / 255.0, dGamma) * 255.0);
201                pDest[i+2] = (BYTE)(pow(pData[i+2] / 255.0, dGamma) * 255.0);
202            }
203
204            if (m_ilHot.Add(&bmpDest, (CBitmap*)NULL) < 0)
205            {
206                delete[] pData;
207                return FALSE;
208            }
209
210            delete[] pData;
211        }
212        else
213        {
214            memcpy(pDest, pData, nSize);
215       
216            // create image mask from transparent color
217            if (m_ilNormal.Add(&bmpDest, AIL_TRANSPARENT) < 0)
218            {
219                delete[] pData;
220                return FALSE;
221            }
222
223            for (int y=0; y<nLineCnt; y++)
224            {
225                for (int x=0; x<nLineSize; x+=3)
226                {
227                    // align index to line size
228                    int i = y*nLineSize + x;
229
230                    // transparent color is not modified
231                    if (RGB(pData[i+2], pData[i+1], pData[i+0]) == AIL_TRANSPARENT)
232                    {
233                        pDest[i+2] = GetRValue(AIL_TRANSPARENT);
234                        pDest[i+1] = GetGValue(AIL_TRANSPARENT);
235                        pDest[i+0] = GetBValue(AIL_TRANSPARENT);
236                    }
237                    else
238                    {
239                        const double dGamma = 0.5;
240                        double dGray = (pData[i+2] * 0.299) + (pData[i+1] * 0.587) + (pData[i+0] * 0.114);
241                        pDest[i+0] = pDest[i+1] = pDest[i+2] = (BYTE)(pow(dGray / 255.0, dGamma) * 255.0);
242                    }
243                }
244            }
245
246            if (m_ilDisabled.Add(&bmpDest, AIL_TRANSPARENT) < 0)
247            {
248                delete[] pData;
249                return FALSE;
250            }
251
252            for (int y=0; y<nLineCnt; y++)
253            {
254                for (int x=0; x<nLineSize; x+=3)
255                {
256                    int i = y*nLineSize + x;
257
258                    if (RGB(pData[i+2], pData[i+1], pData[i+0]) == AIL_TRANSPARENT)
259                    {
260                        pDest[i+2] = GetRValue(AIL_TRANSPARENT);
261                        pDest[i+1] = GetGValue(AIL_TRANSPARENT);
262                        pDest[i+0] = GetBValue(AIL_TRANSPARENT);
263                    }
264                    else
265                    {
266                        const double dGamma = 1.4;
267                        pDest[i+0] = (BYTE)(pow(pData[i+0] / 255.0, dGamma) * 255.0);
268                        pDest[i+1] = (BYTE)(pow(pData[i+1] / 255.0, dGamma) * 255.0);
269                        pDest[i+2] = (BYTE)(pow(pData[i+2] / 255.0, dGamma) * 255.0);
270                    }
271                }
272            }
273
274            if (m_ilHot.Add(&bmpDest, AIL_TRANSPARENT) < 0)
275            {
276                delete[] pData;
277                return FALSE;
278            }
279
280            delete[] pData;
281        }
282    }
283
284    return TRUE;
285}
286
287
288BOOL CAlphaImageList::Draw(CDC* pDC, CPoint ptPos, int nImgList, int nIndex)
289{
290    if (m_szImg.cx <= 0)
291        return FALSE;
292
293    if (m_nBmpDepth >= ILC_COLOR24)
294    {
295        switch (nImgList)
296        {
297        case AIL_NORMAL:
298            return m_ilNormal.Draw(pDC, nIndex, ptPos, ILD_NORMAL);
299        case AIL_HOT:
300            return m_ilHot.Draw(pDC, nIndex, ptPos, ILD_NORMAL);
301        case AIL_DISABLED:
302            return m_ilDisabled.Draw(pDC, nIndex, ptPos, ILD_NORMAL);
303        default:
304            return FALSE;
305        }
306    }
307    else    // old style image
308    {
309        switch (nImgList)
310        {
311        case AIL_NORMAL:
312        case AIL_HOT:
313            return m_ilNormal.Draw(pDC, nIndex, ptPos, ILD_NORMAL);
314
315        case AIL_DISABLED:
316            {
317                CDC dcBmpBW;
318                dcBmpBW.CreateCompatibleDC(pDC);
319
320                // create a black and white bitmap
321                struct {
322                    BITMAPINFOHEADER bmiHeader; 
323                    RGBQUAD bmiColors[2]; 
324                } bmpiBW = {{
325                    sizeof(BITMAPINFOHEADER),
326                    m_szImg.cx, m_szImg.cy, 1, 1, BI_RGB, 0, 0, 0, 0, 0
327                }, {
328                  { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
329                }};
330
331                VOID *pTemp;
332                HBITMAP hBmpBW = CreateDIBSection(dcBmpBW, (LPBITMAPINFO)&bmpiBW,
333                    DIB_RGB_COLORS, &pTemp, NULL, 0);
334
335                if (!hBmpBW)
336                    return FALSE;
337
338                CBitmap bmpBW;
339                bmpBW.Attach(hBmpBW);
340
341                dcBmpBW.SelectObject(&bmpBW);
342
343                // draw the image with white background
344                COLORREF crOld = m_ilNormal.SetBkColor(RGB(255,255,255));
345
346                if (!m_ilNormal.Draw(&dcBmpBW, nIndex, CPoint(0,0), ILD_NORMAL))
347                    return FALSE;
348
349                m_ilNormal.SetBkColor(crOld);
350
351                BOOL bFlat = FALSE;
352#ifndef SPI_GETFLATMENU
353#   define SPI_GETFLATMENU      0x1022
354#endif
355                SystemParametersInfo(SPI_GETFLATMENU, 0, &bFlat, 0);
356
357                CBrush brush;
358
359                if (!bFlat) // highlight is not drawn in XP-style menus
360                {
361                    brush.CreateSysColorBrush(COLOR_3DHILIGHT);
362                    pDC->SelectObject(&brush);
363                    pDC->BitBlt(ptPos.x + 1, ptPos.y + 1, m_szImg.cx, m_szImg.cy, &dcBmpBW, 0, 0, 0xB8074A);
364                    brush.DeleteObject();
365                }
366
367                // draw image with the shadow color
368                brush.CreateSysColorBrush(COLOR_3DSHADOW);
369                pDC->SelectObject(&brush);
370                pDC->BitBlt(ptPos.x, ptPos.y, m_szImg.cx, m_szImg.cy, &dcBmpBW, 0, 0, 0xB8074A);
371            }
372
373        default:
374            return FALSE;
375        }
376    }
377}
378
379
380HIMAGELIST CAlphaImageList::GetImageList(int nImgList)
381{
382    switch (nImgList)
383    {
384    case AIL_NORMAL:
385        return m_ilNormal.m_hImageList;
386    case AIL_HOT:
387        return m_ilHot.m_hImageList;
388    case AIL_DISABLED:
389        return m_ilDisabled.m_hImageList;
390    default:
391        return NULL;
392    }
393}
394
Note: See TracBrowser for help on using the repository browser.