//--------------------------------------------------------------------------- // TextFade.cpp - text fading code (removed from taskbar) //--------------------------------------------------------------------------- // BEGIN fade-text drawing functions and friends //--------------------------------------------------------------------------- #include "stdafx.h" //--------------------------------------------------------------------------- static HBITMAP CreateDibSection32Bit(int w, int h, void** ppv) { HBITMAP bitmap; BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = w; bmi.bmiHeader.biHeight = h; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; bitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, ppv, NULL, 0); if (bitmap) memset(*ppv, 0xff, w*h*4); //32bpp=4bytes return bitmap; } //--------------------------------------------------------------------------- static void SetupAlphaChannel(DWORD* pdw, int w, int h, BYTE bstart, BYTE bend, int nExtra) { //nExtra is extra space that we want to fill with the final value int i,j; w -= nExtra; if (bstart > bend) { BYTE bdiff = bstart - bend; for (j=0;j= nLen) return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx); // too small, let's alpha blend it if ((nwidth <= 0) || (nheight <= 0)) return 1; TEXTMETRIC tm; GetTextMetrics(dc, &tm); int nPix = tm.tmAveCharWidth*5; //don't fade out more than half the text if (nPix > nwidth) nPix = nwidth/2; //Create a 32bpp dibsection to store the background void* pv = NULL; HDC dcbitmap = CreateCompatibleDC(dc); int nRet = 0; if (dcbitmap != NULL) { HBITMAP bitmap = CreateDibSection32Bit(nPix, nheight, &pv); if (bitmap != NULL) { HBITMAP tmpbmp = (HBITMAP) SelectObject(dcbitmap, bitmap); BitBlt(dcbitmap, 0, 0, nPix, nheight, dc, rc.right-nPix, rc.top, SRCCOPY); //Setup the per-pixel alpha blending values SetupAlphaChannel((DWORD*)pv, nPix, nheight, 0x00, 0xdf, 0); //Draw the text onto the display DC ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nLen, lpDx); //Blend the background back into the display BLENDFUNCTION blend = {AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA}; GdiAlphaBlend(dc, rc.right-nPix, rc.top, nPix, nheight, dcbitmap, 0, 0, nPix, nheight, blend); ::SelectObject(dcbitmap, tmpbmp); DeleteObject(bitmap); nRet = 1; } DeleteDC(dcbitmap); } return nRet; } //--------------------------------------------------------------------------- int DrawTextAlpha(HDC hdc, LPCTSTR lpsz, int nCount, RECT* prc, UINT uFormat) { BOOL bEffects = FALSE; SystemParametersInfo(SPI_GETUIEFFECTS, 0, (void*)&bEffects, 0); // don't alpha blend if ui effects off or number of colors <= 256 if (!bEffects || (GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES) <= 8)) { return DrawText(hdc, lpsz, nCount, prc, uFormat); } UINT nEllipsis = (DT_END_ELLIPSIS|DT_WORD_ELLIPSIS|DT_WORD_ELLIPSIS); if (!(uFormat & DT_SINGLELINE) || !(uFormat & DT_END_ELLIPSIS) || (uFormat & DT_CALCRECT)) return ::DrawText(hdc, lpsz, nCount, prc, uFormat); //we are single line and ellipses are requested //we are going to alpha blend though uFormat &= ~nEllipsis; //turn all ellipsis flags off if (nCount == -1) nCount = lstrlen(lpsz); RECT rc; CopyRect(&rc, prc); ::DrawText(hdc, (TCHAR*)lpsz, nCount, &rc, uFormat | DT_CALCRECT); if (rc.right <= prc->right) //not truncated return ::DrawText(hdc, lpsz, nCount, prc, uFormat); // DT_CENTER is effectively ignored when ellipses flags are on, // because text is clipped to fit in rectangle. With fading, we // need to justify the text. uFormat &= ~DT_CENTER; CopyRect(&rc, prc); int nwidth = RECTWIDTH(&rc); int nheight = RECTHEIGHT(&rc); if ((nwidth <= 0) || (nheight <= 0)) return 1; // Figure out how much of the background to stash away TEXTMETRIC tm; GetTextMetrics(hdc, &tm); int nPix = tm.tmAveCharWidth*5; //five characters worth if (nPix > nwidth/2) nPix = nwidth/2; //Adjust by one max char width because DrawText can draw up to //one extra character outside the clip rect. nPix += tm.tmMaxCharWidth; rc.right += tm.tmMaxCharWidth; //Create a 32bpp dibsection to store the background void* pv = NULL; HDC dcbitmap = CreateCompatibleDC(hdc); int nRet = 0; if (dcbitmap != NULL) { HBITMAP bitmap = CreateDibSection32Bit(nPix, nheight, &pv); if (bitmap != NULL) { HBITMAP tmpbmp = (HBITMAP) SelectObject(dcbitmap, bitmap); BitBlt(dcbitmap, 0, 0, nPix, nheight, hdc, rc.right-nPix, rc.top, SRCCOPY); //Setup the per-pixel alpha blending values SetupAlphaChannel((DWORD*)pv, nPix, nheight, 0x00, 0xdf, tm.tmMaxCharWidth); //Draw the text onto the display DC ::DrawText(hdc, lpsz, nCount, prc, uFormat); //Blend the background back into the display BLENDFUNCTION blend = {AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA}; GdiAlphaBlend(hdc, rc.right-nPix, rc.top, nPix, nheight, dcbitmap, 0, 0, nPix, nheight, blend); ::SelectObject(dcbitmap, tmpbmp); DeleteObject(bitmap); nRet = 1; } DeleteDC(dcbitmap); } return nRet; } //---------------------------------------------------------------------------