229 lines
8.1 KiB
C++
229 lines
8.1 KiB
C++
//---------------------------------------------------------------------------
|
|
// 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<h;j++)
|
|
{
|
|
for (i=0;i<w;i++)
|
|
{
|
|
BYTE a = bstart - bdiff * i/w; //alpha
|
|
BYTE r = (GetRValue(*pdw)*a)/256;
|
|
BYTE g = (GetGValue(*pdw)*a)/256;
|
|
BYTE b = (GetBValue(*pdw)*a)/256;
|
|
*pdw = (a<<24)|RGB(r,g,b);
|
|
pdw++;
|
|
}
|
|
for (i=w;i<w+nExtra;i++)
|
|
{
|
|
BYTE a = bend; //alpha
|
|
BYTE r = (GetRValue(*pdw)*a)/256;
|
|
BYTE g = (GetGValue(*pdw)*a)/256;
|
|
BYTE b = (GetBValue(*pdw)*a)/256;
|
|
*pdw = (a<<24)|RGB(r,g,b);
|
|
pdw++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BYTE bdiff = bend - bstart;
|
|
for (j=0;j<h;j++)
|
|
{
|
|
for (i=0;i<w;i++)
|
|
{
|
|
BYTE a = bstart + bdiff * i/w; //alpha
|
|
BYTE r = (GetRValue(*pdw)*a)/256;
|
|
BYTE g = (GetGValue(*pdw)*a)/256;
|
|
BYTE b = (GetBValue(*pdw)*a)/256;
|
|
*pdw = (a<<24)|RGB(r,g,b);
|
|
pdw++;
|
|
}
|
|
for (i=w;i<w+nExtra;i++)
|
|
{
|
|
BYTE a = bend; //alpha
|
|
BYTE r = (GetRValue(*pdw)*a)/256;
|
|
BYTE g = (GetGValue(*pdw)*a)/256;
|
|
BYTE b = (GetBValue(*pdw)*a)/256;
|
|
*pdw = (a<<24)|RGB(r,g,b);
|
|
pdw++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int ExtTextOutAlpha(HDC dc, int X, int Y, UINT fuOptions, CONST RECT *lprc,
|
|
LPCTSTR lpsz, UINT nCount, CONST INT *lpDx)
|
|
{
|
|
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(dc, BITSPIXEL) * GetDeviceCaps(dc, PLANES) <= 8))
|
|
{
|
|
return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx);
|
|
}
|
|
|
|
if (lprc == NULL)
|
|
return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx);
|
|
|
|
RECT rc = *lprc;
|
|
int nwidth = rc.right -rc.left;
|
|
int nheight = rc.bottom - rc.top;
|
|
int nLen = (nCount == -1) ? lstrlen(lpsz) : nCount;
|
|
int nFit=0;
|
|
int* pFit = new int[nLen];
|
|
if (pFit == NULL)
|
|
return 0;
|
|
pFit[0] = 0;
|
|
SIZE size;
|
|
GetTextExtentExPoint(dc, lpsz, nLen, nwidth, &nFit, pFit, &size);
|
|
if (nFit >= 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;
|
|
}
|
|
//---------------------------------------------------------------------------
|