【发布时间】:2021-05-08 06:53:36
【问题描述】:
我正在尝试将应用程序图标放入 char 数组中。下面的代码将 HICON 转换为 BITMAP,然后尝试将 BITMAP 中的字节提取到 char 数组中。当我单步执行代码时,我观察到第二个 GetDIBits() 将目标指针修改为 NULL,尽管声称写入了 16 个字节。这种行为非常令人费解。我怀疑将BITMAPINFOHEADER* 转换为BITMAPINFO* 可能会有问题,但使用BITMAPINFO 会在退出函数时直接导致堆栈损坏。有谁知道为什么 GetDIBits() 会这样?
std::unique_ptr<char> getRawImg(HICON& icon)
{
// step 1 : get a bitmap from an application icon
ICONINFO iconInfo;
ZeroMemory(&iconInfo, sizeof(iconInfo));
BITMAP bitMap;
ZeroMemory(&bitMap, sizeof(bitMap));
HRESULT bRes = GetIconInfo(icon, &iconInfo);
int width;
int height;
int bitsPerPixel;
if (iconInfo.hbmColor) // color icon
{
if (GetObject(iconInfo.hbmColor, sizeof(bitMap), &bitMap))
{
width = bitMap.bmWidth;
height = bitMap.bmHeight;
bitsPerPixel = bitMap.bmBitsPixel;
}
}
else if (iconInfo.hbmMask) // black and white icon
{
if (GetObject(iconInfo.hbmMask, sizeof(bitMap), &bitMap))
{
width = bitMap.bmWidth;
height = bitMap.bmHeight / 2;
bitsPerPixel = 1;
}
}
// step 2 : extract bytes from the bitmap into a byte array
HBITMAP hBitmap = CreateBitmapIndirect(&bitMap);
int stride = (width * bitsPerPixel + 31) / 32 * 4;
HDC hdc = GetDC(NULL);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = bitsPerPixel;
bi.biCompression = BI_RGB;
bi.biSizeImage = stride * height;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
BITMAPINFO* pBitmapInfo = (BITMAPINFO*)&bi;
if (!GetDIBits(hdc, hBitmap, 0, 0, NULL, pBitmapInfo, DIB_RGB_COLORS)) {
// error
std::cout << "failed to get bitmap info" << std::endl;
}
std::unique_ptr<char> buffer(new char[bi.biWidth * bi.biHeight * bi.biBitCount / 8]);
// Buffer points to some address before calling GetDIBits(). After calling GetDIBits(), buffer points to NULL. bytesWritten is 16
int bytesWritten = GetDIBits(hdc, hBitmap, 0, height, (LPVOID)buffer.get(), pBitmapInfo, DIB_RGB_COLORS);
if (bytesWritten <= 0) {
// error
std::cout << "failed" << std::endl;
}
DeleteObject(hBitmap);
ReleaseDC(NULL, hdc);
if (iconInfo.hbmColor)
DeleteObject(iconInfo.hbmColor);
if (iconInfo.hbmMask)
DeleteObject(iconInfo.hbmMask);
return buffer;
}
【问题讨论】: