Reputation: 61
I want do draw a vector of CRect into a device context. The CRects that overlap should add up in a way that the intersection of all turn to a brighter green. 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. What am I doing wrong? Is this a valid approach to begin with?
Upvotes: 1
Views: 4197
Reputation: 31599
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);
}
Upvotes: 1
Reputation: 49986
Instead of TransparentBlt - which does color keying during blt, you can use AlphaBlend, you have also other issues in your code. 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);
Upvotes: 1