1 /** DGui project file. 2 3 Copyright: Trogu Antonio Davide 2011-2013 4 5 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 7 Authors: Trogu Antonio Davide 8 */ 9 10 /* Windows 2000/XP/Vista/7 Compatibility Module */ 11 12 module dgui.core.wincomp; 13 14 import dgui.core.utils; 15 import dgui.core.winapi; 16 import dgui.core.charset; 17 import dgui.core.exception; 18 19 private const WIN_NOT_SUPPORTED_MSG = "This function cannot be used on Windows 2000/XP"; 20 21 enum 22 { 23 BPPF_ERASE = 0x0001, 24 } 25 26 align(1) struct BP_PAINTPARAMS 27 { 28 DWORD cbSize; 29 DWORD dwFlags; 30 RECT* prcExclude; 31 BLENDFUNCTION* pBlendFunction; 32 } 33 34 private alias HANDLE HPAINTBUFFER; 35 private alias uint BP_BUFFERFORMAT; //It's a enum but we need only one value from it, make it an alias of type uint. 36 37 private alias extern(Windows) HPAINTBUFFER function(HDC, RECT*, BP_BUFFERFORMAT, BP_PAINTPARAMS*, HDC*) BeginBufferedPaintProc; 38 private alias extern(Windows) HRESULT function(HPAINTBUFFER, RGBQUAD**, int*) GetBufferedPaintBitsProc; 39 private alias extern(Windows) HRESULT function(HPAINTBUFFER, BOOL) EndBufferedPaintProc; 40 41 private BeginBufferedPaintProc beginBufferedPaint; 42 private GetBufferedPaintBitsProc getBufferedPaintBits; 43 private EndBufferedPaintProc endBufferedPaint; 44 45 private void initBitmapInfo(ref BITMAPINFO bi, SIZE sz) 46 { 47 bi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof; 48 bi.bmiHeader.biPlanes = 1; 49 bi.bmiHeader.biCompression = 0; //BI_RGB; 50 bi.bmiHeader.biWidth = sz.cx; 51 bi.bmiHeader.biHeight = sz.cy; 52 bi.bmiHeader.biBitCount = 32; 53 } 54 55 private HBITMAP create32BitHBITMAP(HDC hdc, SIZE sz) 56 { 57 BITMAPINFO bi; 58 initBitmapInfo(bi, sz); 59 60 return CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, null, null, 0); 61 } 62 63 bool hasAlpha(ARGB* pArgb, SIZE szIco, int cxRow) 64 { 65 ulong cxDelta = cxRow - szIco.cx; 66 67 for(ulong y = szIco.cy; y; --y) 68 { 69 for(ulong x = szIco.cx; x; --x) 70 { 71 if(*pArgb++ & 0xFF000000) 72 { 73 return true; 74 } 75 } 76 77 pArgb += cxDelta; 78 } 79 80 return false; 81 } 82 83 private void convertToPARGB32(HDC hdc, ARGB* pArgb, HBITMAP hBmpMask, SIZE sz, int cxRow) 84 { 85 BITMAPINFO bi; 86 initBitmapInfo(bi, sz); 87 88 ubyte[] pBits = new ubyte[bi.bmiHeader.biWidth * 4 * bi.bmiHeader.biHeight]; 89 GetDIBits(hdc, hBmpMask, 0, bi.bmiHeader.biHeight, pBits.ptr, &bi, DIB_RGB_COLORS); 90 91 ulong cxDelta = cxRow - bi.bmiHeader.biWidth; 92 ARGB *pArgbMask = cast(ARGB*)pBits.ptr; 93 94 for(ulong y = bi.bmiHeader.biHeight; y; --y) 95 { 96 for(ulong x = bi.bmiHeader.biWidth; x; --x) 97 { 98 if(*pArgbMask++) 99 { 100 // transparent pixel 101 *pArgb++ = 0; 102 } 103 else 104 { 105 // opaque pixel 106 *pArgb++ |= 0xFF000000; 107 } 108 } 109 110 pArgb += cxDelta; 111 } 112 } 113 114 private void convertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hIcon, SIZE szIco) 115 { 116 int cxRow; 117 RGBQUAD* pRgbQuad; 118 119 getBufferedPaintBits(hPaintBuffer, &pRgbQuad, &cxRow); 120 ARGB* pArgb = cast(ARGB*)pRgbQuad; 121 122 if(!hasAlpha(pArgb, szIco, cxRow)) 123 { 124 ICONINFO ii; 125 GetIconInfo(hIcon, &ii); 126 127 if(ii.hbmMask) 128 { 129 convertToPARGB32(hdc, pArgb, ii.hbmMask, szIco, cxRow); 130 } 131 132 DeleteObject(ii.hbmColor); 133 DeleteObject(ii.hbmMask); 134 } 135 } 136 137 public HBITMAP iconToBitmapPARGB32(HICON hIcon) 138 { 139 static HMODULE hUxTheme; 140 WindowsVersion ver = getWindowsVersion(); 141 142 SIZE szIco; 143 szIco.cx = GetSystemMetrics(SM_CXSMICON); 144 szIco.cy = GetSystemMetrics(SM_CYSMICON); 145 146 RECT rIco; 147 rIco.left = 0; 148 rIco.top = 0; 149 rIco.right = szIco.cx; 150 rIco.bottom = szIco.cy; 151 152 if(ver > WindowsVersion.windowsXP) //Is Vista or 7 153 { 154 if(!hUxTheme) 155 { 156 hUxTheme = getModuleHandle("UxTheme.dll"); 157 158 beginBufferedPaint = cast(BeginBufferedPaintProc)GetProcAddress(hUxTheme, "BeginBufferedPaint"); 159 getBufferedPaintBits = cast(GetBufferedPaintBitsProc)GetProcAddress(hUxTheme, "GetBufferedPaintBits"); 160 endBufferedPaint = cast(EndBufferedPaintProc)GetProcAddress(hUxTheme, "EndBufferedPaint"); 161 } 162 163 HDC hdc = CreateCompatibleDC(null); 164 HBITMAP hBitmap = create32BitHBITMAP(hdc, szIco); 165 HBITMAP hOldBitmap = SelectObject(hdc, hBitmap); 166 167 BLENDFUNCTION bf; 168 bf.BlendOp = 0; // AC_SRC_OVER 169 bf.SourceConstantAlpha = 255; 170 bf.AlphaFormat = 1; // AC_SRC_ALPHA 171 172 BP_PAINTPARAMS pp; 173 pp.cbSize = BP_PAINTPARAMS.sizeof; 174 pp.dwFlags = BPPF_ERASE; 175 pp.pBlendFunction = &bf; 176 177 HDC hdcBuffer; 178 HPAINTBUFFER hPaintBuffer = beginBufferedPaint(hdc, &rIco, 1 /*BPBF_DIB*/, &pp, &hdcBuffer); 179 DrawIconEx(hdcBuffer, 0, 0, hIcon, szIco.cx, szIco.cy, 0, null, DI_NORMAL); 180 convertBufferToPARGB32(hPaintBuffer, hdc, hIcon, szIco); 181 endBufferedPaint(hPaintBuffer, true); 182 183 SelectObject(hdc, hOldBitmap); 184 DeleteDC(hdc); 185 186 return hBitmap; 187 } 188 189 throwException!(WindowsNotSupportedException)("Not supported in 2000/XP"); 190 return null; 191 }