Красивый вариант - уходить в полупрозрачность:
Реализовать можно довольно просто:
- перед отрисовкой текста запоминаем тот фрагмент фона, на котором текст будет уходить в полупрозрачность
- после отрисовки текста выводим этот фрагмент с учетом полупрозрачности.
Для удобства использования этих двух процессов (который "перед" и который "после") вынесем первый в конструктор класса Fader, второй в деструктор. Использование будет такое:
{
Fader fader(dc, rect); // выполняется то, что "перед"
SomeDrawing(dc, rect); // непосредственно отрисовка текста
// выполняется то, что "после" - в деструкторе ~Fader()
}
Сама реализация предельно проста:
class Fader
{
public:
Fader::Fader(CDCHandle DC, const CRect& ClientRect) : DC_(DC), FaderRect_(ClientRect)
{
// опеределяем область, в которой будем уходить в полупрозрачность
const int FaderWidth = 32;
FaderRect_.left = max(FaderRect_.right - FaderWidth, 0);
// создаем bitmap
BYTE *Bits = static_cast(CreateBGRABitmap(Bitmap_, DC, FaderRect_.Size()));
if (!Bits)
return;
// копируем фон в bitmap
BitmapDC_.CreateCompatibleDC(DC);
BitmapDC_.SelectBitmap(Bitmap_);
BitBlt(BitmapDC_, 0, 0, FaderRect_.Width(), FaderRect_.Height(), DC, FaderRect_.left, FaderRect_.top, SRCCOPY);
// уводим в полупрозрачность
GdiFlush();
for (int Line = FaderRect_.Height(); Line; --Line)
for (int Pos = 0; Pos < FaderRect_.Width(); ++Pos, Bits += 4)
{
BYTE Alpha = Pos << 3; // как удачно, что FaderWidth является степенью двойки ;)
ApplyAlpha(Bits[0], Alpha);
ApplyAlpha(Bits[1], Alpha);
ApplyAlpha(Bits[2], Alpha);
Bits[3] = Alpha;
}
}
Fader::~Fader()
{
// накладываем полупрозрачный bitmap с фоном
if (BitmapDC_)
AlphaBlend(DC_, FaderRect_, BitmapDC_, CRect(CPoint(0, 0), FaderRect_.Size()));
}
private:
HDC DC_;
CRect FaderRect_;
CBitmap Bitmap_;
CDC BitmapDC_;
};
PS. Парочка helper-ов, которые используются выше:
void *CreateBGRABitmap(CBitmap& Bitmap, HDC DC, CSize Size, bool UpsideDown)
{
BITMAPV5HEADER bi;
memset(&bi, 0, sizeof(bi));
bi.bV5Size = sizeof (BITMAPV5HEADER);
bi.bV5Width = Size.cx;
bi.bV5Height = UpsideDown ? Size.cy : -Size.cy;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_BITFIELDS;
bi.bV5RedMask = 0x00FF0000;
bi.bV5GreenMask = 0x0000FF00;
bi.bV5BlueMask = 0x000000FF;
bi.bV5AlphaMask = 0xFF000000;
void *Bits = NULL;
Bitmap.CreateDIBSection(DC, (BITMAPINFO*)&bi, DIB_RGB_COLORS, &Bits, NULL, 0);
return Bits;
}
void ApplyAlpha(BYTE& Value, BYTE Alpha)
{
Value = ((unsigned)Value * Alpha) >> 8;
}