0

我有一个函数,它获取位图图像的矩形区域,将其重新缩放为不同的尺寸,并在我的对话框应用程序的窗口内的某个偏移处绘制它:

void DrawImage(HANDLE hImageBitmap,
               CDC* pDstDC,const CRect& dstRect,
               CDC* pSrcDC,const CRect& srcRect)
{
    pSrcDC->SelectObject(hImageBitmap);
    pDstDC->SetStretchBltMode(HALFTONE);
    pDstDC->StretchBlt
    (
        dstRect.left,dstRect.top,dstRect.Width(),dstRect.Height(),pSrcDC,
        srcRect.left,srcRect.top,srcRect.Width(),srcRect.Height(),SRCCOPY
    );
}

我使用CWnd m_cImageWindow成员变量创建和维护窗口。

我从对话框的OnPaint处理程序执行绘图,如下所示:

CDC* pDC = m_cImageWindow.GetDC();
CDC  cDC;
cDC.CreateCompatibleDC(pDC);

CRect srcRect = ...;
CRect dstRect = ...;
DrawImage(m_hImageBitmap,pDC,dstRect,&cDC,srcRect);

cDC.DeleteDC();
m_cImageWindow.ReleaseDC(pDC);

我有两个问题:

  1. 每当我更改绘图参数时,我都会看到闪烁。根据我在这里和那里阅读的内容,解决此问题的标准方法是使用临时 DC 进行双缓冲。但据我了解,这正是我已经在做的事情。

  2. 如果某些目标区域位于窗口之外,则会将其绘制在对话框内的其他控件上。我可以通过调用这些控件中的每一个来部分解决这个MoveWindow问题SetWindowPos。但我仍然可以看到他们身后闪烁的图像。我尝试过SetWindowPos以各种不同的方式调用,但徒劳地希望它会规定控件的严格 Z 顺序。

谢谢你。

4

2 回答 2

1
  1. 将图像绘制到子窗口中应该在该子窗口的 WM_PAINT 处理程序中完成,而不是在对话框中完成。您的子窗口可能需要记住父对话框提供的信息,以便它可以独立绘制。通过从对话框的 WM_PAINT 处理程序绘制窗口,您的绘制频率可能会超出必要(并且可能不会导致在图像窗口中发生验证)。

  2. 该对话框应该可能具有 WS_CLIPCHILDREN 窗口样式,并且您的图像窗口应该可能具有 WS_CLIPSIBLINGS。这将防止对话框控件相互绘制,并且可以通过允许更少量的更新来减少闪烁。

  3. 如果图像将始终完全覆盖整个图像窗口,那么您要确保图像窗口没有发生背景擦除,因为这会导致背景颜色闪烁,看起来像绘画。有几种方法可以做到这一点,但最简单的可能是提供一个只返回 TRUE 的 WM_ERASEBKGND 处理程序。

于 2017-05-30T17:38:13.523 回答
0

我发现 OnEraseBkgnd 是减少绘制位图闪烁的正确位置。

于 2017-05-30T14:15:48.317 回答