GDI+ 文本闪烁,现在有黑色背景

GDI+ Text Flickering and Now with Black background

我正在开发 windows 桌面应用程序,令我沮丧的是我的文本在闪烁,因此在搜索时我发现了两种方法 - return true 用于 erasebkgnd 和双缓冲。第一种方法没有做任何事情,第二种方法由于某种原因使我的背景全黑并且它仍然闪烁。

下面是我调用绘画和缓冲的地方:

case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC screen = BeginPaint(hWnd, &ps);   
            putImage(screen, hWnd);
            RECT rc;
            GetClientRect(hWnd, &rc);
            HDC memdc;
            auto hbuff = BeginBufferedPaint(screen, &rc, BPBF_COMPATIBLEBITMAP, NULL, &memdc);
            EndBufferedPaint(hbuff, TRUE);
            EndPaint(hWnd, &ps); } break;

下一部分是 putImage 函数

void putImage(HDC hdc, HWND hWnd)
{
    Graphics graphic(hdc);
    graphic.DrawImage(Image::FromFile(filePath), 10, 10);
    RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}

我想知道问题出在哪里,是否有解决办法。

my background all black

这个问题是因为你的背景没有填满。您可以像这样在绘制图像之前填充背景:

        RECT rc;
        GetClientRect(hWnd, &rc);
        FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));

flickering

此问题是由于未正确使用 BeginBufferedPaint。在绘制图像之前调用 BeginBufferedPaint

case WM_PAINT: {
    PAINTSTRUCT ps;
    HDC screen = BeginPaint(hWnd, &ps);
    HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
    if (hbuff)
    {
        RECT rc;
        GetClientRect(hWnd, &rc);
        FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
        putImage(screen, hWnd);

        hr = EndBufferedPaint(hbuff, TRUE);
    }

    EndPaint(hWnd, &ps); } break;

别忘了打电话给 BufferedPaintInit and BufferedPaintUnInit。例如像这样:

case WM_CREATE:
{
    hr = BufferedPaintInit();
}
break;

//...

case WM_DESTROY:
{
    BufferedPaintUnInit();
    PostQuitMessage(0);
}
break;

更新:完整代码。

void putImage(HDC hdc, HWND hWnd)
{
    Graphics graphic(hdc);
    Image* image = Image::FromFile(L"path-to\test.png");
    Status status = graphic.DrawImage(image, 10, 10);
    RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    DWORD err;
    HRESULT hr;
    static HDC memdc;

    switch (message)
    {
    case WM_CREATE:
    {
        hr = BufferedPaintInit();
    }
    break;
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC screen = BeginPaint(hWnd, &ps);
        HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
        if (hbuff)
        {
            RECT rc;
            GetClientRect(hWnd, &rc);
            FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
            putImage(screen, hWnd);

            hr = EndBufferedPaint(hbuff, TRUE);
        }

        EndPaint(hWnd, &ps); } break;

    case WM_DESTROY:
    {
        BufferedPaintUnInit();
        PostQuitMessage(0);
    }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}