5

我正在将文本绘制到 DIB 部分的屏幕外位图中,该位图是 32 位深并使用 alpha 通道 (ARGB)。我将像素直接绘制到内存中。然后,我创建一个 Gdiplus Graphics 对象,将我的内存 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);
  }
4

2 回答 2

4

我很惊讶这曾经有效。使用 gdi32 绘图会丢失 alpha 信息,据我了解,任何使用 gdi32 在 32 位 DIB 上绘图都会使 DIB 中的 alpha 信息未定义。在这种情况下,GDI+ 必须通过 gdi32,因为您给了它一个 HDC。

要使用 GDI+ 绘制到 RGBA DIB,您需要创建一个由 DIB 内存支持的具有正确像素格式的 GDI+ Bitmap 对象(使用采用像素数据指针的构造函数,例如this one),然后从你的位图。这允许 GDI+ 直接绘制到 DIB 的内存并正确处理 alpha 通道,而不是通过 gdi32。

当然,如果您不需要每像素 alpha,您可以通过在混合函数中使用 0 的 AlphaFormat 来简化事情,以忽略 DIB 中的 alpha 通道。

于 2012-11-15T20:39:28.420 回答
0

我有一个可能的解决方案给你。不确定您要连接到哪个版本的 Windows,但在远程计算机上,您可能必须为终端服务启用 32 位颜色模式。否则您的客户端可能会被限制为 16 位模式。

在服务器上,使用 gpedit.msc,将“限制最大颜色深度”选项配置为 32 位。在 Windows 2008/2012 中,这是在管理模板 - Windows 组件 - 远程桌面服务 - 远程会话环境中。

如果您连接到 Windows XP/Vista/7/8 计算机,我不确定此 gpedit 设置是否可用。

于 2013-02-26T23:20:02.440 回答