contents

  1. サンプル
  2. GetDC()について補足

GDI+ with Direct3D9

DirectX9 になって、IDirect3DSurface9::GetDC() が追加されました。 しかし、GDI ではαチャネルを扱うことができないことが問題です。 どうせデバイスコンテキストを取得できるのは、 マネージドまたはシステムメモリ上のサーフェイスのみなのですから、 LockRect() して GDI+ を利用したほうが便利です。

サンプル

実際のコードで示すとこんな感じ。 DirectX8以前でも問題なくつかえますね。 ただし、GDI+1.0は16bitカラーに対応していないようなので、そこだけ注意が必要です。

// フォーマットマッピング
Gdiplus::PixelFormat D3D_to_GDI(D3DFORMAT format)
{
  switch(format)
  {
  case D3DFMT_P8          : return PixelFormat8bppIndexed;
  case D3DFMT_L16         : return PixelFormat16bppGrayScale;
  case D3DFMT_R5G6B5      : return PixelFormat16bppRGB565;
  case D3DFMT_X1R5G5B5    : return PixelFormat16bppRGB555;
  case D3DFMT_A1R5G5B5    : return PixelFormat16bppARGB1555;
  case D3DFMT_R8G8B8      : return PixelFormat24bppRGB;
  case D3DFMT_X8R8G8B8    : return PixelFormat32bppRGB;
  case D3DFMT_A8R8G8B8    : return PixelFormat32bppARGB;
  case D3DFMT_A16B16G16R16: return PixelFormat64bppARGB;
  default                 : return PixelFormatUndefined;
  }
}

IDirect3DTexture9* pTexture; // 対象テクスチャ

DWORD level = 0;
D3DSURFACE_DESC desc;
m_pTexture->GetLevelDesc(level, &desc);
D3DLOCKED_RECT bits;
m_pTexture->LockRect(level, &bits, NULL, 0);
{  // ~Bitmap() → UnlockRect() の順が望ましいため、スコープを切る
  Bitmap bitmap(desc.Width, desc.Height, bits.Pitch, D3D_to_GDI(desc.Format), (BYTE*)bits.pBits);
  Graphics graphics(bitmap);
  // graphics を使う……
  graphics.Flush(); // 念のため
}
m_pTexture->UnlockRect(level);

GetDC()について補足

GetDC() ⇒ Graphics(HDC hDC) は使えないかということなのですが、 αが使えないGDIの問題点を引きずってしまうため、ほとんどメリットはありません。 一応試したところ、XP組み込みのGDI+では、IDirect3DSurface9::GetDC()で取得したHDCからGdiplus::Graphicsを作成することはでき ますが、そのときDirect3D7が初期化されています。 もしかしたら、内部的にはirect3D7が使用されているのかもしれません。 しかも、D3D7/D3D9ともに終了時にメモリリークが報告されます。 この方法は使わないほうが良さそうです。