【问题标题】:Direct2D refuses to draw a bitmap onto a window, fails silentlyDirect2D 拒绝在窗口上绘制位图,静默失败
【发布时间】:2012-04-21 04:32:25
【问题描述】:

我正在尝试使用 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 中使用带有本机 WinAPI 的 C++。

【问题讨论】:

  • 我不知道 DirectX,但是在图形中,当您根本看不到任何东西时,可能是您启用了“双缓冲区”并且您没有交换缓冲区。是这样吗?
  • @Shahbaz 我不认为是这种情况...我正在绘制另一个显示得很好的纯色矩形。我认为 Direct2D 会处理它,因为它应该用于桌面界面,而不是 Direct3D 用于复杂的图形渲染。

标签: c++ winapi user-interface embedded-resource direct2d


【解决方案1】:

从资源加载位图时我遇到了同样的问题,而 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 );

【讨论】:

    【解决方案2】:

    我认为您仍然必须在 WM_PAINT 中使用经典的 BeginPaint(),然后进行 D2D 渲染,然后调用 EndPaint()。这就是我的代码所做的,我认为这也是 MSDN 示例代码小工具所做的。

    【讨论】:

    • 我研究过的 MSDN 示例不使用 BeginPaint/EndPaint。相反,他们只是在使用 Direct2D 绘制窗口后调用 ValidateRect。
    【解决方案3】:

    对此进行调试的方法是使用各种 API 锁定调用来获取指向图像数据的指针,然后通过调试器或 printf 检查图像数据,以验证数据是否符合您的预期。

    HBITMAP 和 D2D 表面有不同的 Lock 调用,但可以使用相同的想法。您应该能够缩小获取不良数据的范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 2016-06-11
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      相关资源
      最近更新 更多