MFC中使用TransparentBlt绘图

Using TransparentBlt for drawing in MFC

我想将 CRect 向量绘制到设备上下文中。重叠的 CRects 应该以一种方式加起来,所有的交叉点都变成更亮的绿色。因此我想出了以下代码:

void Grid::tag(CDC* pDC){

    CBrush brushGreen;
    brushGreen.CreateSolidBrush(RGB(0, 100, 0));
    CDC dcMemory;
    dcMemory.SelectObject(&brushGreen);
    dcMemory.CreateCompatibleDC(pDC);
    for (size_t i = 0; i < taglist.size(); i++){
        dcMemory.FillRect(taglist[i], &brushGreen);
        pDC->TransparentBlt(frame.left, frame.top, frame.Width(), frame.Height(), &dcMemory, taglist[i].left, taglist[i].top, taglist[i].Width(), taglist[i].Height(),RGB(0,100,0));
    }
    DeleteObject(brushGreen);

}

不幸的是,它变成了黑色。似乎没有任何东西被吸引到 pDC 中。我究竟做错了什么?这是一个有效的开始方法吗?

而不是 TransparentBlt - which does color keying during blt, you can use AlphaBlend,您的代码中还有其他问题。下面是一些修复程序,以及如何更正您的代码的想法(我还没有测试过它是否可以编译)。

CBrush brushGreen;
brushGreen.CreateSolidBrush(RGB(0, 100, 0));
CDC dcMemory;

//SO: what is the use of this? Also before creating DC
//dcMemory.SelectObject(&brushGreen);   
dcMemory.CreateCompatibleDC(pDC);

//SO: for memory DC you need also a bitmap to be selected (dont forget to release it):
HBITMAP hbmp = CreateCompatibleBitmap((HDC)dc, 500, 500);
auto oldDcMemoryBmp = dcMemory.SelectObject(hbmp);

for (size_t i = 0; i < taglist.size(); i++){
    dcMemory.FillRect(taglist[i], &brushGreen);

    // SO: this is not needed
    //pDC->TransparentBlt(frame.left, frame.top, frame.Width(), frame.Height(), &dcMemory, taglist[i].left, taglist[i].top, taglist[i].Width(), taglist[i].Height(),RGB(0,100,0));

    // SO: Instead use albhaBlt
    BLENDFUNCTION BlendFunction;
    BlendFunction.AlphaFormat = AC_SRC_ALPHA;
    BlendFunction.BlendFlags = 0;
    BlendFunction.BlendOp = AC_SRC_OVER;
    BlendFunction.SourceConstantAlpha = 15; // value 0 (transparent) to 255 (opaque)

    dc.AlphaBlend(taglist[i].left, taglist[i].top, taglist[i].Width(), taglist[i].Height(), &dcMemory, 0, 0, taglist[i].Width(), taglist[i].Height(), BlendFunction);
}
//DeleteObject(brushGreen);

在您的示例中,您必须用透明颜色填充内存 dc。这将初始化背景颜色,可以这么说。然后在内存 dc 上绘制并使用 TransparentBlt 和透明颜色。

void CMyWnd::OnPaint()
{
    CWnd::OnPaint();
    CClientDC dc(this);
    CRect rc;
    GetClientRect(&rc);

    //paint any custom background
    dc.FillSolidRect(&rc, RGB(200,200,255));

    //choose a color which you don't otherwise need, use it for transparency
    COLORREF transparent_color = RGB(1, 1, 1);

    //create memory dc and initialize with transparent_color:
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&dc, rc.right, rc.bottom);
    memdc.SelectObject(bitmap);
    memdc.FillSolidRect(&rc, transparent_color);

    //start custom drawing on memeory dc:
    CBrush brushGreen;
    brushGreen.CreateSolidBrush(RGB(0, 100, 0));
    CRect small_rc(10, 10, rc.right - 10, 20);
    memdc.FillRect(small_rc, &brushGreen);
    //end custom drawing

    //Finish by copying memeory dc to destination dc:
    dc.TransparentBlt(0, 0, rc.Width(), rc.Height(), 
        &memdc, 0, 0, rc.Width(), rc.Height(), transparent_color);
}