Моя цель состоит в том, чтобы динамически поместить некоторый произвольный текст в HICON изображение Я использую следующий код (во время выполнения.):Как нарисовать текст с прозрачностью с помощью GDI?
//Error checks are omitted for brevity
//First create font
LOGFONT lf = {0};
lf.lfHeight = -58;
lf.lfWeight = FW_NORMAL;
lf.lfOutPrecision = OUT_TT_PRECIS; //Use TrueType fonts for anti-alliasing
lf.lfQuality = CLEARTYPE_QUALITY;
lstrcpy(lf.lfFaceName, L"Segoe UI");
HFONT hFont = ::CreateFontIndirect(&lf);
//HICON hIcon = original icon to use as a source
//I'm using a large 256x256 pixel icon
hIcon = (HICON)::LoadImage(theApp.m_hInstance, MAKEINTRESOURCE(IDI_ICON_GREEN_DIAMOND), IMAGE_ICON, 256, 256, LR_DEFAULTCOLOR);
ICONINFO ii = {0};
::GetIconInfo(hIcon, &ii);
BITMAP bm = {0};
::GetObject(ii.hbmColor, sizeof(bm), &bm);
SIZE szBmp = {bm.bmWidth, bm.bmHeight};
HDC hDc = ::GetDC(hWnd);
HDC hMemDC = ::CreateCompatibleDC(hDc);
HGDIOBJ hOldBmp = ::SelectObject(hMemDC, ii.hbmColor);
HGDIOBJ hOldFont = ::SelectObject(hMemDC, hFont);
::SetBkMode(hMemDC, TRANSPARENT);
::SetTextColor(hMemDC, RGB(255, 0, 0)); //Red text
//Draw text
//NOTE that DrawText API behaves in a similar way
::TextOut(hMemDC, 0, 0, L"Hello", 5);
::SelectObject(hMemDC, hOldFont);
::SelectObject(hMemDC, hOldBmp);
//We need a simple mask bitmap for the icon
HBITMAP hBmpMsk = ::CreateBitmap(szBmp.cx, szBmp.cy, 1, 1, NULL);
ICONINFO ii2 = {0};
ii2.fIcon = TRUE;
ii2.hbmColor = ii.hbmColor;
ii2.hbmMask = hBmpMsk;
//Create updated icon
HICON hIcon2 = ::CreateIconIndirect(&ii2);
//Cleanup
::DeleteObject(hBmpMsk);
::DeleteDC(hMemDC);
::ReleaseDC(hWnd, hDc);
::DeleteObject(ii.hbmColor);
::DeleteObject(ii.hbmMask);
::DeleteObject(hFont);
, а затем я могу отобразить значок в моем окне из OnPaint()
обработчика (так что я могу видеть, как это получается), как например:
::DrawIconEx(dc.GetSafeHdc(), 0, 0,
hIcon2,
256, 256, NULL,
::GetSysColorBrush(COLOR_BTNFACE),
DI_NORMAL);
так вот что я получаю:
Чтобы посмотреть, что происходит в пикселях в моем hIcon2
Я позвонил GetDIBits
на свой ii.hbmColor
по вышеуказанному коду. Полученный массив пикселей, где предполагается мое слово «Hello» должен был быть показан выглядел следующим образом:
Пиксели кодируются как BGRA
в этом дампа памяти, поэтому четвёртую байт в каждом DWORD выступает за прозрачность: 0 = прозрачный, FF = непрозрачный. Но в этом случае TextOut
не заполняет прозрачность или оставляет его как 0, что интерпретируется как «полностью прозрачное». Вместо этого он, кажется, предварительно размножает его в цветах RGB
.
Обратите внимание, что если я продолжаю смотреть дальше по той же битовой карты, где начинается зеленый алмаз, изображение пикселей, кажется, прозрачность байты установлены правильно:
Любая идея, как сделать текст таким образом, чтобы API может установить эти байты прозрачности?
EDIT: Как было предложено ниже я попытался следующий GDI + метод:
HGDIOBJ hOldBmp = ::SelectObject(hMemDC, ii.hbmColor);
Graphics grpx(hMemDC);
RectF rcfTxt(0.0f, 0.0f, (REAL)szBmp.cx, (REAL)szBmp.cy);
Font gdiFont(L"Segoe UI", 58.0f, FontStyleRegular, UnitPixel);
SolidBrush gdiBrush(Color(255, 0, 0));
StringFormat gdiSF;
gdiSF.SetAlignment(StringAlignmentNear);
gdiSF.SetFormatFlags(StringFormatFlagsNoWrap);
gdiSF.SetHotkeyPrefix(HotkeyPrefixNone);
//The reason I was using GDI was because I was setting
//spacing between letters using SetTextCharacterExtra()
//Unfortunately with GDI+ this does not work!
HDC hTmpDC = grpx.GetHDC();
::SetTextCharacterExtra(hTmpDC, -4); //This doesn't do anything!
grpx.ReleaseHDC(hTmpDC);
grpx.DrawString(L"Hello", 5, &gdiFont, rcfTxt, &gdiSF, &gdiBrush);
::SelectObject(hMemDC, hOldBmp);
и к тому же не в состоянии установить характер интервала между (который я мог бы с GDI, используя SetTextCharacterExtra
) вот что я получил (немного увеличенный для наглядности):
Так ясно все еще проблема с прозрачностью.
GDI не понимает альфа; Вместо этого рассмотрите gdiplus. –
@JonathanPotter: Спасибо. Да, похоже, что GDI + - единственный способ сделать это с поддержкой альфа-канала. Хотя причина, по которой я пошел с простым GDI, заключается в том, что он предоставил ['SetTextCharacterExtra'] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd145092 (v = vs.85) .aspx) функция для изменения интервала между символами. Вы знаете, могу ли я использовать его с GDI +? – c00000fd