使用TransparentBlt在MFC中绘图

Using TransparentBlt for drawing in MFC

本文关键字:绘图 MFC TransparentBlt 使用      更新时间:2023-10-16

我想在设备上下文中绘制一个CRect向量。重叠的CR应该以这样一种方式相加,即所有的交点都变成更亮的绿色。因此,我想出了以下代码:

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。我做错了什么?这是一个有效的方法吗?

在您的示例中,您必须用透明颜色填充内存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);
}

您可以使用AlphaBlend来代替在blt期间执行颜色键控的TransparentBlt,但您的代码中也存在其他问题。以下是一些修复程序,以及如何更正代码的想法(我还没有测试是否编译)。

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);