Direct2D DC上下文渲染图像在启动时不会出现

问题描述 投票:0回答:1

我有一个原生的winapi窗口的简单应用程序,以及作为子窗口的静态控件。我想用Direct2D绘制子窗口。

绘图发生在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 ();
}

您是否知道如何在应用程序启动时显示图形?

c++ winapi direct2d
1个回答
1
投票

WM_CREATE期间窗口没有完全创建,所以绘画不起作用。您应该编写一个合适的WM_PAINT(和WM_ERASEBKGND)消息处理程序并执行那里的所有绘制操作。然后,当您需要重绘作为对任何其他消息(例如WM_LBUTTONDOWN)的响应时,您需要使窗口无效并触发WM_PAINT而不是立即调用Paint();

© www.soinside.com 2019 - 2024. All rights reserved.