简体   繁体   English

C的Direct2D。FillRectangle不起作用

[英]Direct2D with C. FillRectangle not working

I am currently relearning C for a hobby project, for which i am trying to build a simple UI with direct2D graphics. 我目前正在为一个业余项目重新学习C,为此我正在尝试使用Direct2D图形构建一个简单的UI。 Using the instructions available at DirectX in C , I was able to successfully open a blank window. 使用CDirectX的可用说明,我能够成功打开一个空白窗口。 Since my UI only needs few rectangles, i have not used the Direct3D code in that tutorial. 由于我的UI仅需要几个矩形,因此在该教程中我没有使用Direct3D代码。 Instead, i am trying to draw a filled rectangle using Direct2D API, but it is not working. 相反,我试图使用Direct2D API绘制一个填充的矩形,但是它不起作用。 I have gone through every line of code many times and tried many things , but just couldn't make it work. 我已经遍历了每一行代码多次,并尝试了许多事情,但无法使其正常工作。 Below is pasted my complete C file. 下面粘贴了我完整的C文件。

In my render() function , ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor); 在我的render()函数中, ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor); seems to be working , but the FillRectangle doesn't work. 似乎有效,但FillRectangle不起作用。 Can someone please tell, how to fix this issue ? 有人可以告诉我如何解决此问题吗?

#include <windows.h>
#include <malloc.h>

#include <d2d1.h>
#pragma comment(lib, "d2d1.lib")

const int WIDTH = 400;
const int HEIGHT = 400;

typedef struct {
    HWND hWnd;
    BOOL bDone;

    ID2D1Factory* direct2dFactory;
    ID2D1HwndRenderTarget* renderTarget;
    ID2D1SolidColorBrush* m_pLightSlateGrayBrush;
    ID2D1SolidColorBrush* m_pCornflowerBlueBrush;
} WindowObject;

static LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static void FreeWindowObject(WindowObject *window);

HRESULT CreateDeviceIndependentResources(WindowObject *window)
{
    HRESULT hr = S_OK;
    ID2D1Factory* pFactory = NULL;
    const D2D1_FACTORY_OPTIONS opts = { D2D1_DEBUG_LEVEL_INFORMATION };
    // Create a Direct2D factory.
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, 
        &IID_ID2D1Factory, &opts, (void**)&pFactory);
    window->direct2dFactory = pFactory;

    return hr;
}


HRESULT CreateDeviceResources(WindowObject *window)
{
    HRESULT hr = S_OK;

    if (!window->renderTarget)
    {
        RECT rc;
        GetClientRect(window->hWnd, &rc);

        D2D1_SIZE_U size;
        size.width = rc.right - rc.left;
        size.height = rc.bottom - rc.top;

        D2D1_RENDER_TARGET_PROPERTIES renderProps;
        D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderProps;
        D2D1_PIXEL_FORMAT pixFmt = { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN };
        renderProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
        renderProps.pixelFormat = pixFmt;
        renderProps.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
        renderProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
        renderProps.dpiX = renderProps.dpiY = 0.f;

        hwndRenderProps.hwnd = window->hWnd;
        hwndRenderProps.pixelSize = size;
        hwndRenderProps.presentOptions = D2D1_PRESENT_OPTIONS_NONE;

        // Create a Direct2D render target.
        if (FAILED(hr = ID2D1Factory_CreateHwndRenderTarget(window->direct2dFactory, 
            &renderProps, &hwndRenderProps, &window->renderTarget)))
        {
            OutputDebugStringA("Failed to create render target, err = %#x\n", hr);
            return 0;
        }

        D2D1_COLOR_F redColor = { 51, 51, 255 };
        if (SUCCEEDED(hr))
        {
            // Create a gray brush.
            hr = ID2D1HwndRenderTarget_CreateSolidColorBrush(window->renderTarget,
                &redColor, NULL, &window->m_pLightSlateGrayBrush);
        }
    }

    return hr;
}


void DiscardDeviceResources(WindowObject *window)
{
    ID2D1HwndRenderTarget_Release(window->renderTarget);
    ID2D1Factory_Release(window->direct2dFactory);
    //ID2D1HwndRenderTarget_Release(window->m_pCornflowerBlueBrush);
    //ID2D1HwndRenderTarget_Release(window->m_pLightSlateGrayBrush);
}


