2016-05-20 11 views
0

Ich lerne derzeit C für ein Hobby-Projekt, für das ich versuche, eine einfache Benutzeroberfläche mit Direct2D-Grafik zu erstellen. Mit den Anweisungen unter DirectX in C konnte ich ein leeres Fenster erfolgreich öffnen. Da meine Benutzeroberfläche nur wenige Rechtecke benötigt, habe ich den Direct3D-Code in diesem Tutorial nicht verwendet. Stattdessen versuche ich ein gefülltes Rechteck mit Direct2D API zu zeichnen, aber es funktioniert nicht. Ich habe viele Codezeilen viele Male durchlaufen und viele Dinge ausprobiert, aber ich konnte einfach nicht funktionieren. Unten ist meine komplette C-Datei eingefügt.Direct2D mit C. FillRectangle funktioniert nicht

In meiner Render() -Funktion scheint ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor); zu funktionieren, aber das FillRectangle funktioniert nicht. Kann jemand bitte sagen, wie man dieses Problem beheben kann?

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

Welchen Wert gibt 'ID2D1HwndRenderTarget_FillRectangle' zurück? –

+0

@ JonathanPotter Zeichenoperationen geben 'void' zurück und verschieben einen Fehler auf' EndPaint() ', was ein' HRESULT' zurückgibt, das anzeigt, was der Fehler ist. – andlabs

Antwort

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

Denken Sie daran, dass D2D1_COLOR_F RGBA ist, nicht RGB. Dies initialisiert also eine Farbe mit einem Alpha-Wert von 0, der vollständig transparent ist. Wenn Sie ein völlig undurchsichtiges Rechteck wollen, müssen Sie sagen, dass:

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

Außer dem ist immer noch nicht richtig, da die Felder von D2D1_COLOR_F sind Gleitkommazahlen (die _F) im Bereich [0, 1] . Also, was Sie tun müssen, ist substitue 51.0/255.0 für 51 und einfach 1.0 für 255:

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

und jetzt sollte Ihr Rechteck angezeigt.

Lesen Sie unbedingt the documentation; es erklärt alles (auch wenn Sie durch einige typedef s klicken müssen, um dorthin zu gelangen).

+0

Danke, das hat mein Problem gelöst. Danke auch für die Erinnerung an die Dokumentation. – dprasad