CreateHwndRenderTarget引发异常:读取访问冲突 **这**是nullptr

问题描述

我最近一直在使用this教程来学习Win32 API。我一直在尝试创建一个基于Direct2D的显示圆形的窗口。但是,程序不断抛出异常:

Exception thrown: read access violation.
**this** was nullptr.

VS 2019然后在本节中打开d2d1.h:

CreateHwndrendertarget(
        CONST D2D1_RENDER_TARGET_PROPERTIES &rendertargetProperties,CONST D2D1_HWND_RENDER_TARGET_PROPERTIES &hwndrendertargetProperties,_COM_Outptr_ ID2D1Hwndrendertarget **hwndrendertarget 
        )  
    {
        return CreateHwndrendertarget(&rendertargetProperties,&hwndrendertargetProperties,hwndrendertarget);
    }

这是我的代码中导致此问题的部分:

HRESULT CreateGraphicsResources(HWND hWnd) {
    HRESULT hr = S_OK;
    if (prendertarget == NULL) {
        RECT rc;
        GetClientRect(hWnd,&rc);

        D2D1_SIZE_U size = D2D1::SizeU(rc.right,rc.bottom);

        hr = pFactory->CreateHwndrendertarget(
            D2D1::rendertargetProperties(),D2D1::HwndrendertargetProperties(hWnd,size),&prendertarget);
        
        if (SUCCEEDED(hr)) {
            const D2D1_COLOR_F color = D2D1::ColorF(1.0f,1.0f,0);
            hr = prendertarget->CreateSolidColorBrush(color,&pBrush);

            if (SUCCEEDED(hr))
            {
                CalculateLayout();
            }
        }
    }
    return hr;
}

这是我调用函数的地方

case WM_PAINT:
        {
            HRESULT hr = CreateGraphicsResources(hWnd);
            if (SUCCEEDED(hr))
            {
                PAINTSTRUCT ps;
                BeginPaint(hWnd,&ps);

                prendertarget->BeginDraw();

                prendertarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
                prendertarget->FillEllipse(ellipse,pBrush);

                hr = prendertarget->EndDraw();
                if (Failed(hr) || hr == D2DERR_RECREATE_TARGET)
                {
                    discardGraphicsResources();
                }
                EndPaint(hWnd,&ps);
            }
}

那么,此异常是什么意思,是什么导致它被抛出? 另外,我该如何解决? 感谢您的帮助。 完整文件可用here

解决方法

您的pFactory引用为null。但是您要初始化它,为什么它为null?由于您的代码已损坏,因此可以这样做:

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch (message)
    {
    ... some code
    case WM_SIZE:
        {
           ... some code
        }
        
    // there is no break here!
    // first call to WM_SIZE falls down to WM_DESTROY which destroys your pFactory...
    
    case WM_DESTROY:
        DiscardGraphicsResources();
        SafeRelease(&pFactory);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd,message,wParam,lParam);
    }
    return 0;

只需在break之前添加WM_DESTROY