【发布时间】:2020-09-02 08:46:48
【问题描述】:
看来我学得很辛苦,如果我们使用 Direct2D 进行绘画,则不能使用WM_ERASEBKGND 来处理背景擦除,但我可能错了,所以这里是问题:
我用空画笔注册我的绘图窗口,让我手动处理背景擦除:
WNDCLASSEXW wcex;
wcex.hbrBackground = nullptr;
// etc...
这将使系统生成WM_ERASEBKGND,这是后台擦除的实现,顺便说一句。工作得很好:
// case WM_ERASEBKGND:
BOOL DrawableWindow::OnEraseBackground(WPARAM wParam)
{
HRESULT hr = CreateGraphicsResources();
if (SUCCEEDED(hr))
{
RECT rc{ };
GetClientRect(mhWnd, &rc);
const HDC hDC = reinterpret_cast<HDC>(wParam);
// ID2D1DCRenderTarget
hr = mpContextRender->BindDC(hDC, &rc);
if (FAILED(hr))
{
DiscardGraphicsResources();
return FALSE;
}
mpContextRender->BeginDraw();
mpContextRender->Clear(mBackground); // D2D1::ColorF background color (ie. green)
hr = mpContextRender->EndDraw();
if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
{
DiscardGraphicsResources();
return FALSE;
}
return TRUE;
}
// NOTE: Return value sets the PAINTSTRUCT.fErase
// which the OnPaint() handler can use to determine if painting the backgound is needed
return FALSE;
}
好的,背景已经设置好了,现在让我们在那个背景上绘画吧! 请参阅有条件擦除背景的代码中的注释。
// case WM_PAINT:
void DrawableWindow::OnPaint()
{
HRESULT hr = CreateGraphicsResources();
if (SUCCEEDED(hr))
{
PAINTSTRUCT ps{ };
BeginPaint(mhWnd, &ps);
// ID2D1HwndRenderTarget
mpWindowRender->BeginDraw();
// ***THE PROBLEM IS HERE***
// This value is nonzero if WM_ERASEBKGND erased the background!
if (ps.fErase)
{
// We clear client area only if WM_ERASEBKGND returned FALSE!
mpWindowRender->Clear(mBackground); // D2D1::ColorF background color (ie. green)
}
// We do drawing routuine here...
// ...
// done painting
hr = mpWindowRender->EndDraw();
if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
{
DiscardGraphicsResources();
}
EndPaint(mhWnd, &ps);
}
}
好的,这不起作用,因为一旦调用BeginDraw(),背景就会变黑,而我们在WM_ERASEBKGND 期间删除的背景会消失!
OnPaint() 处理程序中的检查if (ps.fErase) 不会被执行,因为它是FALSE,它是错误的,因为背景已被删除在WM_ERASEBKGND 中
结果是背景完全是黑色的,当我调整窗口大小时,我可以在几毫秒内看到我的原始背景很快变成黑色和ofc。由于色差,屏幕会闪烁。
所以问题是,我如何保留在WM_ERASEBKGND 中设置的背景?
从WM_ERASEBKGND返回FALSE真的是这里唯一的解决方案吗?
那么WM_ERASEBKGND 消息的意义何在?为什么BeginDraw() 会忽略我来自WM_ERASEBKGND 的背景并将背景变为黑色?
其他图纸是可见的。只是背景丢失了。
【问题讨论】:
-
您肯定可以通过简单地删除本机窗口客户区来让您的生活更轻松。这就是WS_EX_NOREDIRECTIONBITMAP 扩展窗口样式的用途。这样一来,您就可以完全控制窗口内容。 High-Performance Window Layering Using the Windows Composition Engine 解释了如何去做。
-
@IInspectable 好的,谢谢,我会检查一下,虽然我很感兴趣,为什么背景被擦除了两次