2017-01-08 10 views
0

Я начал Direct2D с очень простого примера. Приобретите фабрику и ID2D1HwndRenderTarget, затем обработайте сообщение WM_PAINT, чтобы нарисовать только фон с сплошным цветом, используя функцию «Очистить».Direct2D: движущееся окно становится серым

Это нормально работает, пока я не начну перемещать окно. Когда окно движется, оно становится серым, как ничто не рисует. Я попытался нарисовать эллипс, и результат тот же.

Как можно представить содержимое окна при перемещении окна?

P.S. В случае, если код необходим

#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

Нам нужно будет увидеть код. – andlabs

ответ

2

Настройте WNDCLASSEX, чтобы не иметь фоновой щетки.

Заменить строку:

wndClassStruct.hbrBackground = (HBRUSH)COLOR_WINDOW; 

С этим:

wndClassStruct.hbrBackground = GetStockObject(NULL_BRUSH); 

В качестве альтернативы, вы можете изменить MainWndProc проглотить WM_ERASEBKGND сообщения. Он достигает такого же эффекта, не позволяя окну стираться до выдачи WM_PAINT.

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

Спасибо! Оба работают. Что лучше? NULL_BRUSH или WM_ERASEBKGND? – Lionishy

+0

Я бы использовал исправление WM_ERASEBKGND, так как это означает, что Windows даже не попытается выполнить обновление пикселя. Вы должны прочитать [this] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648055 (v = vs.85) .aspx), поскольку он предлагает вам вернуть 1 вместо 0. – selbie

+0

Большое спасибо! Я собираюсь обрабатывать сообщение WM_ERASEBKGND. – Lionishy