Direct2D与C. FillRectangle无法正常工作

时间:2016-05-20 23:01:31

标签: c visual-studio winapi directx

我目前正在为一个爱好项目重新学习C,我正在尝试使用direct2D图形构建一个简单的UI。使用DirectX in C处提供的说明,我能够成功打开一个空白窗口。由于我的UI只需要很少的矩形,我没有在该教程中使用Direct3D代码。相反,我试图使用Direct2D API绘制一个填充矩形,但它无法正常工作。我已经多次遍历每一行代码并尝试了很多东西,但却无法使其工作。下面是我完整的C文件。

在我的render()函数中, ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor);似乎有效,但FillRectangle无法正常工作。有人可以告诉,如何解决这个问题?

#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);
}

1 个答案:

答案 0 :(得分:0)

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

请记住,D2D1_COLOR_F是RGBA,而不是RGB。因此,这会初始化alpha值为0的颜色,这是完全透明的。如果你想要一个完全不透明的矩形,你需要说:

_F

除了仍然不正确之外,因为51.0/255.0的字段是[0,1]范围内的浮点(51)。所以你需要做的是替换1.0代替255 D2D1_COLOR_F redColor = { 51.0 / 255.0, 51.0 / 255.0, 1.0, 1.0 }; 代替typedef

yield

现在你的矩形应该出现了。

请务必阅读the documentation;它解释了一切(即使你必须点击一些Linq才能到达那里)。