我正试图将一些HBITMAP保存到一个数组中,并在以后显示它们。从DC创建HBITMAP是可行的,但当我试图显示保存的HBITMAP时,我似乎得到了错误的HBITMAP。这让我觉得我还没有真正理解HTBIMAP是如何存储在内存中的。我假设数据类型HBITMAP本质上是指向内存中对象的指针,这就是我所需要的,但也许还有更多?
这是一个示例代码:
HBITMAP aBitMaps[NUM_BITMAPS];
int iNumBitMaps;
void SaveScreen(CDC *dc)
{
if (iNumBitMaps>0)
{
if (iNumBitMaps>=NUM_BITMAPS)
{
iNumBitMaps=NUM_BITMAPS-1;
DeleteObject(aBitMaps[iNumBitMaps]);
}
for (int i=iNumBitMaps;i>0;i--)
{
aBitMaps[i] = aBitMaps[i-1];
}
}
iNumBitMaps++;
aBitMaps[0] = CreateCompatibleBitmap(dc->m_hDC, 800, 800);
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[0]);
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
void RestoreScreen(CDC *dc, int i)
{
if (i>=NUM_BITMAPS) i = NUM_BITMAPS-1;
if (i<0) i = 0;
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[i]);
BitBlt(dc->m_hDC, 0, 0, 800, 800, hdcMem, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
因此,这个想法本质上是将HBITMAP指针推送到一个数组,并在稍后通过将其选择到存储器DC中,然后将其复制到实际DC来显示任何存储的图像。这个怎么了?
我使用的是VC++,Visual Studio 2010,没有MFC。
编辑:
我又做了一些测试。为了调试,我尝试通过在SaveScreen
中添加以下for
循环来显示所有存储的位图(位置偏移)
...
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
for (int j=0; j<iNumBitMaps;j++)
{
SelectObject(hdcMem, aBitMaps[j]);
BitBlt(dc->m_hDC, 20*(j+1), 100*(j+1), 800+20*(j+1), 800+100*(j+1), hdcMem, 0, 0, SRCCOPY);
}
ReleaseDC(hdcMem);
然后,它确实显示了图像的iNumBitMaps
倍,但它始终是相同的图像(即我存储在aBitMaps[0]
中的图像)。我确实在调试器中验证了aBitMaps
包含所有不同的指针。所以,不知怎么的,我认为我没有正确地将位图加载到内存DC中。
我想明白了。在我上面的代码中有两个错误(我知道)。首先,使用后必须删除内存DC,因此必须用DeleteDC
替换ReleaseDC
。
第二,必须知道被选入DC的对象不能被选入另一个DC。因此,重要的是,在对存储器DC中的对象进行操作之后,必须通过选择DC的前一个对象来卸载该对象。因此,正确的结构本质上是
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, aBitMaps[0]);
BitBlt(...);
HBITMAP hbmNew = (HBITMAP)SelectObject(hdcMem, hbmOld);
其中现在CCD_ 8指向与CCD_ 9相同的对象。