【问题标题】:GDI+ Text Flickering and Now with Black backgroundGDI+ 文本闪烁和现在黑色背景
【发布时间】:2020-09-22 03:52:54
【问题描述】:

我正在开发一个 Windows 桌面应用程序,但我沮丧地注意到我的文本在闪烁,因此在搜索时我发现了两种方法 - 对于 erasebkgnd 和双缓冲返回 true。第一种方法没有做任何事情,第二种方法由于某种原因使我的背景全黑,它仍然闪烁。

下面是我称之为绘画和缓冲的地方:

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);
}

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

【问题讨论】:

  • 提供的代码无法重现此问题。你能展示一个迷你的、完整的和可重复的样品吗?您想使用BeginBufferedPaint 实现什么目标? graphic.DrawImage实际做画。
  • 我读到要停止闪烁,我需要放置一个称为双缓冲区的东西,我不完全确定。因此,我决定尝试那里的解决方案,即 wmpaint 案例中 putImage 下面的行一直到 endbufferedpaint。当我注释掉那部分时,黑色窗口消失了,但闪烁仍然存在。

标签: c++ winapi gdi+


【解决方案1】:

我的背景全黑

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

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

闪烁

这个问题是由于没有以正确的方式使用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;

别忘了致电BufferedPaintInitBufferedPaintUnInit。比如这样:

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;
}

【讨论】:

  • 嗨,我想知道当您将 hr 变量设置为 EndBufferedPaint 时它是什么。是否只是为了检查返回值是否有效?
  • 由于某种原因,屏幕实际上闪烁比以前更严重:/
  • @ShadyAF 我用适合我的完整代码更新我的答案。你可以试试看。
  • 嗯...还是不行。是否与我添加了一个静态控件文本框有关?不知道为什么会这样。我还发现,如果我在 putImage 中注释掉 RedrawWindow,控件会停止闪烁,但窗口现在没有更新,因此它甚至无法显示图像。另外,我想知道你为什么把 m_pf 放在 bufferedpaint 函数调用的前面。
  • @ShadyAF 请使用没有其他控件的干净应用程序,然后重试。或发布重现问题的完整代码。使用 m_pf 因为我从 DLL 中找到函数并为我重命名它。我已经更新了我的答案以将其删除。你可以忽略它。
猜你喜欢
  • 2015-05-01
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-22
相关资源
最近更新 更多