将位图图像绘制成window的正确方法
The correct method for drawing a bitmap image into a window
我有一个函数,它获取位图图像的矩形区域,将其重新缩放到不同的尺寸,并在我的对话框应用程序中 window 内的某个偏移处绘制它:
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
成员变量创建和维护 window。
我从对话框的 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);
我有两个问题:
每当我更改绘图参数时,我都会看到闪烁。根据我在这里和那里阅读的内容,解决这个问题的标准方法是使用临时 DC 进行双缓冲。但据我了解,这正是我已经在做的事情。
如果某些目标区域落在 window 之外,它会覆盖对话框中的其他控件。我可以通过为这些控件中的每一个调用 MoveWindow
或 SetWindowPos
来部分解决这个问题。但我仍然可以看到他们身后闪烁的图像。我曾尝试以各种不同的方式调用 SetWindowPos
,希望它能规定控件的严格 Z 顺序是徒劳的。
谢谢。
我发现 OnEraseBkgnd 是最小化绘制位图闪烁的正确位置。
将图像绘制到 child window 应该在 WM_PAINT 处理程序中完成 child window ,不适用于对话框。您的 child window 可能需要记住 parent 对话框提供的信息,以便它可以独立绘制。通过从对话框的 WM_PAINT 处理程序绘制 window,您可能会比必要的更频繁地绘制(并且可能不会导致图像 window 中发生验证)。
对话框应该有 WS_CLIPCHILDREN window 风格,你的图像 window 应该有 WS_CLIPSIBLINGS。这将防止对话框控件相互重叠,并且可以通过允许更小的更新来减少闪烁。
如果图像总是完全覆盖整个图像 window,那么您要确保图像 window 没有发生背景擦除,因为这可能会导致看起来像绘画的背景颜色的闪光。有几种方法可以做到这一点,但最简单的方法可能是提供一个 returns TRUE 的 WM_ERASEBKGND 处理程序。
我有一个函数,它获取位图图像的矩形区域,将其重新缩放到不同的尺寸,并在我的对话框应用程序中 window 内的某个偏移处绘制它:
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
成员变量创建和维护 window。
我从对话框的 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);
我有两个问题:
每当我更改绘图参数时,我都会看到闪烁。根据我在这里和那里阅读的内容,解决这个问题的标准方法是使用临时 DC 进行双缓冲。但据我了解,这正是我已经在做的事情。
如果某些目标区域落在 window 之外,它会覆盖对话框中的其他控件。我可以通过为这些控件中的每一个调用
MoveWindow
或SetWindowPos
来部分解决这个问题。但我仍然可以看到他们身后闪烁的图像。我曾尝试以各种不同的方式调用SetWindowPos
,希望它能规定控件的严格 Z 顺序是徒劳的。
谢谢。
我发现 OnEraseBkgnd 是最小化绘制位图闪烁的正确位置。
将图像绘制到 child window 应该在 WM_PAINT 处理程序中完成 child window ,不适用于对话框。您的 child window 可能需要记住 parent 对话框提供的信息,以便它可以独立绘制。通过从对话框的 WM_PAINT 处理程序绘制 window,您可能会比必要的更频繁地绘制(并且可能不会导致图像 window 中发生验证)。
对话框应该有 WS_CLIPCHILDREN window 风格,你的图像 window 应该有 WS_CLIPSIBLINGS。这将防止对话框控件相互重叠,并且可以通过允许更小的更新来减少闪烁。
如果图像总是完全覆盖整个图像 window,那么您要确保图像 window 没有发生背景擦除,因为这可能会导致看起来像绘画的背景颜色的闪光。有几种方法可以做到这一点,但最简单的方法可能是提供一个 returns TRUE 的 WM_ERASEBKGND 处理程序。