Gdiplus DrawString рисует прозрачный текст через удаленный рабочий стол

Я рисую текст в закадровом растровом изображении раздела DIB, который имеет глубину 32 бита и использует альфа-канал (ARGB). Я рисую пиксели прямо в память. Затем я создаю графический объект Gdiplus, передаю ему свой DC памяти и рисую текст, используя Graphics :: DrawString. Это нормально работает в нормальных условиях. Однако через удаленный рабочий стол отображаемый текст полностью прозрачен, т.е. вместо рисования любых цветных пикселей вы можете видеть, где находится текст. Кто-нибудь знает, почему это так и как это исправить ??

Вот моя рутина drawString:

void SplashScreen::drawString (MyString &ivText, Gdiplus::RectF &r,
Gdiplus::ARGB c, Gdiplus::StringAlignment align, Gdiplus::Font &fnt,
Gdiplus::Graphics &gfx)
{
Gdiplus::StringFormat fmt;
fmt.SetAlignment (align);
Gdiplus::SolidBrush brush (c);
wchar_t *wstr = new wchar_t [ivText.length()+1];
std::mbstowcs (wstr, ivText.cstr(), ivText.length()+1);
gfx.DrawString (wstr, ivText.length(), &fnt, r, &fmt, &brush);
delete wstr;
}

И вот как я создаю DIB:

BITMAPV5HEADER bhd;
memset (&bhd, 0, sizeof (bhd));
bhd.bV5Size = sizeof (BITMAPV5HEADER);
bhd.bV5Width = nWidth;
bhd.bV5Height = -nHeight;  // negative height indicates top-down DIB
bhd.bV5Planes = 1;
bhd.bV5BitCount = 32;
bhd.bV5Compression = BI_BITFIELDS;
bhd.bV5RedMask   = 0x00FF0000;
bhd.bV5GreenMask = 0x0000FF00;
bhd.bV5BlueMask  = 0x000000FF;
bhd.bV5AlphaMask = 0xFF000000;
m_pBuf = NULL;
m_hBmp = ::CreateDIBSection (m_hDC, (BITMAPINFO *) &bhd, DIB_RGB_COLORS,
(void **) &m_pBuf, NULL, 0);
if (m_hBmp == NULL || m_pBuf == NULL)
{
// error...
}
HGDIOBJ oldObj = ::SelectObject (m_hDC, m_hBmp);
if (oldObj == NULL)
{
// error...
}

После рисования текста в DIB я делаю

gfx.Flush (Gdiplus::FlushIntentionSync);

РЕДАКТИРОВАТЬ: Вам также может быть интересно, что окно, в которое DIB окончательно обращается, является окном WS_EX_LAYERED. Это заставка, которая показывает, когда приложение запускается, и постепенно исчезает, используя таймер и следующий метод:

void SplashScreen::setWindowTransparency (int nAlpha)
// @param nAlpha: 255 is opaque, 0 is fully transparent.
{
HWND hwnd = getHwnd();
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = nAlpha;
blend.AlphaFormat = AC_SRC_ALPHA;
BOOL bResult = ::UpdateLayeredWindow (hwnd, NULL, NULL, NULL, NULL,
NULL, RGB (0, 0, 0), &blend, ULW_ALPHA);
}

5

Решение

Я удивлен, что это когда-либо работает. Рисование с помощью gdi32 теряет альфа-информацию, и, насколько я понимаю, любой рисунок на 32-битном DIB с gdi32 оставляет альфа-информацию в DIB неопределенной. В этом случае GDI + должен пройти через gdi32, потому что вы дали ему HDC.

Для рисования в RGBA DIB с использованием GDI + необходимо создать объект GDI + Bitmap, поддерживаемый памятью вашего DIB, с правильным форматом пикселей (используя конструктор, который принимает указатель на данные пикселей, такой как этот), затем создать графический объект из вашего растрового изображения. Это позволяет GDI + рисовать непосредственно в памяти DIB и правильно обрабатывать альфа-канал, а не проходить через gdi32.

Конечно, если вам не нужна альфа-версия на пиксель, вы можете упростить ситуацию, используя AlphaFormat, равный 0, в функции смешивания, чтобы игнорировать альфа-канал в DIB.

3

Другие решения

У меня есть возможное решение для вас. Не уверен, к какой версии Windows вы подключаетесь, но на удаленном компьютере вам может потребоваться включить 32-битный цветовой режим для служб терминалов. В противном случае ваш клиент может быть ограничен 16-битным режимом.

На сервере, используя gpedit.msc, настройте параметр «Ограничить максимальную глубину цвета» до 32 бит. В Windows 2008/2012 это в административных шаблонах — Компоненты Windows — Службы удаленных рабочих столов — Среда удаленного сеанса.

Если вы подключаетесь к компьютеру с Windows XP / Vista / 7/8, я не уверен, доступен ли этот параметр gpedit.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector