【问题标题】:How to save hdc and restore it?如何保存hdc并恢复它?
【发布时间】:2013-04-25 15:58:42
【问题描述】:

我编写了一个应用程序来在客户区绘制直线、矩形、椭圆。当我画任何东西时,我需要保存客户区的图像。当出现 WM_PAINT 消息时,我会恢复它。

我使用HBITMAP保存和恢复

保存

RECT rc;
GetClientRect(hMain, &rc); // hMain: handle main window
hdc = GetDC(hMain);
HDC hdcMem = CreateCompatibleDC(hdc);
// hbm: handle bitmap to save and restore
hbm = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);

SelectObject(hdcMem, hbm);
BitBlt(hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
    hdc, rc.right - rc.left, rc.bottom - rc.top, SRCCOPY); 
ReleaseDC(hMain, hdc);

恢复

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hMain, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
HDC hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hbm);
BitBlt(hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
    hdcMem, rc.right - rc.left, rc.bottom - rc.top, SRCCOPY);
ReleaseDC(hMain, hdc);
EndPaint(hMain, &ps);

但它不起作用。请帮帮我。

【问题讨论】:

  • 你不能用简单的方法在 WM_PAINT 中绘制(或代替)吗?
  • 这在保存端和恢复端都是错误的。保存端将仅捕获可见像素。不可见的像素(例如,被另一个窗口覆盖)将不会被捕获。恢复端在WM_PAINT 消息之外调用BeginPaint,不建议这样做。在这种情况下,它获得了一个被完全剪掉的 DC,因为没有任何东西是无效的。您应该在WM_PAINT 内完成所有工作 - 当您想要替换客户区时,绘制替换。当你想恢复旧的客户区时,执行旧的绘图代码。

标签: c++ winapi bitblt gdi


【解决方案1】:

除非您真的打算以艰难的方式做到这一点,否则我会放弃这种方法。我看到了两个合理的选择:

  1. 只需在 WM_PAINT 内进行所有绘图。当您希望线条、矩形、椭圆等消失时,请设置一些变量(或其他)以指示它们已消失,并使窗口无效以强制重绘。这是常规方式,大部分时间都能找到作品。

  2. 创建第二个窗口,覆盖当前窗口的客户区。将其创建为分层窗口,并在其窗口类中设置CS_SAVEBITS 样式。在此处绘制线条、椭圆等,并在您希望它们消失时简单地销毁窗口。

CS_SAVEBITS 自动执行您现在正在尝试执行的操作:保存窗口下方区域的位图,用于在CS_SAVEBITS 窗口消失时恢复底层窗口(完全自动)。这和你当前尝试做的事情都有同样的问题:保存的位图跟踪底层窗口中的任何变化——它们只是恢复曾经 上层窗口创建时在那里,它可能会变得陈旧。只有当底层窗口在持续时间内保持静态时它才能正常工作。

如果这是个问题,请结合使用两种方法:在覆盖窗口上去掉 CS_SAVEBITS。当它被销毁时,底层窗口将失效,并通过正常的重绘逻辑自行恢复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-06
    • 2015-03-21
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 2016-09-08
    • 1970-01-01
    相关资源
    最近更新 更多