C ++访问CAutoPtr数组时遇到问题

时间:2016-07-17 01:05:41

标签: c++ arrays image gdi+ cautoptr

我正在开发一个Windows程序,其目标是使用GDIPlus和Windows头文件显示图像按钮。

图像附加到全局CAutoPtr数组。在按钮回调中,我通过使用按钮的标识符(GetDlgCtrlID(hWnd))搜索图像数组(imageList)来处理WM_PAINT消息。

我可以使用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"));

1 个答案:

答案 0 :(得分: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; 
}

用于绘图

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

清理只有一行。如果您有较旧的VS版本,请使用

WM_DRAWITEM

如果制作自定义绘图按钮,您应该在按钮的父级中处理WM_PAINT。否则,如果禁用主题,则子类中的ReleaseDC(hWnd, GetDC(hWnd)); DeleteDC(newDC); 将不起作用(这适用于XP / Vista / Win7)。

您也可以考虑仅保存图像名称,然后加载/绘制/卸载以节省内存。

另请注意:

readings.js

你应该删除以上2行。请阅读有关其用法的文档。