ID2D1DeviceContext 实现的 Direct2D 基本代码无法正常工作

问题描述 投票:0回答:1

https://learn.microsoft.com/ko-kr/windows/win32/direct2d/direct2d-quickstart-with-device-context

按照上面的步骤,我输入了绘制矩形的 Direct2D 基本代码。但它并没有画出任何东西。原因是什么?

这是创建一个空工程并在工程属性中将子系统设置为WINDOW后的结果。

#pragma comment(lib, "D2D1.lib")
#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "DXGI.lib")
#pragma comment(lib, "dxguid.lib")
#include <windows.h>
#include <d2d1.h>
#include <d2d1helper.h>
#include <d2d1_1.h>
#include <d3d11.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <wrl.h>
#include <wincodec.h>

using namespace D2D1;
using namespace Microsoft::WRL;

HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("DeviceContext Test");


int m_dpi = 96;
ComPtr<ID2D1Factory1> m_d2dFactory;
D3D_FEATURE_LEVEL m_featureLevel;
ComPtr<ID2D1Device> m_d2dDevice;
ComPtr<ID2D1DeviceContext> m_d2dContext;
ComPtr<IDXGISwapChain1> m_swapChain;
ComPtr<ID2D1Bitmap1> m_d2dTargetBitmap;
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
ComPtr<IDXGIDevice1> dxgiDevice;
ComPtr<IDXGIAdapter> dxgiAdapter;
ComPtr<IDXGIFactory2> dxgiFactory;
ComPtr<ID3D11Texture2D> backBuffer;
ComPtr<IDXGISurface> dxgiBackBuffer;

void onInit();
void onPaint();

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
    , LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;

    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);

    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
        //CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        1400, 500, 500, 500,
        NULL, (HMENU)NULL, hInstance, NULL);
    hWndMain = hWnd;
    ShowWindow(hWnd, nCmdShow);

    while (GetMessage(&Message, NULL, 0, 0)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch (iMessage) {
    case WM_CREATE:
        hWndMain = hWnd;
        onInit();
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        onPaint();
        InvalidateRect(hWnd, 0, 0);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}




void onPaint()
{
    HRESULT res;

    m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
    auto size = m_d2dTargetBitmap->GetSize();
    ComPtr<ID2D1SolidColorBrush> pBlackBrush;
    res = m_d2dContext->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
    );

    m_d2dContext->BeginDraw();

    D2D1_RECT_F rc;
    rc.left = rc.top = 100;
    rc.right = rc.bottom = 200;
    m_d2dContext->DrawRectangle(rc, pBlackBrush.Get());

    res = m_d2dContext->EndDraw();

    RECT rect = { 0, 0, 400, 400 };
    DXGI_PRESENT_PARAMETERS parameters;
    parameters.DirtyRectsCount = 1;
    parameters.pDirtyRects = &rect;
    parameters.pScrollOffset = 0;
    parameters.pScrollRect = 0;
    res = m_swapChain->Present1(1, 0, &parameters);
}
void onInit()
{
    D2D1_FACTORY_OPTIONS options;
    options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), &options, &m_d2dFactory);
    // This flag adds support for surfaces with a different color channel ordering than the API default.
    // You need it for compatibility with Direct2D.
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

    // This array defines the set of DirectX hardware feature levels this app  supports.
    // The ordering is important and you should  preserve it.
    // Don't forget to declare your app's minimum required feature level in its
    // description.  All apps are assumed to support 9.1 unless otherwise stated.
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    // Create the DX11 API device object, and get a corresponding context.

    D3D11CreateDevice(
        nullptr,                    // specify null to use the default adapter
        D3D_DRIVER_TYPE_HARDWARE,
        0,
        creationFlags,              // optionally set debug and Direct2D compatibility flags
        featureLevels,              // list of feature levels this app can support
        ARRAYSIZE(featureLevels),   // number of possible feature levels
        D3D11_SDK_VERSION,
        &device,                    // returns the Direct3D device created
        &m_featureLevel,            // returns feature level of device created
        &context                    // returns the device immediate context
    );

    // Obtain the underlying DXGI device of the Direct3D11 device.
    device.As(&dxgiDevice);

    // Obtain the Direct2D device for 2-D rendering.
    m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice);

    // Get Direct2D device's corresponding device context object.
    m_d2dDevice->CreateDeviceContext(
        D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
        &m_d2dContext
    );

    // Allocate a descriptor.
    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
    swapChainDesc.Width = 0;                           // use automatic sizing
    swapChainDesc.Height = 0;
    swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
    swapChainDesc.Stereo = false;
    swapChainDesc.SampleDesc.Count = 1;                // don't use multi-sampling
    swapChainDesc.SampleDesc.Quality = 0;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.BufferCount = 2;                     // use double buffering to enable flip
    swapChainDesc.Scaling = DXGI_SCALING_NONE;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
    swapChainDesc.Flags = 0;

    // Identify the physical adapter (GPU or card) this device is runs on.
    dxgiDevice->GetAdapter(&dxgiAdapter);

    // Get the factory object that created the DXGI device.
    dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory));

    // Get the final swap chain for this window from the DXGI factory.
    dxgiFactory->CreateSwapChainForHwnd(
        device.Get(),
        hWndMain,
        &swapChainDesc,
        nullptr,    // allow on all displays
        nullptr,
        &m_swapChain
    );

    // Ensure that DXGI doesn't queue more than one frame at a time.
    dxgiDevice->SetMaximumFrameLatency(1);

    // Get the backbuffer for this window which is be the final 3D render target.
    m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));

    // Now we set up the Direct2D render target bitmap linked to the swapchain. 
    // Whenever we render to this bitmap, it is directly rendered to the 
    // swap chain associated with the window.
    D2D1_BITMAP_PROPERTIES1 bitmapProperties =
        BitmapProperties1(
            D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
            m_dpi,
            m_dpi
        );

    // Direct2D needs the dxgi version of the backbuffer surface pointer.
    m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer));

    // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
    m_d2dContext->CreateBitmapFromDxgiSurface(
        dxgiBackBuffer.Get(),
        &bitmapProperties,
        &m_d2dTargetBitmap
    );
}
direct2d
1个回答
0
投票

更新窗口后,尝试删除 InvalidateRect 行或将其更改为 ValidateRect(hwnd, NULL)。

如果你不使用BeginPaint() ... EndPaint()对,你一定要使用ValidateRect(hwnd, NULL),否则窗口将不断生成WM_PAINT消息。 EndPaint() 内部执行 ValidateRect(hwnd, NULL)

© www.soinside.com 2019 - 2024. All rights reserved.