将位图图像绘制到窗口中的正确方法

时间:2017-05-29 13:27:25

标签: winapi mfc device-context stretchblt setwindowpos

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

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. 如果某些目标区域落在窗口之外,则会将其绘制在对话框中的其他控件上。我可以通过为每个控件调用MoveWindowSetWindowPos来部分解决此问题。但我仍然可以看到背后闪烁的图像。我试过以各种不同的方式调用SetWindowPos,希望它能控制严格的Z控制顺序。

  3. 谢谢。

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

我发现OnEraseBkgnd是最小化绘制位图闪烁的最佳位置。