2017-12-28 8 views
0

기본 Winapi 창을 사용한 간단한 응용 프로그램과 하위 창인 정적 컨트롤이 있습니다. Direct2D를 사용하여 자식 윈도우를 그립니다.Direct2D DC 컨텍스트 렌더링 이미지가 시작시 나타나지 않습니다.

드로잉은 WM_PAINT 메시지 외부에서 발생하므로 ID2D1DCRenderTarget을 사용하기로 결정했습니다. 한 가지는 제외하고 모든 것이 작동합니다. 응용 프로그램이 시작될 때 도면을 보이게 할 수 없습니다.

어떤 경우에도 (예 : WM_LBUTTONDOWN) 그림을 그리면 그림이 나타납니다. 그러나 내가 그림을 그리면 WM_CREATE 나는 화면에 아무 것도 볼 수 없다. 여기

내 예제 코드입니다 :

#include <iostream> 

#include <windows.h> 
#include <windowsx.h> 

#include <d2d1.h> 

#pragma comment(lib, "d2d1.lib") 

HWND windowHandle = NULL; 
HWND childWindowHandle = NULL; 

ID2D1Factory* direct2DFactory = nullptr; 
ID2D1DCRenderTarget* renderTarget = nullptr; 

static void InitDirect2D() 
{ 
    D2D1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED, &direct2DFactory); 

    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
     D2D1_RENDER_TARGET_TYPE_DEFAULT, 
     D2D1::PixelFormat(
      DXGI_FORMAT_B8G8R8A8_UNORM, 
      D2D1_ALPHA_MODE_IGNORE), 
     0, 
     0, 
     D2D1_RENDER_TARGET_USAGE_NONE, 
     D2D1_FEATURE_LEVEL_DEFAULT 
     ); 

    direct2DFactory->CreateDCRenderTarget (&props, &renderTarget); 
    renderTarget->SetAntialiasMode (D2D1_ANTIALIAS_MODE_ALIASED); 
} 

static void Paint() 
{ 
    ID2D1SolidColorBrush* blackBrush = nullptr; 
    renderTarget->CreateSolidColorBrush (
     D2D1::ColorF (D2D1::ColorF::Black), 
     &blackBrush 
    ); 

    renderTarget->BeginDraw(); 
    renderTarget->SetTransform (D2D1::Matrix3x2F::Identity()); 
    renderTarget->Clear (D2D1::ColorF (D2D1::ColorF::LightGray)); 
    D2D1_RECT_F rect = D2D1::RectF (10.0f, 10.0f, 100.0f, 100.0f); 
    renderTarget->DrawRectangle (&rect, blackBrush); 
    renderTarget->EndDraw(); 
} 

static LRESULT CALLBACK ChildWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) { 
     case WM_CREATE: 
      { 
       RECT rc; 
       GetClientRect (hwnd, &rc); 
       renderTarget->BindDC (GetDC (hwnd), &rc); 
       Paint(); 
      } 
      break; 
     case WM_LBUTTONDOWN: 
      Paint(); 
      break; 
     case WM_PAINT: 
      break; 
     case WM_SIZE: 
      { 
       RECT rc; 
       GetClientRect (hwnd, &rc); 
       renderTarget->BindDC (GetDC (hwnd), &rc); 
       Paint(); 
      } 
      break; 
     case WM_CLOSE: 
      DestroyWindow (hwnd); 
      break; 
     case WM_DESTROY: 
      PostQuitMessage (0); 
      break; 
      break; 
    } 

    LRESULT res = DefWindowProc (hwnd, msg, wParam, lParam); 
    return res; 
} 

static void CreateChildWindow (HWND parentHandle) 
{ 
    WNDCLASSEX windowClass; 
    memset (&windowClass, 0, sizeof (WNDCLASSEX)); 
    windowClass.cbSize = sizeof(WNDCLASSEX); 
    windowClass.style = 0; 
    windowClass.lpfnWndProc = ChildWindowProc; 
    windowClass.style = CS_DBLCLKS; 
    windowClass.cbClsExtra = 0; 
    windowClass.cbWndExtra = 0; 
    windowClass.hInstance = NULL; 
    windowClass.hCursor = LoadCursor (NULL, IDC_ARROW); 
    windowClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); 
    windowClass.lpszMenuName = NULL; 
    windowClass.lpszClassName = L"ChildWindowClass"; 

    RegisterClassEx (&windowClass); 
    childWindowHandle = CreateWindowEx (
     0, windowClass.lpszClassName, L"", WS_CHILD, 
     CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, parentHandle, NULL, NULL, nullptr 
    ); 

    ShowWindow (childWindowHandle, SW_SHOW); 
    UpdateWindow (childWindowHandle); 
    MoveWindow (childWindowHandle, 10, 10, 780, 580, TRUE); 
} 

