C ++ Проблемы с доступом к массиву CAutoPtr

Я работаю над программой Windows, целью которой является отображение кнопок изображений с помощью GDIPlus и заголовочного файла Windows.

Изображения прикреплены к глобальному массиву CAutoPtr. Внутри обратного вызова кнопки я обрабатываю сообщение WM_PAINT путем поиска в массиве изображений (imageList) с использованием идентификатора кнопки (GetDlgCtrlID (hWnd)).

Я могу нарисовать первое изображение в imageList, однако, когда я пытаюсь нарисовать следующую кнопку с помощью imageList [2], оно не показывает никакого изображения.

Где именно проблема, и почему я не могу отобразить любое изображение, кроме того, что находится в первом слоте imageList?

Спасибо!

Это обрабатывает все сообщения кнопки.

CAutoPtr<Gdiplus::Image> typedef GdiplusImagePtr;
GdiplusImagePtr imageList[50];
Rect imagePositions[50];

LRESULT CALLBACK CustomButtonProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_CREATE:
{
// Same as WM_PAINT
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC newDC = BeginPaint(hWnd, &ps);

Gdiplus::Graphics newGraphics(hWnd);
newGraphics.DrawImage(imageList[GetDlgCtrlID(hWnd)], imagePositions[GetDlgCtrlID(hWnd)]);

EndPaint(hWnd, &ps);
ReleaseDC(hWnd, GetDC(hWnd));
DeleteDC(newDC);
break;
}
return CallWindowProc(customButtonProc, hWnd, msg, wp, lp);
}

Я использую эту строку кода, чтобы прикрепить изображение к imageList. Я подтвердил, что imageList содержит другие изображения; Я просто не могу их отобразить.

imageList[1].Attach(new Gdiplus::Bitmap(L"TestImage.png"));

0

Решение

CAutoPtr<Gdiplus::Image> typedef GdiplusImagePtr;
GdiplusImagePtr imageList[50];
imageList[1].Attach(new Gdiplus::Bitmap(L"TestImage.png"));

Вы не можете использовать Gdiplus::Image в одном месте и Gdiplus::Bitmap в другом месте.

Вы не можете использовать CAutoPtr для создания массивов таким образом. Кроме того, кажется, что вы объявляете массив указателей как глобальные значения. Это не освобождается до конца программы. Нет смысла делать это таким образом, даже если это работает. Обратите внимание, что при выходе из программы система освободит всю память. Цель должна состоять в том, чтобы минимизировать использование памяти во время работы программы.

использование CAutoPtr для одного объекта и использования CAutoPtrArray для массива. Но проще и эффективнее управлять распределением и очисткой самостоятельно. Пример:

std::vector<Gdiplus::Image*> list;
LRESULT CALLBACK MyProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM)
{
switch (msg)
{

case WM_CREATE:
list.push_back(new Gdiplus::Image(L"pic1.bmp"));
list.push_back(new Gdiplus::Image(L"pic2.bmp"));
return TRUE;

case WM_NCDESTROY:
//free memory here:
for (auto e : list) delete e;
break;
...
}
}

Для рисования

case WM_PAINT:
{
PAINTSTRUCT ps = { 0 };
HDC hdc = BeginPaint(hWnd, &ps);
Gdiplus::Graphics graphics(hWnd);
graphics.DrawImage(list[0], 0, 0);
EndPaint(hWnd, &ps);
return 0;
}

Очистка только одна строка. Если у вас более старые версии VS, используйте

for (size_t i = 0; i < list.size(); i++)
delete list[i];

При создании пользовательской кнопки рисования вы должны обрабатывать WM_DRAWITEM в родителя кнопки. Иначе WM_PAINT в подклассе не будет работать, если тема отключена (это относится к XP / Vista / Win7).

Вы также можете сохранить только имя изображения, а затем загрузить / нарисовать / выгрузить, чтобы сохранить память.

Также обратите внимание:

ReleaseDC(hWnd, GetDC(hWnd));
DeleteDC(newDC);

Вы должны удалить вышеуказанные 2 строки. Пожалуйста, ознакомьтесь с документацией по их использованию.

0

Другие решения

Других решений пока нет …