简体   繁体   English

在 MFC 中使用 TransparentBlt 进行绘图

[英]Using TransparentBlt for drawing in MFC

I want do draw a vector of CRect into a device context.我想将 CRect 的向量绘制到设备上下文中。 The CRects that overlap should add up in a way that the intersection of all turn to a brighter green.重叠的 CRect 相加应该使所有的交集变成更亮的绿色。 Therefore I came up with the following code:因此,我想出了以下代码:

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

}

Unfortunately, it turns out black.不幸的是,结果是黑色的。 It seems like nothing is drawn into pDC.似乎没有任何东西被吸引到 pDC 中。 What am I doing wrong?我究竟做错了什么? Is this a valid approach to begin with?这是一种有效的方法吗?

Instead of TransparentBlt - which does color keying during blt, you can use AlphaBlend , you have also other issues in your code.您可以使用AlphaBlend代替TransparentBlt - 在 blt 期间进行颜色键控,您的代码中还有其他问题。 Below are some fixes, and ideas how to correct your code (I have not tested if this compiles).下面是一些修复程序,以及如何更正代码的想法(我还没有测试过它是否可以编译)。

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

In your example you have to fill memory dc with a transparent color.在您的示例中,您必须用透明颜色填充内存 dc。 This will initialize the background color, so to speak.这将初始化背景颜色,可以这么说。 Then draw on memory dc and use TransparentBlt with that transparent color.然后在内存 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM