Данная функция используется в следующем фрагменте кода:
HDC dc = GetDC();
HDC mem_dc = CreateCompatibleDC(dc);
HBITMAP bitmap = CreateCompatibleBitmap(dc, 100, 50);
ReleaseDC(dc);
HBITMAP old = static_cast<HBITMAP>(SelectObject(mem_dc, bitmap));
SelectObject(mem_dc, CreateFontIndirect(&lf));
RECT rect = {0, 0, 100, 50};
HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255));
BITMAPINFO bmi;
char buffer[4096];
for (int i = 0; i < 32; i++)
{
FillRect(mem_dc, &rect, brush);
string symbol;
symbol += char('А' + i);
TextOut(mem_dc, x_offset_, y_offset_, symbol.c_str(), 1);
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 20;
bmi.bmiHeader.biHeight = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 4;
bmi.bmiHeader.biCompression = BI_RGB;
// Это нужно, чтобы удовлетворить следующему требованию из MSDN'а:
// The bitmap identified by the hbmp parameter must not be selected into
// a device context when the application calls this function.
SelectObject(mem_dc, old);
int rest = GetDIBits(mem_dc, bitmap, 0, 32, buffer, &bmi, DIB_PAL_COLORS);
old = static_cast<HBITMAP>(SelectObject(mem_dc, bitmap));
}
При запуске в debugger'е программа вылетает со следующим сообщением:
Run-Time Check Failure #2 — Stack around the variable 'bmi' was corrupted.
Если закомментировать вызов GetDIBits() то данная ошибка не появляется.
Я предполагаю, что GetDIBits() почему пишет за пределы массива buffer, но почему не пойму.
(специально увеличивал размеры массива на несколько порядков не помогает;
динамическое выделение массива приводит к другой ошибке — heap corruption)
Там специальным alloc'ом надо память выделять под буфер. Так по-памяти не вспомню, поглядите в MSDN в статье GetDIBits как функция называется.
Странно: сейчас глянул msdn, там ничего такого не сказано, но точно помню, что когда юзал GetDIBits (свой код писал на основе на основе чужих исходников) — использовал GlobalAlloc или что-то в этом духе. Почему — не помню, исходников под рукой нет. Но могу гарантировать, если Вы то же самое сделаете, то debug-версия ругаться не будет
Здравствуйте Topi_Nambur, Вы писали:
TN>Данная функция используется в следующем фрагменте кода:
TN>
TN>
TN>HDC dc = GetDC();
TN>HDC mem_dc = CreateCompatibleDC(dc);
TN>HBITMAP bitmap = CreateCompatibleBitmap(dc, 100, 50);
TN>ReleaseDC(dc);
TN>HBITMAP old = static_cast<HBITMAP>(SelectObject(mem_dc, bitmap));
TN>SelectObject(mem_dc, CreateFontIndirect(&lf));
TN>RECT rect = {0, 0, 100, 50};
TN>HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255));
TN>BITMAPINFO bmi;
TN>char buffer[4096];
TN>for (int i = 0; i < 32; i++)
TN>{
TN> FillRect(mem_dc, &rect, brush);
TN> string symbol;
TN> symbol += char('А' + i);
TN> TextOut(mem_dc, x_offset_, y_offset_, symbol.c_str(), 1);
TN> bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
TN> bmi.bmiHeader.biWidth = 20;
TN> bmi.bmiHeader.biHeight = 32;
TN> bmi.bmiHeader.biPlanes = 1;
TN> bmi.bmiHeader.biBitCount = 4;
TN> bmi.bmiHeader.biCompression = BI_RGB;
TN> // Это нужно, чтобы удовлетворить следующему требованию из MSDN'а:
TN> // The bitmap identified by the hbmp parameter must not be selected into
TN> // a device context when the application calls this function.
TN> SelectObject(mem_dc, old);
TN> int rest = GetDIBits(mem_dc, bitmap, 0, 32, buffer, &bmi, DIB_PAL_COLORS);
TN> old = static_cast<HBITMAP>(SelectObject(mem_dc, bitmap));
TN>}
TN>
TN>При запуске в debugger'е программа вылетает со следующим сообщением:
TN>Run-Time Check Failure #2 — Stack around the variable 'bmi' was corrupted.
Проблема в том, что для 4bpp GetDIBits пытается вернуть палитру, места для которой ты не зарезервировал.
Надо делать примерно так:
struct {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[16];
} bmi;
// всегда обнуляй неиспользуемые поля BITMAPINFOHEADER
memset(&bmi, 0, sizeof(bmi));
...
// сообщаем GetDIBits в каком формате мы хотим получить картинку
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 20;
bmi.bmiHeader.biHeight = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 4;
bmi.bmiHeader.biCompression = BI_RGB;
...
// вызываем GetDIBits; всегда указывай DIB_RGB_COLORS, unless
// ты действительно хочешь DIB_PAL_COLORS и знаешь, что это такое
GetDIBits(..., (BITMAPINFO *)&bmi, DIB_RGB_COLORS);