【问题标题】:Using the GDI+ API to draw an image使用 GDI+ API 绘制图像
【发布时间】:2021-11-09 18:36:39
【问题描述】:

我使用GDI+ API 只是为了在屏幕上显示图像 (bmp)。这是执行任务的函数的代码:

void drawImg_ArmorInfo_PupupWnd(HDC hdc) {

    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    Image* image = new Image(L"C:/Users/Darek/F2 stuff/art/intrface/armor_info_1.bmp");
    int a1 = image->GetWidth();
    int a2 = image->GetHeight();

    Graphics graphics(hdc);
    graphics.DrawImage(image, 0, 0);

    delete image;
    GdiplusShutdown(gdiplusToken);
}

问题是我在调用GdiplusShutdown 函数后遇到了一个异常:Access violation writing location 0xXXXXXXXX。当我注释掉的时候有什么有趣的

Graphics graphics(hdc);
graphics.DrawImage(image, 0, 0);

部分程序运行没有任何问题,但当然,图像没有被绘制。当我注释掉对GdiplusShutdown 函数的调用时 - 再次没有问题。

代码有什么问题,这里的问题可能是什么原因?

【问题讨论】:

  • GdiplusStartup/Shutdown 属于 main()。
  • Drawing a Line -- 查看两个配对调用的范围。
  • @Hans Passant "GdiplusStartup/Shutdown 属于 main" - 你能这么好解释一下你的意思吗?它怎么可能属于main,因为我是从drawImg_ArmorInfo_PupupWnd 函数中调用它的!?

标签: c++ winapi


【解决方案1】:

graphicsGdiplusShutdown 之后超出范围,因此无法正确销毁。

试试这个:

Graphics * graphics = new Graphics(hdc);
graphics->DrawImage(image, 0, 0);
delete graphics;

【讨论】:

  • 在 C++ 中确实没有 delete 的位置,并且几乎没有理由使用 new。 C++ 的强大功能是自定义析构函数。声明一个结构,其唯一目的是在其构造函数中初始化 GDI+,并在其析构函数中关闭 GDI+。
  • @Oleg Korzhukov。您的解决方案确实有效,但您可以这么好心并解释一下graphics 对象与GdiplusShutdown 函数的关系如何,因为在调用GdiplusShutdown 时没有引用graphics 对象!?
  • derec_911,是的,your 代码中没有直接引用,但请看 MS 写的。 MSDN:GdiplusStartup 函数初始化 Windows GDI+。在进行任何其他 GDI+ 调用之前调用 GdiplusStartup,并在您使用完 GDI+* 后*调用 GdiplusShutdown。graphics 被破坏之前,您还没有完成使用 GDI+。
  • @IInspectable 是对的,但我想,我们不是在这里教 RAII。原始代码相当短,出于宗教原因创建新对象是不切实际的。
  • @OlegKorzhukov Thx 回答但你能解释一下为什么当我使用“普通”对象而不是指针(Graphics graphics(hdc) vs new Gdiplus::Graphics(hdc))时会出现问题吗?
猜你喜欢
  • 1970-01-01
  • 2014-01-15
  • 2022-01-17
  • 2012-11-09
  • 2010-09-16
  • 1970-01-01
  • 2012-03-31
  • 1970-01-01
相关资源
最近更新 更多