Копирование прозрачного (32-битного альфа) растрового изображения из TImageList в событии ComboBox DrawItem

Я настраиваю событие OnDrawItem для рисования значков рядом с именами элементов. Вот мой код для события OnDrawItem:

void __fastcall Form1::ComboBox1DrawItem(TWinControl *Control, int Index,
                                         TRect &Rect, TOwnerDrawState State)
{
TComboBox* CB = static_cast<TComboBox*>(Control);
CB->Canvas->FillRect(Rect);

boost::scoped_ptr<Graphics::TBitmap> bitmap(new Graphics::TBitmap());
bitmap->PixelFormat = pf32bit;
bitmap->AlphaFormat = afPremultiplied;

ImageList1->GetBitmap(Index, bitmap.get());

bitmap->AlphaFormat = afPremultiplied;

if (bitmap->Canvas->Handle)
    {
    // structure for alpha blending
    BLENDFUNCTION bf;
    bf.BlendOp              = AC_SRC_OVER;
    bf.BlendFlags           = 0;
    bf.SourceConstantAlpha  = 0xFF;         // 0x00 (transparent) through 0xFF (opaque)
    bf.AlphaFormat          = AC_SRC_ALPHA; // Use bitmap alpha

    ::AlphaBlend(CB->Canvas->Handle,    // handle to destination DC
             Rect.Left + 2,             // x-coord of upper-left corner
             Rect.Top,                  // y-coord of upper-left corner
             bitmap->Width,             // destination width
             bitmap->Height,            // destination height
             bitmap->Canvas->Handle,    // handle to source DC
             0,                         // x-coord of upper-left corner
             0,                         // y-coord of upper-left corner
             bitmap->Width,             // source width
             bitmap->Height,            // source height
             bf                         // alpha-blending function
            );
    }

    Rect = Bounds(Rect.Left + 20 + 2, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top);

    DrawTextW(CB->Canvas->Handle, CB->Items->Strings[Index].c_str(), -1, &Rect, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}

Проблема, конечно, заключается в том, чтобы получить прозрачный TImageList1 для копирования в прозрачный TBitmap с сохранением 32-битной альфа-прозрачности/полупрозрачности. В настоящее время я получаю его с белым фоном в результате TBitmap.

Просто чтобы было ясно, TImageList ColorDepth устанавливается в cd32bit с DrawingStyle = dsTransparent перед загрузкой изображений в него, и изображения на нем прозрачны, никаких проблем.

В чем хитрость, чтобы решить эту проблему?

ОБНОВЛЕНИЕ И МОЕ ОКОНЧАТЕЛЬНОЕ РЕШЕНИЕ

Основываясь на ответе здесь, вот мой окончательный рабочий код для кого-то, кому он может понадобиться в будущем. Это, конечно, всего лишь код шаблона, который вы, возможно, захотите настроить под свои нужды.

void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index, TRect &Rect, TOwnerDrawState State)
{
if (Index >= 0)
        {
        TComboBox* CB     = static_cast<TComboBox*>(Control);
        CB->Canvas->FillRect(Rect);
        // Note - ImageList1 already has DrawingStyle set to dsTransparent          
        ImageList1->Draw(CB->Canvas, Rect.Left + 2, Rect.Top, 0);
        Rect = Bounds(Rect.Left + ImageList1->Width + 2 + 2, Rect.Top, Rect.Right - Rect.Left - ImageList1->Width - 2, Rect.Bottom - Rect.Top);
        DrawTextW(CB->Canvas->Handle, CB->Items->Strings[Index].c_str(), -1, &Rect, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
        }
}

person Coder12345    schedule 07.02.2015    source источник


Ответы (1)


Вам не нужно пытаться получить исходное растровое изображение из списка изображений, потому что сам список изображений знает, как рисовать с соблюдением информации о прозрачности. Для этого вы можете использовать его метод Draw.

В противном случае ответ здесь предполагает, что установка AlphaFormat на "afIgnored" перед вызовом GetBitmap должна сохранить прозрачность.

person Sertac Akyuz    schedule 08.02.2015