【问题标题】:Copying transparent (32bit alpha) bitmap from TImageList in ComboBox DrawItem event在 ComboBox DrawItem 事件中从 TImageList 复制透明(32 位 alpha)位图
【发布时间】:2015-02-07 23:18:50
【问题描述】:

我正在自定义 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 位 alpha 透明度/半透明度。目前我在生成的TBitmap 中以白色背景将其取出。

需要明确的是,TImageList ColorDepth 在加载图像之前设置为cd32bitDrawingStyle = 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);
        }
}

【问题讨论】:

  • 为什么不让图片列表绘制呢?你可以使用它的 draw 方法。否则请参阅stackoverflow.com/questions/13352497/…
  • @SertacAkyuz 谢谢,效果很好......如果你把它变成一种答案,我会很高兴接受它。否则我会等一会儿,自己做答案。
  • 完成。但是您认为更冗长的答案请发布,我将删除我的。不客气。
  • @SertacAkyuz 这个建议足以让我解决问题,我已经用解决方案更新了我自己的问题,因此它可能会在未来帮助其他人。再次感谢。

标签: delphi c++builder alpha-transparency c++builder-2010


【解决方案1】:

您无需尝试从图像列表中获取原始位图,因为图像列表本身知道如何绘制尊重透明度信息。你可以使用它的Draw 方法。

否则,here 的回答建议在调用 GetBitmap 之前将 AlphaFormat 设置为“afIgnored”应该保持透明度。

【讨论】:

    猜你喜欢
    • 2019-03-18
    • 2010-09-23
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多