IGraphics(2)

W21S で IGraphics が動作しない理由を調べてみたところ、どうやら自分でアロケートしたメモリに対して IGraphics を使用しようとするとアウトらしい。
つまり、

IBitmap* pDeviceBitmap = NULL;

ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_GRAPHICS, (void**)&pMe->_pGraphics);
IDISPLAY_GetDeviceBitmap(pMe->a.m_pIDisplay, &pDeviceBitmap);

IBITMAP_CreateCompatibleBitmap(pDeviceBitmap, &pMe->_pBitmap, 240, 240);

IGRAPHICS_SetDestination(pMe->_pGraphics, pMe->_pBitmap);
IGRAPHICS_EnableDoubleBuffer(pMe->_pGraphics, FALSE);
IGRAPHICS_SetFillMode(pMe->_pGraphics, TRUE);
IGRAPHICS_SetFillColor(pMe->_pGraphics, 255, 255, 0, 0);
IGRAPHICS_SetColor(pMe->_pGraphics, 255, 255, 0, 0);
{
    AEERect r = { 0, 0, 240, 240 };
    IGRAPHICS_DrawRect(pMe->_pGraphics, &r );
}
IBITMAP_BltIn(pDeviceBitmap, 0, 0, 240, 240, pMe->_pBitmap, 0, 0, AEE_RO_COPY);

IDISPLAY_Update(pMe->a.m_pIDisplay);

こうやって、IBITMAP_CreateCompatibleBitmap() で幅と高さをちゃんと指定してやれば IGraphics は使えるが、

IBitmap* pDeviceBitmap = NULL;

ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_GRAPHICS, (void**)&pMe->_pGraphics);
IDISPLAY_GetDeviceBitmap(pMe->a.m_pIDisplay, &pDeviceBitmap);

IBITMAP_CreateCompatibleBitmap(pDeviceBitmap, &pMe->_pBitmap, 240, 0);
{
    void* buf = NULL;
    IBITMAP_QueryInterface(pMe->_pBitmap, AEECLSID_DIB, (void*)&pMe->_pDIB);
    buf = MALLOC(pMe->_pDIB->nPitch * 240 | ALLOC_NO_ZMEM);
    pMe->_pDIB->pBmp = (byte*)buf;
    pMe->_pDIB->cy = 240;
}

IGRAPHICS_SetDestination(pMe->_pGraphics, pMe->_pBitmap);
IGRAPHICS_EnableDoubleBuffer(pMe->_pGraphics, FALSE);
IGRAPHICS_SetFillMode(pMe->_pGraphics, TRUE);
IGRAPHICS_SetFillColor(pMe->_pGraphics, 255, 255, 0, 0);
IGRAPHICS_SetColor(pMe->_pGraphics, 255, 255, 0, 0);
{
    AEERect r = { 0, 0, 240, 240 };
    IGRAPHICS_DrawRect(pMe->_pGraphics, &r);
}

IBITMAP_BltIn(pDeviceBitmap, 0, 0 , 240, 240, pMe->_pBitmap, 0, 0, AEE_RO_COPY);

IDISPLAY_Update(pMe->a.m_pIDisplay);

IBASE_Release((IBase*)pDeviceBitmap );

こうやって高さを 0 にすると、自分でアロケートしたメモリのポインタを IDIB::pBmp にセットしても失敗するようだ。


以下推測。


IBITMAP_CreateCompatibleBimtap() で幅と高さをちゃんと指定して、それを IDIB に変換してから pBmp を NULL に設定して、IBITMAP_Release( pMe->_pBitmap ) を呼び出してみても正常にシステムで割り当てられた領域が解放されることから、本来の領域のポインタは IDIB の外にあって、終了時にそこから領域を解放していると予想。
IBITMAP_CreateCompatibleBimtap() で高さに 0 を指定すると、その本来の領域に NULL が設定されてしまって、IGraphics が使用出来ないのでは。
でも、なぜか IGRAPHICS_DrawRect() の返り値が SUCCESS なので、IDIB::cx と IDIB::cy の本来の値も外部にあって、本当の cy が 0 になっているから、クリッピングの時点で弾かれて SUCCESS を返していると考えられる。


つまり、IBITMAP_CreateCompatibleBimtap() で高さに 0 を指定するのはダメってことですな(´・ω・`)
自前のアロケータで DDB は作れないってことですか(;´Д`)