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