【发布时间】:2019-10-21 02:35:10
【问题描述】:
下面是一个将资源图像从可执行文件加载到ID2D1Bitmap指针的函数。
我的问题是,我需要在ID2D1Bitmap** ppBitmap函数参数上调用AddRef()吗?
例如在函数的末尾我需要这个吗:
(*ppBitmap)->AddRef();
我看到互联网上的代码有时会执行此类调用,有时不会,但我无法理解这何时有效,何时无效?
注意:对于最少的可编译代码,我提供了整个函数,不包括错误检查实现。
#include <sdkddkver.h>
#include <Windows.h>
#include <wincodec.h> // WIC
#include <d2d1.h> // ID2D1Bitmap
//
// Loads resource Image from executable
// into ID2D1Bitmap* pointer
//
template<typename RenderType>
HRESULT LoadResourceImage(
IWICImagingFactory* pFactory,
PCTSTR szFilename,
PCTSTR szFileType,
RenderType* pRenderTarget,
ID2D1Bitmap** ppBitmap)
{
HRESULT hr = S_OK;
DWORD dwImageSize = 0;
HMODULE hModule = GetModuleHandle(nullptr);
HRSRC hResource = nullptr;
HGLOBAL hResourceData = nullptr;
void* pImageFile = nullptr;
IWICStream* pStream = nullptr;
IWICFormatConverter* pConverter = nullptr;
IWICBitmapFrameDecode* pFrameDecode = nullptr;
IWICBitmapDecoder* pDecoder = nullptr;
if (!hModule)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}
hResource = FindResource(hModule, szFilename, szFileType);
if (!hResource)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}
if (FAILED(hr = hResource ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
dwImageSize = SizeofResource(hModule, hResource);
if (!dwImageSize)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}
if (FAILED(hr = dwImageSize ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
hResourceData = LoadResource(hModule, hResource);
if (!hResourceData)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}
if (FAILED(hr = hResourceData ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
pImageFile = LockResource(hResourceData);
if (!pImageFile)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}
if (FAILED(hr = pImageFile ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
if (FAILED(hr = pFactory->CreateStream(&pStream)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
hr = pStream->InitializeFromMemory(
reinterpret_cast<BYTE*>(pImageFile), dwImageSize);
if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
hr = pFactory->CreateDecoderFromStream(
pStream,
nullptr,
WICDecodeMetadataCacheOnDemand,
&pDecoder);
if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
if (FAILED(hr = pDecoder->GetFrame(0, &pFrameDecode)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
if (FAILED(hr = pFactory->CreateFormatConverter(&pConverter)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
hr = pConverter->Initialize(
pFrameDecode,
GUID_WICPixelFormat32bppPRGBA,
WICBitmapDitherTypeNone,
nullptr,
0.f,
WICBitmapPaletteTypeCustom);
if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
hr = pRenderTarget->CreateBitmapFromWicBitmap(
pConverter,
0,
ppBitmap);
if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}
done:
SafeRelease(&pFrameDecode);
SafeRelease(&pDecoder);
SafeRelease(&pConverter);
SafeRelease(&pStream);
return hr;
}
【问题讨论】:
-
不,你不需要这样做。您最终只需返回
CreateBitmapFromWicBitmap的结果 -
不,CreateBitmapFromWicBitmap() 已经这样做了。因此,使用您的函数的代码中的单个 Release() 调用足以再次销毁它。
-
你知道在什么情况下我需要
AddRef()吗?关于 AddRef 的任何规则 -
一般Rules for Managing Reference Counts,但您需要了解自己的参考计数。还有Managing the Lifetime of an Object