2016-07-17 2 views
0

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

Изображения прикреплены к глобальному массиву 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 Palce.

Вы не можете использовать 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 линии. Пожалуйста, ознакомьтесь с документацией об их использовании.