2017-12-28 24 views
0

私はネイティブwinapiウィンドウと静的コントロールを子ウィンドウとして持つ単純なアプリケーションを持っています。私はDirect2Dで子ウィンドウを描画したいと思います。Direct2D DCコンテキストレンダリングイメージは起動時に表示されません

描画はWM_PAINTメッセージの外側で行われるため、ID2D1DCRenderTargetを使用することに決めました。 1つのこと以外はすべて動作します。アプリケーションの起動時に図面を表示させることはできません。

どのようなイベント(たとえば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

関連する問題