C++ 无法访问 CAutoPtr 数组

C++ Trouble accessing CAutoPtr array

我正在开发一个 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"));
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)。

您也可以考虑只保存图像名称,然后 load/draw/unload 以节省内存。

另请注意:

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

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