使用TransparentBlt在MFC中绘图

时间:2016-04-04 07:31:59

标签: c++ mfc drawing

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

2 个答案:

答案 0 :(得分:1)

而不是TransparentBlt - 在blt期间进行颜色键控,您可以使用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);

答案 1 :(得分:0)

In your example you have to fill memory dc with a transparent color. This will initialize the background color, so to speak. Then draw on memory dc and use TransparentBlt with that transparent color.

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