static LRESULT CALLBACK MainWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    if (msg == WM_CREATE) { 
     CreateChildWindow (hwnd); 
     InvalidateRect (hwnd, NULL, FALSE); 
    } 

    switch (msg) { 
     case WM_SIZE: 
      { 
       int newWidth = LOWORD (lParam); 
       int newHeight = HIWORD (lParam); 
       MoveWindow (childWindowHandle, 10, 10, newWidth - 20, newHeight - 20, TRUE); 
      } 
      break; 
     case WM_CLOSE: 
      DestroyWindow (hwnd); 
      break; 
     case WM_DESTROY: 
      PostQuitMessage (0); 
      break; 
    } 

    return DefWindowProc (hwnd, msg, wParam, lParam); 
} 

static int CreateMainWindow() 
{ 
    WNDCLASSEX windowClass; 
    memset (&windowClass, 0, sizeof (WNDCLASSEX)); 
    windowClass.cbSize = sizeof (WNDCLASSEX); 
    windowClass.style = 0; 
    windowClass.lpfnWndProc = MainWindowProc; 
    windowClass.style = CS_DBLCLKS; 
    windowClass.cbClsExtra = 0; 
    windowClass.cbWndExtra = 0; 
    windowClass.hInstance = NULL; 
    windowClass.hIcon = LoadIcon (NULL, IDI_APPLICATION); 
    windowClass.hCursor = LoadCursor (NULL, IDC_ARROW); 
    windowClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); 
    windowClass.lpszMenuName = NULL; 
    windowClass.lpszClassName = L"WindowClass"; 
    windowClass.hIconSm = LoadIcon (NULL, IDI_APPLICATION); 

    RegisterClassEx (&windowClass); 

    RECT requiredRect = { 0, 0, 800, 600 }; 
    HWND windowHandle = CreateWindowEx (
     WS_EX_WINDOWEDGE, windowClass.lpszClassName, L"Example", WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, CW_USEDEFAULT, requiredRect.right - requiredRect.left, requiredRect.bottom - requiredRect.top, NULL, NULL, NULL, nullptr 
    ); 

    if (windowHandle == NULL) { 
     return 1; 
    } 

    ShowWindow (windowHandle, SW_SHOW); 
    UpdateWindow (windowHandle); 

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

    return 0; 
} 

int main (int argc, char* argv[]) 
{ 
    InitDirect2D(); 
    return CreateMainWindow(); 
} 

내가이 (가) 응용 프로그램 시작에 표시 그리기 할 수있는 방법 어떤 생각을 가지고 있습니까?

답변

1

WM_CREATE 동안 창은 아직 작성되지 않았으므로 그림이 작동하지 않습니다. 적절한 WM_PAINT (및 WM_ERASEBKGND) 메시지 처리기를 작성하고 거기에 모든 페인팅 작업을 수행해야합니다. 그런 다음 다른 메시지 (예 : WM_LBUTTONDOWN)에 대한 응답으로 다시 그려야 할 경우 즉시 Paint();을 호출하는 대신 창을 무효화하고 WM_PAINT을 트리거해야합니다.

+0

저는 Direct2D를 오프 스크린 컨텍스트로 사용하고 싶습니다. 그래서 이것이 Hwnd 렌더 타겟 대신 DC 렌더 타겟을 사용하는 이유입니다. 따라서 일반적으로 드로잉은 WM_PAINT에서는 발생하지 않지만 코드의 어디에서나 발생합니다. WM_PAINT에서 GDI 오프 스크린 DC 및 BitBlt와 비슷한 작업을하고 싶지만 Direct2D를 사용하고 싶습니다. – kovacsv

+1

더블 버퍼링을 위해 D2D를 사용하여 비트 맵 렌더 타겟을 생성하려면 WM_PAINT 핸들러에서 내용을 화면 타겟에 복사하십시오. – SoronelHaetir

+0

@kovacsv 오프 스크린 컨텍스트를 만들려면 GDI 장치 컨텍스트를 사용하거나 창을 전혀 만들지 않아도됩니다. – VTT

관련 문제