下面是一个将资源图像从可执行文件加载到ID2D1Bitmap
指针中的函数。
我的问题是,我需要在AddRef()
函数参数上调用ID2D1Bitmap** ppBitmap
吗?
例如在函数末尾,我是否需要这样做:
(*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;
}
答案 0 :(得分:1)
hr = pRenderTarget->CreateBitmapFromWicBitmap( pConverter, 0, ppBitmap);
成功调用上述ID2D1Bitmap
方法返回的CreateBitmapFromWicBitmap
对象已经已设置了正确的引用计数。因此,您不应在其上致电AddRef
。
完成对象后,只需在Release
COM接口指针上调用ID2D1Bitmap*
。
相反,如果您对返回的指针再次显式调用AddRef
,则需要一个与Release
匹配的正确的 additional ,否则将返回返回的对象不能释放自己。
请注意,由于我们正在讨论的是C ++代码(而非C代码),因此您可以使用 smart 指针,例如{来简化所有这些COM接口指针生命周期管理代码。 {3}},而不是指向COM接口的原始指针。
CComPtr
将自动在包装的原始COM接口指针上调用AddRef
和Release
(例如,在作用域末尾{{1} }将由Release
析构函数调用),因此您不必注意这些COM对象生命周期的详细信息。此外,即使在发生异常的情况下,~CComPtr
也会被自动调用,因此在引发异常时您不会泄漏COM对象。