【问题标题】:How to load a png resource into picture control on a dialog box?如何将png资源加载到对话框上的图片控件中?
【发布时间】:2011-04-28 15:47:56
【问题描述】:

我在 OnInitDialog() 上尝试了以下代码,但没有显示任何内容。

m_staticLogo.SetBitmap(::LoadBitmap(NULL, MAKEINTRESOURCE(IDB_LOGO)));

其中m_staticLogo为静态图片控件,IDB_LOGO为png文件的资源ID。

【问题讨论】:

标签: c++ visual-studio mfc png


【解决方案1】:

如您所见,::LoadBitmap(以及更新的::LoadImage)只处理.bmps。到目前为止,最简单的解决方案是将您的图像转换为.bmp

如果图片有透明度,可以转换成32位的ARGB位图(这里有个叫AlphaConv的工具可以转换)。然后使用CImageLoadFromResource 方法加载图像。将CImage 传递给m_staticLogo.SetBitmap()

但如果你真的需要它是.png,它可以做到。

方法 1(更简单的方法):使用 CImage::Load 从文件中加载 .png。将CImage 传递给m_staticLogo.SetBitmap()

方法 2(更难的方法): 通过将资源加载到 COM IStream 并使用 CImage::Load 从资源中加载 .png。 (注意:CImage::LoadFromResource 看起来很诱人,但不适用于.png 图形)。要将资源放入 COM IStream,请参阅 this Codeproject article。请注意本文适用于Gdiplus::Bitmap,但关键部分是如何创建IStream,您应该能够适应CImage。最后,将CImage 传递给m_staticLogo.SetBitmap()

编辑:更新为使用CImage,这比Gdiplus::Bitmap更容易。

【讨论】:

  • 我将 png 文件转换为 bmp 但问题是转换后图像的背景不再透明。有什么方法可以转换并仍然保留透明背景?
  • 方法 1 有效,但我希望将图形放在资源文件中。方法2对我来说太难了。
  • 您可以通过将 .png 转换为 32 位“ARGB”.bmp 来保持透明度。像 Paint.NET 这样的标准工具不会这样做。我已经用一个有效的工具更新了这篇文章。在 Visual Studio 中查看时可能看起来很奇怪,但呈现良好。这适用于单色背景。如果您有像照片这样的复杂背景,它将无法工作。
【解决方案2】:

对于那些需要快速解决方案的人,这是一种使用 GDI+ 从资源中加载 png 文件的方法(来自此处的标准 GDI 的原始答案 - http://www.codeproject.com/Questions/377803/How-to-load-PNG-images-in-mfc):

bool GdiPlusUtils::LoadBitmapFromPNG(UINT uResourceID, 
    Bitmap** ppBitmapOut, HINSTANCE hInstance /*= NULL*/)
{
    bool bRet = false;

    if (!hInstance)
        hInstance = AfxGetInstanceHandle();

    HRSRC hResourceHandle = ::FindResource(
        hInstance, MAKEINTRESOURCE(uResourceID), L"PNG");
    if (0 == hResourceHandle)
    {
        return bRet;
    }

    DWORD nImageSize = ::SizeofResource(hInstance, hResourceHandle);
    if (0 == nImageSize)
    {
        return bRet;
    }

    HGLOBAL hResourceInstance = ::LoadResource(hInstance, hResourceHandle);
    if (0 == hResourceInstance)
    {
        return bRet;
    }

    const void* pResourceData = ::LockResource(hResourceInstance);
    if (0 == pResourceData)
    {
        FreeResource(hResourceInstance);
        return bRet;
    }

    HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, nImageSize);
    if (0 == hBuffer)
    {
        FreeResource(hResourceInstance);
        return bRet;
    }

    void* pBuffer = ::GlobalLock(hBuffer);
    if (0 != pBuffer)
    {
        CopyMemory(pBuffer, pResourceData, nImageSize);
        IStream* pStream = 0;
        if (S_OK == ::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream))
        {
            *ppBitmapOut = new Bitmap(pStream);
            pStream->Release();
            bRet = true;
        }
        ::GlobalUnlock(hBuffer);
    }
    ::GlobalFree(hBuffer);

    UnlockResource(hResourceInstance);
    FreeResource(hResourceInstance);

    return bRet;
}

您可以使用“添加资源”命令将 png 文件添加为资源,然后在面板中选择“导入”。

【讨论】:

  • 你能举例说明调用 LoadBitmapFromPNG() 的正确方法吗?
  • 很简单,只要使用:Bitmap* pBitmap = 0; LoadBitmapFromPNG(IDB_PNG_YOUR_RESOURCE_ID, &pBitmap);其中 Bitmap* 是 GDI+ 位图类,IDB_PNG_YOUR_RESOURCE_ID 是指向位图的资源的 ID。
【解决方案3】:

它支持的位图和图标。不确定.png。 或者,您可以尝试以下方法。

  1. 在 MS Paint 或其他查看器中打开 png。
  2. 然后从中复制图像部分。
  3. 在 MFC 资源中创建资源。
  4. 将复制的图像粘贴到新创建的资源中。
  5. 在 LoadBitmap 中使用新的资源 ID。

【讨论】:

    【解决方案4】:

    如果您将 .png 图像文件转换为 .bmp 格式,您最终可以获得图像清晰度。因此,在对话框类中捕获 WM_PAINT 消息并使用

    Graphics::DrawImage 方法

    要获得此方法,请将您的项目与 gdiplus.lib 库链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2012-05-06
      • 2013-07-26
      相关资源
      最近更新 更多