首页 > 解决方案 > 使用 GDI+ 旋转位图然后转换为 HDC

问题描述

我正在尝试做标题所说的。

下面是应该返回带有旋转图标的 HDC 的代码。我不确定为什么它没有返回任何东西。当我尝试绘制返回的 HDC 时,什么都没有出现,而且我测试它不是我的绘图中的错误。

Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR           gdiplusToken;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

Gdiplus::Bitmap SrcBitmap(L"H:\\Company\\iOG\\blue_arrow.tif", FALSE);

Gdiplus::Graphics DstGraphics(&SrcBitmap);

Gdiplus::REAL angle = lAngle;
DstGraphics.ResetTransform();
DstGraphics.RotateTransform(angle);
DstGraphics.TranslateTransform(SrcBitmap.GetWidth() / 2.0f, SrcBitmap.GetHeight() / 2.0f, Gdiplus::MatrixOrderAppend);
DstGraphics.DrawImage(&SrcBitmap, -((INT)SrcBitmap.GetWidth() / 2), -((INT)SrcBitmap.GetHeight() / 2), SrcBitmap.GetWidth(), SrcBitmap.GetHeight());

HBITMAP hBmp;
SrcBitmap.GetHBITMAP(Gdiplus::Color::Transparent, &hBmp);
HDC dcIcon = CreateCompatibleDC(NULL);
SelectObject(dcIcon, hBmp);

return dcIcon;

标签: c++winapibitmapdrawinggdi+

解决方案


Gdiplus::Bitmap::GetHBITMAP创建一个新的位图句柄。当不再需要此句柄时,应将其删除。上面代码的设置方式,位图句柄丢失,无法清理。这将导致资源泄漏,程序最终将停止工作。

您应该在修改图像的位图句柄之后,而不是在绘制该位图的设备上下文之后。您可以按如下方式修改代码:

HBITMAP convert(const wchar_t* filename, UINT& w, UINT& h)
{
    Gdiplus::Bitmap src(filename, FALSE);
    if(0 != src.GetLastStatus())
        return NULL;

    w = src.GetWidth();
    h = src.GetHeight();
    Gdiplus::Graphics gr(&src);
    gr.ResetTransform();
    gr.RotateTransform(45);
    gr.TranslateTransform(w / 2.0f, h / 2.0f, Gdiplus::MatrixOrderAppend);
    gr.DrawImage(&src, -(INT)w / 2, -(INT)h / 2);// , w, h);
    HBITMAP hbitmap = NULL;
    src.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
    return hbitmap;
}

void draw(HDC hdc)
{
    UINT w, h;
    HBITMAP hbitmap = convert(L"filename.bmp", w, h);
    if(hbitmap)
    {
        HDC memdc = CreateCompatibleDC(hdc);
        auto oldbmp = SelectObject(memdc, hbitmap);
        BitBlt(hdc, 0, 0, w, h, memdc, 0, 0, SRCCOPY);
        SelectObject(memdc, oldbmp);
        DeleteDC(memdc);
        DeleteObject(hbitmap);
    }
}

此外,调用GdiplusStartup应该以GdiplusShutdown

SelectObject(dcIcon, hBmp);应修改为返回旧的位图句柄。旧手柄应在最后恢复。


推荐阅读