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);
您应该删除以上两行。请阅读有关其用法的文档。
我正在开发一个 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);
您应该删除以上两行。请阅读有关其用法的文档。