Возникло необработанное исключение std::bad_alloc
Нужно написать простой графический редактор, в котором есть кисть, ластик и возможность сохранять файл в формате bmp.
#include <iostream>
#include <wingdi.h>
// Константы для определения типов инструментов
const int TOOL_PENCIL = 0;
const int TOOL_BRUSH = 1;
const int TOOL_ERASER = 2;
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
bool isDrawing = false;
POINT prevPoint;
void SaveImageToFile(HBITMAP hBitmap, const char* filename) {
BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), &bmp);
BITMAPFILEHEADER bmfh = { 0 };
bmfh.bfType = 0x4D42; // "BM" magic number
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp.bmWidth * bmp.bmHeight * 4;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BITMAPINFOHEADER bmih = { 0 };
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = bmp.bmWidth;
bmih.biHeight = bmp.bmHeight;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
FILE* file;
errno_t err = fopen_s(&file, filename, "wb");
if (err == 0 && file) {
fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, file);
fwrite(&bmih, sizeof(BITMAPINFOHEADER), 1, file);
HDC hdc = GetDC(NULL);
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, hBitmap);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader = bmih;
GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, NULL, &bmi, DIB_RGB_COLORS);
BYTE* bits = new BYTE[bmp.bmWidth * bmp.bmHeight * 4];
GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, bits, &bmi, DIB_RGB_COLORS);
fwrite(bits, bmp.bmWidth * bmp.bmHeight * 4, 1, file);
delete[] bits;
SelectObject(memDC, oldBmp);
DeleteDC(memDC);
ReleaseDC(NULL, hdc);
fclose(file);
}
else {
std::cout << "Error saving image" << std::endl;
}
}
void CleanupResources(HWND hWnd, HBITMAP hBitmap) {
if (hBitmap) {
DeleteObject(hBitmap);
}
HDC hdc = GetDC(hWnd);
ReleaseDC(hWnd, hdc);
}
// Класс для рисования инструментов
class CPaintTool {
public:
virtual void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) = 0;
};
// Класс для карандаша
class CPencil : public CPaintTool {
public:
void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
LineTo(hdc, currentPoint.x, currentPoint.y);
}
};
// Класс для кисти
class CBrush : public CPaintTool {
public:
void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
Ellipse(hdc, currentPoint.x - 5, currentPoint.y - 5, currentPoint.x + 5, currentPoint.y + 5);
}
};
// Класс для ластика
class CEraser : public CPaintTool {
public:
void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
SelectObject(hdc, GetStockObject(WHITE_PEN));
MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
LineTo(hdc, currentPoint.x, currentPoint.y);
SelectObject(hdc, GetStockObject(BLACK_PEN));
}
};
// Класс графического редактора
class CGraphicEditor {
public:
CGraphicEditor() : m_hWnd(NULL), m_hdc(NULL), m_selectedTool(nullptr), m_previousPoint({ 0, 0 }) {}
void Initialize(HWND hWnd) {
m_hWnd = hWnd;
m_hdc = GetDC(hWnd);
}
void SetTool(CPaintTool* tool) {
m_selectedTool = tool;
}
void Draw(POINT currentPoint) {
if (m_selectedTool) {
m_selectedTool->Draw(m_hdc, m_previousPoint, currentPoint);
m_previousPoint = currentPoint;
}
}
private:
HWND m_hWnd;
HDC m_hdc;
CPaintTool* m_selectedTool;
POINT m_previousPoint;
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
static CGraphicEditor graphicEditor;
static CPencil pencil;
static CBrush brush;
static CEraser eraser;
static HBITMAP hBitmap;
switch (message) {
case WM_CREATE:
graphicEditor.Initialize(hWnd);
return 0;
case WM_MOUSEMOVE: {
POINTS points = MAKEPOINTS(lParam);
POINT currentPoint = { points.x, points.y };
graphicEditor.Draw(currentPoint);
if (isDrawing) {
HDC hdc = GetDC(hWnd);
SelectObject(hdc, hBrush);
POINT currentPoint;
currentPoint.x = LOWORD(lParam);
currentPoint.y = HIWORD(lParam);
MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
LineTo(hdc, currentPoint.x, currentPoint.y);
prevPoint = currentPoint;
ReleaseDC(hWnd, hdc);
}
return 0;
}
case WM_LBUTTONDOWN: {
int tool = TOOL_PENCIL; // Выбираем инструмент (карандаш, кисть, ластик)
switch (tool) {
case TOOL_PENCIL:
graphicEditor.SetTool(&pencil);
break;
case TOOL_BRUSH:
graphicEditor.SetTool(&brush);
break;
case TOOL_ERASER:
graphicEditor.SetTool(&eraser);
break;
}
SetCapture(hWnd); // Захватываем мышь для отслеживания движения за пределами окна
return 0;
}
case WM_LBUTTONUP:
isDrawing = false;
return 0;
//case WM_KEYDOWN:
// if (wParam == 'S') {
//const wchar_t* wideString = L"image.bmp";
// int size_needed = WideCharToMultiByte(CP_ACP, 0, wideString, -1, NULL, 0, NULL, NULL);
// char* filename = new char[size_needed];
// WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, size_needed, NULL, NULL);
// graphicEditor.SaveImageToFile(hBitmap, filename);
// delete[] filename;
// }
//return 0;
//case WM_KEYDOWN:
//if (wParam == 'S') {
//const wchar_t* wideString = L"image.bmp";
//int size_needed = WideCharToMultiByte(CP_ACP, 0, wideString, -1, NULL, 0, NULL, NULL);
//char* filename = new char[size_needed];
//WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, size_needed, NULL, NULL);
// SaveImageToFile(hBitmap, filename);
//delete[] filename;
//}
// return 0;
case WM_KEYDOWN:
if (wParam == 'S') {
const wchar_t* wideString = L"image.bmp";
char filename[MAX_PATH];
if (WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, MAX_PATH, nullptr, nullptr) != 0) {
SaveImageToFile(hBitmap, filename);
}
else {
// Обработка ошибки при преобразовании
MessageBox(nullptr, "Ошибка при преобразовании строки.", "Ошибка", MB_OK | MB_ICONERROR);
}
}
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
CleanupResources(hWnd, hBitmap);
PostQuitMessage(0);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
};
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = "SimplePaint";
if (!RegisterClass(&wc))
return 1;
HWND hWnd = CreateWindow(
wc.lpszClassName,
TEXT("Simple Paint"), // или L"Simple Paint"
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return 1;
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Имею следующую проблему: Вызвано исключение по адресу 0x00007FFFD0D25B0C: исключение Microsoft C++: std::bad_alloc по адресу памяти 0x00000073F4EFF070. Возникло необработанное исключение по адресу 0x00007FFFD0D25B0C: исключение Microsoft C++: std::bad_alloc по адресу памяти 0x00000073F4EFF070.
Возникает она, когда я нажимаю клавишу "S" для сохранения. Пробовала по разному фиксить - не выходит. Что делать с проблемой?