2016-04-04 3 views
1

Я хочу сделать нарисовать вектор CRect в контексте устройства. Критерии, которые перекрываются, должны складываться таким образом, чтобы пересечение всех объектов становилось ярче зеленого. Поэтому я придумал следующий код:Использование TransparentBlt для рисования в MFC

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. Что я делаю не так? Действительно ли это правильный подход?

ответ

0

В вашем примере вы должны заполнить память постоянного тока прозрачным цветом. Это приведет к инициализации цвета фона, так сказать. Затем нарисуйте память 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); 
} 
+0

Спасибо, Бармак! И спасибо Марчину! Сочетание обоих подходов помогло мне решить эту задачу. – Michen

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

Я немного адаптировал код, но с тем же результатом, что и выше: он остается черным. Вот что я написал: [...] \t dcMemory.CreateCompatibleDC (pDC); \t HBITMAP hbmp = CreateCompatibleBitmap ((HDC) dcMemory, frame.Width(), frame.Height()); \t dcMemory.SelectObject (hbmp); \t для (size_t i = 0; i AlphaBlend (taglist [i] .left, taglist [i] .top, taglist [i] .Width(), taglist [i] .Height(), & dcMemory, 0, 0, taglist [i] .Width(), taglist [i] .Height(), BlendFunction); – Michen

+0

@ Michen трудно прочитать код, который вы предоставили, из того, что я могу сказать, выглядит нормально. – marcinj

+0

Прошу прощения за это, Марцин. Это действительно странно, но я не могу его решить. Экран остается черным. Если я pDC-> FillRect (...) напрямую, он работает, но не имеет никакого отношения. С логической точки зрения, единственное, что должно пойти не так, это когда я dcMemory.FillRect (...) Есть ли способ проверить, что FillRect действительно преуспевает? – Michen

Смежные вопросы