2015-02-07 29 views
2

我正在自定义OnDrawItem事件以在项目名称旁边绘制图标。 这里是迄今为事件的OnDrawItem我的代码:在ComboBox DrawItem事件中复制TImageList中的透明(32位阿尔法)位图

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中将它与白色背景相结合。

只是要清楚,TImageListColorDepth是在其加载图像,它和之前的图像设置为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); 
     } 
} 
+4

为什么不让图像列表绘制?你可以使用它的绘制方法。否则,请参阅http://stackoverflow.com/questions/13352497/delphi-get-bitmap-from-a-timagelist。 – 2015-02-08 01:57:43

+0

@SertacAkyuz谢谢你,这很有效......如果你把它变成一种答案,我会非常乐意接受它。否则,我会等待一段时间,自己做出答案。 – Coder12345 2015-02-08 15:13:07

+0

完成。但是,你的想法是一个更详细的答案,请张贴,我会删除我的。别客气。 – 2015-02-08 16:02:54

回答

2

你并不需要去尝试,并从图像列表抢原始位图,因为图像列表本身知道如何绘制履行透明度信息。你可以使用它的Draw方法。

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