2017-01-08 4 views
0

Ich habe Direct2D von einem sehr einfachen Beispiel gestartet. Erwerben Sie die Factory und ID2D1HwndRenderTarget, und behandeln Sie die WM_PAINT-Nachricht, um nur einen Hintergrund mit einer Volltonfarbe mithilfe der Funktion "Clear" zu zeichnen.Direct2D: bewegliches Fenster wird grau

Es funktioniert gut, bis ich anfange, das Fenster zu bewegen. Wenn sich das Fenster bewegt, wird es grau, als würde nichts gezeichnet. Ich habe versucht, eine Ellipse zu zeichnen, und das Ergebnis ist das gleiche.

Wie könnte man den Fensterinhalt mit dem sich bewegenden Fenster darstellen?

P.S. Wenn der Code benötigt wird

#include <Windows.h> 

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

ID2D1Factory * d2factory_ptr = NULL; 
ID2D1HwndRenderTarget * renderTarget_ptr = NULL; 


LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

int WINAPI wWinMain(
    HINSTANCE hInstance 
    , HINSTANCE prevInstance 
    , LPWSTR cmd 
    , int nCmdShow 
) { 
    WNDCLASSEX wndClassStruct; 
    ZeroMemory(&wndClassStruct, sizeof(WNDCLASSEX)); 
    wndClassStruct.cbSize = sizeof(WNDCLASSEX); 
    wndClassStruct.hbrBackground = (HBRUSH)COLOR_WINDOW; 
    wndClassStruct.style = CS_HREDRAW | CS_VREDRAW; 
    wndClassStruct.hInstance = hInstance; 
    wndClassStruct.lpfnWndProc = mainWinProc; 
    wndClassStruct.lpszClassName = TEXT("MainWnd"); 

    RegisterClassEx(&wndClassStruct); 

    RECT windowRect = { 0,0,640,480}; 
    AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, 0, WS_EX_APPWINDOW); 
    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, TEXT("MainWnd"), TEXT("Direct 2D Test Window"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, NULL, NULL, hInstance, 0); 

    { 
     D2D1_FACTORY_OPTIONS fo; 
     ZeroMemory(&fo, sizeof(D2D1_FACTORY_OPTIONS)); 

     IID const factoryIID = IID_ID2D1Factory1; 

     HRESULT res = S_OK; 
     if (S_OK != (res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factoryIID, &fo, &d2factory_ptr))) { 
      return 0; 
     } 

     RECT clientRect; 
     GetClientRect(hWnd, &clientRect); 

     D2D1_RENDER_TARGET_PROPERTIES renderTargetProps; 
     ZeroMemory(&renderTargetProps, sizeof(D2D1_RENDER_TARGET_PROPERTIES)); 
     renderTargetProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; 
     renderTargetProps.pixelFormat = (D2D1_PIXEL_FORMAT) { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED }; 
     renderTargetProps.dpiX = 0; 
     renderTargetProps.dpiY = 0; 
     renderTargetProps.usage = D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING; 
     renderTargetProps.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; 

     D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderProps; 
     ZeroMemory(&hwndRenderProps, sizeof(D2D1_HWND_RENDER_TARGET_PROPERTIES)); 
     hwndRenderProps.hwnd = hWnd; 
     hwndRenderProps.pixelSize = (D2D1_SIZE_U) { clientRect.right - clientRect.left, clientRect.bottom - clientRect.top }; 
     hwndRenderProps.presentOptions = D2D1_PRESENT_OPTIONS_NONE; 

     if (S_OK != (res = d2factory_ptr->lpVtbl->CreateHwndRenderTarget(d2factory_ptr, &renderTargetProps, &hwndRenderProps, &renderTarget_ptr))) { 
      return 0; 
     } 
    } 

    ShowWindow(hWnd, nCmdShow); 

    MSG msg; 
    while (GetMessage(&msg, NULL, 0, 0)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    DestroyWindow(hWnd); 

    if(NULL != renderTarget_ptr) 
     renderTarget_ptr->lpVtbl->Base.Base.Base.Release((IUnknown*)renderTarget_ptr); 

    if (NULL != d2factory_ptr) 
     d2factory_ptr->lpVtbl->Base.Release((IUnknown*)d2factory_ptr); 

    return 0; 
} 

LRESULT onPaintMainWindow() { 
    ID2D1RenderTargetVtbl renderTargetFuncs = renderTarget_ptr->lpVtbl->Base; 
    ID2D1RenderTarget * This = (ID2D1RenderTarget*)renderTarget_ptr; 
    D2D1_TAG tag1, tag2; 

    D2D1_COLOR_F backgroundClr = (D2D1_COLOR_F) { 0.0, 0.5, 1.0, 1.0 }; 
    renderTargetFuncs.BeginDraw(This); 
    renderTargetFuncs.Clear(This, &backgroundClr); 
    renderTargetFuncs.EndDraw(This, &tag1, &tag2); 

    return 0; 
} 

LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 

    if (WM_PAINT == uMsg) 
     return onPaintMainWindow(); 

    if (WM_DESTROY == uMsg) { 
     PostQuitMessage(0); return 0; 
    } 

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

Wir müssen Code sehen. – andlabs

Antwort

2

Konfigurieren Sie Ihre WNDCLASSEX, um keinen Hintergrundpinsel zu haben.

Ersetzen Sie diese Zeile:

wndClassStruct.hbrBackground = (HBRUSH)COLOR_WINDOW; 

mit diesem:

wndClassStruct.hbrBackground = GetStockObject(NULL_BRUSH); 

Alternativ können Sie MainWndProc ändern Sie die WM_ERASEBKGND Nachrichten zu schlucken. Dieselbe Wirkung wird erzielt, wenn das Fenster sich vor dem Ausgeben eines WM_PAINT nicht löschen lässt.

LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 

    if (WM_PAINT == uMsg) 
     return onPaintMainWindow(); 

    if (uMsg == WM_ERASEBKGND) 
    { 
     // ignore requests to erase the background since the wm_paint 
     // handler is going to redraw the entire window. 
     return 0; 
    } 

    if (WM_DESTROY == uMsg) { 
     PostQuitMessage(0); return 0; 
    } 

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

Danke! Beide arbeiten. Was ist eine bessere Entscheidung? NULL_BRUSH oder WM_ERASEBKGND? – Lionishy

+0

Ich würde den WM_ERASEBKGND-Fix verwenden, da dies bedeutet, dass Windows nicht einmal versuchen wird, einen Pixelupdate-Durchlauf durchzuführen. Sie sollten [this] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648055 (v = vs.85) .aspx) lesen, da es vorschlägt, dass Sie 1 anstelle von 0 zurückgeben sollten. – selbie

+0

Danke vielmals! Ich werde WM_ERASEBKGND Nachricht verarbeiten. – Lionishy