我正在尝试使用 Direct2D 在窗口上绘制 128x128 位图。但是,没有显示任何内容,并且
EndDraw()
不会返回任何错误。
这是我的
WM_PAINT
代码:
case WM_PAINT:
D2D1_RECT_F testd2dbuttonrect;
mainwRT->BeginDraw();
mainwRT->SetTransform( D2D1::Matrix3x2F::Identity() );
testd2dbutton.pd2drectgm->GetRect( &testd2dbuttonrect );
mainwRT->FillRectangle( &testd2dbuttonrect, pSolidBrush );
//This is where I'm trying to draw my bitmap
mainwRT->FillRectangle( D2D1::RectF(0.0f,0.0f,127.0f,127.0f), pBgndBrush );
errmsg = mainwRT->EndDraw();
if( !SUCCEEDED(errmsg) )
printf("EndDraw() error: %d\r\n", errmsg );
break;
我怀疑这可能是因为我从 Visual Studio 资源加载的位图数据是垃圾,但我无法知道,因为没有任何失败并给出错误消息。这是我用来从资源加载
ID2D1Bitmap
的代码:
int LoadBitmapFromResource( IWICImagingFactory *pImageFactory, ID2D1RenderTarget *pRT, int resID, ID2D1Bitmap **ppD2DBitmap )
{
int errmsg;
HBITMAP hbitmap;
WICBitmapAlphaChannelOption wicalpha;
IWICBitmap *pwicbitmap;
IWICBitmapSource *pconvertedwicbitmap;
IWICFormatConverter *pConverter;
ID2D1Factory *d2dfactory;
D2D1_BITMAP_PROPERTIES d2dbp;
D2D1_PIXEL_FORMAT d2dpf;
FLOAT dpiX;
FLOAT dpiY;
hbitmap = LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCEW(resID) );
wicalpha = WICBitmapUseAlpha;
errmsg = pImageFactory->CreateBitmapFromHBITMAP( hbitmap, NULL, wicalpha, &pwicbitmap );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateBitmapFromHBITMAP() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pImageFactory->CreateFormatConverter( &pConverter );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateFormatConverter() error: %x\r\n", errmsg );
return errmsg;
}
d2dpf.format = DXGI_FORMAT_B8G8R8A8_UNORM;
d2dpf.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
pRT->GetFactory( &d2dfactory );
d2dfactory->GetDesktopDpi( &dpiX, &dpiY );
d2dbp.pixelFormat = d2dpf;
d2dbp.dpiX = dpiX;
d2dbp.dpiY = dpiY;
pConverter->Initialize( pwicbitmap, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::Initialize() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = WICConvertBitmapSource( GUID_WICPixelFormat32bppPBGRA, pwicbitmap, &pconvertedwicbitmap );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::WICConvertBitmapSource() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pRT->CreateBitmapFromWicBitmap( pconvertedwicbitmap, &d2dbp, ppD2DBitmap );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateBitmapFromWicBitmap() error: %x\r\n", errmsg );
return errmsg;
}
pConverter->Release();
pwicbitmap->Release();
DeleteObject( hbitmap );
return 0;
}
我在 Visual Studio 2010 中使用 C++ 和本机 WinAPI。
我认为你仍然必须使用WM_PAINT中经典的BeginPaint(),然后进行D2D渲染,然后调用EndPaint()。这就是我的代码所做的事情,我认为这也是 MSDN 示例代码小工具所做的事情。
从资源加载位图时遇到同样的问题,而 D2D 在运行 CreateBitmapFromWicBitmap 时遇到问题。在我的同事的帮助下,关键问题是使用 WICBitmapIgnoreAlpha,因为位图没有 Alpha(至少我的资源中的 BITMAP 没有 Alpha)。
甚至您不需要转换器,只需简单的代码即可
hbitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(resID) );
if (hbitmap==0)
{
SafeRelease(&pImageFactory);
return nullptr;
}
hr = pImageFactory->CreateBitmapFromHBITMAP( hbitmap, NULL, wicalpha, &pwicbitmap );
if( !SUCCEEDED(hr) )
{
DeleteObject( hbitmap );
SafeRelease(&pImageFactory);
return nullptr;
}
ID2D1Bitmap* ppD2DBitmap=nullptr;
hr = pRT->CreateBitmapFromWicBitmap( pwicbitmap, &ppD2DBitmap );
调试此问题的方法是使用各种 API 锁定调用来获取指向图像数据的指针,然后通过调试器或 printf 检查图像数据,以验证数据是否是您所期望的。
HBITMAP 和 D2D 表面有不同的 Lock 调用,但可以使用相同的想法。您应该能够缩小获得不良数据的范围。
我刚刚遇到了一个非常类似的问题,所以我想我应该把我的解决方案留在这里:如果你尝试使用 direct2d 绘制一些东西并且没有显示任何内容(但没有报告错误),你可能忘记了调整你的大小WM_SIZE 消息中的渲染目标。如果您不这样做,也不使用屏幕尺寸初始化渲染目标,那么您将拥有尺寸为零的渲染目标,这将无法绘制任何内容,甚至屏幕清除操作也会失败。