static WindowObject *CreateWindowObject(HINSTANCE hInstance)
{
    WindowObject *window;
    // Allocate the window data and create the window.
    window = malloc(sizeof(WindowObject));
    ZeroMemory(window, sizeof(WindowObject));
    HRESULT hr = CreateDeviceIndependentResources(window);

    const char *name = "Simple";
    int x, y, width, height;
    RECT rect;
    DWORD dwStyle = WS_VISIBLE | WS_OVERLAPPEDWINDOW;
    DWORD dwExStyle =  WS_EX_CLIENTEDGE;
    WNDCLASS wndClass = {
        CS_HREDRAW | CS_VREDRAW, WinProc, 0, 0, hInstance,
        0, LoadCursor(0, IDC_ARROW),
        1, 0, name
    };
    RegisterClass(&wndClass);

    window->hWnd = CreateWindowEx(
        dwExStyle, name, name, dwStyle,
        CW_USEDEFAULT,
        CW_USEDEFAULT, WIDTH, HEIGHT,
        0, 0, hInstance, 0
    );

    SetWindowLongPtr(window->hWnd, GWLP_USERDATA, window);

    hr = window->hWnd ? S_OK : E_FAIL;
    return window;
}

HRESULT render(WindowObject *window)
{
    HRESULT hr = S_OK;
    hr = CreateDeviceResources(window);
    if (!SUCCEEDED(hr))
    {
        return hr;
    }
    ID2D1HwndRenderTarget_BeginDraw(window->renderTarget);

    D2D1_COLOR_F whiteColor = { 255, 255,255 };
    ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor);

        // Draw rectangle.
    D2D1_RECT_F rectangle1 = { 10, 10,100,100 };
    ID2D1HwndRenderTarget_FillRectangle(window->renderTarget, &rectangle1, window->m_pLightSlateGrayBrush);

    hr = ID2D1HwndRenderTarget_EndDraw(window->renderTarget, NULL, NULL);
    if (hr == D2DERR_RECREATE_TARGET)
    {
        hr = S_OK;
        DiscardDeviceResources(window);
    }
    return hr;
}



static LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    WindowObject *window = (WindowObject *)GetWindowLongPtr(hWnd, GWLP_USERDATA);

    switch (uMsg) {
    case WM_KEYUP:
        if (wParam == VK_ESCAPE)
            SendMessage(hWnd, WM_CLOSE, 0, 0);
        break;
    case WM_PAINT:
        render(window);
        ValidateRect(hWnd, NULL);
        return 0;
        break;
    case WM_CLOSE:
        window->bDone = TRUE;
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WindowObject *window = CreateWindowObject(hInstance);


    while (!window->bDone) {
        MSG msg;
        if (PeekMessage(&msg, window->hWnd, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            render(window);
            ValidateRect(window->hWnd, NULL);
        }
    }

    FreeWindowObject(window);
    return 0;
}

static void FreeWindowObject(WindowObject *window)
{
    DiscardDeviceResources(window);
    free(window);
}
        D2D1_COLOR_F redColor = { 51, 51, 255 };

Remember that D2D1_COLOR_F is RGBA, not RGB. 请记住, D2D1_COLOR_F是RGBA,而不是RGB。 So this initializes a color with an alpha value of 0, which is fully transparent. 因此,这将初始化Alpha值为0的颜色,该颜色是完全透明的。 If you want a fully opaque rectangle, you'll need to say that: 如果您想要一个完全不透明的矩形,则需要这样说:

        D2D1_COLOR_F redColor = { 51, 51, 255, 255 };

Except that's still not correct, because the fields of D2D1_COLOR_F are floating-point (the _F ) in the range [0, 1]. 除非仍然不正确,否则因为D2D1_COLOR_F的字段是[0,1]范围内的浮点数( _F )。 So what you need to do is substitue 51.0/255.0 for 51 and simply 1.0 for 255 : 因此,您需要做的是将51替换为51.0/255.0 ,将255 51.0/255.01.0

        D2D1_COLOR_F redColor = { 51.0 / 255.0, 51.0 / 255.0, 1.0, 1.0 };

and now your rectangle should show up. 现在您的矩形应该会显示出来。

Be sure to read the documentation ; 请务必阅读文档 it explains everything (even if you have to click through some typedef s to get there). 它解释了所有内容(即使您必须单击某些typedef才能到达此处)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM