Как нарисовать текст с помощью CDC с прозрачным фоном на CBitmap? - PullRequest
2 голосов
/ 05 октября 2011

У меня есть следующий код, который работает, если вы замаскируете розовые пиксели, однако, на самом деле мне нужны прозрачные биты, такие как файл PNG, чтобы я мог избежать проблем альфа-смешения и необходимости маскировать определенный цвет везде растровым изображением будет использоваться.

CClientDC dc(pWnd);
CDC memDC;

if(!memDC.CreateCompatibleDC(&dc))
   return NULL;

CRect bitmapRect;
bitmapRect.SetRectEmpty();

CFont* pOldFont = memDC.SelectObject(pWnd->GetFont());
CSize fontSize = memDC.GetTextExtent(imageText);

bitmapRect.right = fontSize.cx;
bitmapRect.bottom = fontSize.cy;

CBitmap bitmap;
if(!bitmap.CreateCompatibleBitmap(&dc, bitmapRect.Width(), bitmapRect.Height()))
   return NULL;

CBitmap* pOldMemDCBitmap = memDC.SelectObject(&bitmap);

memDC.FillSolidRect(&bitmapRect, RGB(255,0,255));
//memDC.SetBkMode(TRANSPARENT); // doesn't work
//memDC.SetBkColor(TRANSPARENT); // doesn't work
memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));

//memDC.DrawText(imageText, bitmapRect, DT_TOP|DT_LEFT|DT_NOCLIP); // same difference
memDC.TextOut(0, 0, imageText);

memDC.SelectObject(pOldMemDCBitmap);
memDC.SelectObject(pOldFont);
memDC.DeleteDC();

CImageList bmImage;
bmImage.Create(bitmapRect.Width(), bitmapRect.Height(), ILC_COLOR32|ILC_MASK, 0, 1);
// this masks out the pink but for some windows blends edges of text causing pink text instead of black!
bmImage.Add(&bitmap, RGB(255,0,255));

Это просто зверь, заполненный ошибками, который плохо себя ведет в MFC, или я что-то упустил?

Ответы [ 2 ]

2 голосов
/ 03 апреля 2014

Простой DrawText () с прозрачным фоном без MFC:

// in my case a user drawn button:
_windowHandle = CreateWindowEx(...);
SendMessage(_windowHandle, WM_SETFONT, (WPARAM)font, (LPARAM)NULL);

...

// WM_DRAWITEM
SetTextColor(hDC, RGB(216, 27, 27));
SetBkMode(hDC, TRANSPARENT);
RECT rect = { 0, 0, backgroundBitmap.bmWidth, backgroundBitmap.bmHeight };
DrawText(hDC, _text.c_str(), -1, &rect, DT_CENTER | DT_WORDBREAK);

- hfrmobile

1 голос
/ 05 октября 2011

Примерно через 10 минут после того, как я спросил об этом, я прочитал свой собственный комментарий и понял, что «некоторые окна» означают, что он связан с передаваемыми окнами. В частности, шрифт, используемый из указанного окна.Шрифты со свойствами по умолчанию демонстрировали странное смешивание.

В конце дня я решил, что мне нужно изменить шрифт, чтобы отключить все, что портит мой чертежный код.В конце концов я сузил его до одного виновника, вызвавшего проблему:

CClientDC dc(pWnd);
CDC memDC;

if(!memDC.CreateCompatibleDC(&dc))
   return NULL;

LOGFONT tempFont;
CFont* winFont = pWnd->GetFont();
if (winFont)
   winFont->GetLogFont(&tempFont);
else
{
   // generate a likely font
   SecureZeroMemory(&tempFont, sizeof(LOGFONT));
   //TEXTMETRIC txt;
   //GetTextMetrics(memDC, &txt);
   //tempFont.lfHeight = txt.tmHeight * -1; // 16 is too big looking
   tempFont.lfHeight = -12;
   tempFont.lfWeight = FW_NORMAL;
   tempFont.lfCharSet = DEFAULT_CHARSET;
   wcscpy_s(tempFont.lfFaceName, L"Segoe UI"); // Win7 control default
}

tempFont.lfQuality = NONANTIALIASED_QUALITY; // this is the fix!!!

CFont newFont;
newFont.CreateFontIndirect(&tempFont);

CFont* pOldFont = memDC.SelectObject(&newFont);
// ... other stuff same as before ...

Так что я все еще FillSolidRect розового цвета, затем рисую свои значки, текст, все, что я хочу, и т. Д. Затем замаскирую розовые пиксели.С регулировкой качества шрифта он больше не смешивается с текстом шрифта и выглядит хорошо.В другом случае, приведенном выше, создается шрифт по умолчанию, который будет использоваться в случае, если переданный CWnd* не имеет правильного указанного.

...