Yanesdk 改造中(6)

DIB の生成について。


バイスコンテキストを関連付けることが出来る DIB を生成するためには、CreateDIBSection() を使います。


使用する API の宣言。

[StructLayout(LayoutKind.Explicit, Size = 4)]
public struct HBITMAP__
{
    [FieldOffset(0)]
    public int unused;
}

[StructLayout(LayoutKind.Explicit, Size = 4)]
public struct HDC__
{
    [FieldOffset(0)]
    public int unused;
}

[StructLayout(LayoutKind.Explicit, Size = 40)]
public struct BITMAPINFOHEADER
{
    [FieldOffset(0)]
    public uint biSize;

    [FieldOffset(4)]
    public int biWidth;

    [FieldOffset(8)]
    public int biHeight;

    [FieldOffset(12)]
    public ushort biPlanes;

    [FieldOffset(14)]
    public ushort biBitCount;

    [FieldOffset(16)]
    public uint biCompression;

    [FieldOffset(20)]
    public uint biSizeImage;

    [FieldOffset(24)]
    public int biXPelsPerMeter;

    [FieldOffset(28)]
    public int biYPelsPerMeter;

    [FieldOffset(32)]
    public uint biClrUsed;

    [FieldOffset(36)]
    public uint biClrImportant;
}

[StructLayout(LayoutKind.Explicit, Size = 4)]
public struct RGBQUAD
{
    [FieldOffset(0)]
    public byte rgbBlue;

    [FieldOffset(1)]
    public byte rgbGreen;

    [FieldOffset(2)]
    public byte rgbRed;

    [FieldOffset(3)]
    public byte rgbReserved;
}

[StructLayout(LayoutKind.Explicit, Size = 44)]
public struct BITMAPINFO
{
    [FieldOffset(0)]
    public BITMAPINFOHEADER bmiHeader;

    //Fixed-length Array "bmiColors[1]". Members can be
    //accessed with (&my_BITMAPINFO.bmiColors_1)[index]
    [FieldOffset(40)]
    public RGBQUAD bmiColors_1;
}

[DllImport(@"gdi32.dll", EntryPoint = "CreateCompatibleDC", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern unsafe HDC__* CreateCompatibleDC(HDC__* __formal);

[DllImport(@"gdi32.dll", EntryPoint = "CreateDIBSection", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern unsafe HBITMAP__* CreateDIBSection(HDC__* __formal, BITMAPINFO* __formal1, uint __formal2, void** __formal3, void* __formal4, uint __formal5);

[DllImport(@"gdi32.dll", EntryPoint = "DeleteDC", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern unsafe int DeleteDC(HDC__* __formal);

[DllImport(@"gdi32.dll", EntryPoint = "SelectObject", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern unsafe void* SelectObject(HDC__* __formal, void* __formal1);

[DllImport(@"gdi32.dll", EntryPoint = "DeleteObject", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern unsafe int DeleteObject(void* __formal);

public const uint DIB_RGB_COLORS = 0; /* color table in RGBs */
public const uint DIB_PAL_COLORS = 1; /* color table in palette indices */
public const uint BI_RGB = 0;
public const uint BI_RLE8 = 1;
public const uint BI_RLE4 = 2;
public const uint BI_BITFIELDS = 3;

これは、id:melpon:20060625 からコピペしてきました。通りすがりさんにはほんと感謝。


で、実際の生成。

// デバイスコンテキストを取得
unsafe
{
    // null でいいよね?
    this.hDC = (IntPtr)CreateCompatibleDC(null);
}
if (this.hDC == IntPtr.Zero)
{
    return YanesdkResult.Win32apiError;
}

// DIB を生成
unsafe
{
    BITMAPINFO info = new BITMAPINFO();
    info.bmiHeader.biSize = (uint)sizeof(BITMAPINFOHEADER);
    info.bmiHeader.biWidth = width;
    info.bmiHeader.biHeight = height;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 32;
    info.bmiHeader.biCompression = BI_RGB;
    info.bmiHeader.biSizeImage = 0;
    info.bmiHeader.biXPelsPerMeter = 0;
    info.bmiHeader.biYPelsPerMeter = 0;
    info.bmiHeader.biClrUsed = 0;
    info.bmiHeader.biClrImportant = 0;

    fixed (IntPtr* p = &this.pixels)
    {
        this.hBitmap = (IntPtr)CreateDIBSection((HDC__*)hDC, &info, DIB_RGB_COLORS, (void**)p, (void*)null, 0);
    }
}
if (this.hBitmap == IntPtr.Zero)
{
    return YanesdkResult.Win32apiError;
}

これだけです。
後は、SelectObject でデバイスコンテキストに hBitmap を関連付けておけば、レンダリングコンテキストでの描画がこの DIB に反映されるようになります。

unsafe
{
    this.hOldBitmap = (IntPtr)SelectObject((HDC__*)this.hDC, (void*)this.hBitmap);
}