简体   繁体   English

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

[英]The correct method for drawing a bitmap image into a window

I have a function which takes a rectangular region of a bitmap image, rescales it to different dimensions, and draws it at some offset inside of a window within my dialog-box application: 我有一个函数,它获取位图图像的矩形区域,将其重新缩放为不同的尺寸,并在对话框应用程序中的窗口内部某个偏移处绘制它:

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
    );
}

I create and maintain the window using a CWnd m_cImageWindow member variable. 我使用CWnd m_cImageWindow成员变量创建和维护窗口。

I perform the drawing from the dialog-box's OnPaint handler as follows: 我从对话框的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);

I have two problems: 我有两个问题:

  1. I see flickering whenever I change the drawing parameters. 每当我更改图形参数时,都会看到闪烁。 The standard way to solve this, from what I have read here and there, is by using a temporary DC for double-buffering. 根据我在这里和那里读到的内容,解决此问题的标准方法是使用临时DC进行双缓冲。 But as far as I understand, this is exactly what I am already doing. 但是据我了解,这正是我已经在做的事情。

  2. If some of the destination region falls outside the window, it is painted over other controls within the dialog box. 如果某些目标区域落在窗口之外,则会在对话框中的其他控件上绘制它。 I am able to partially solve this by calling MoveWindow or SetWindowPos for each one of these controls. 我可以通过为这些控件中的每个控件调用MoveWindowSetWindowPos来部分解决此问题。 But I can still see the image flickering behind them. 但是我仍然可以看到图像在它们后面闪烁。 I have tried calling SetWindowPos in various different ways, hoping in vain that it would dictate a strict Z-order of the controls. 我尝试以各种不同的方式调用SetWindowPos ,但徒劳地希望它能指示严格的Z顺序控件。

Thank you. 谢谢。

  1. The painting of the image into the child window should be done in the WM_PAINT handler for that child window, not for the dialog. 应当在WM_PAINT处理程序中为该子窗口(而不是对话框)在子窗口中绘画图像。 Your child window may need remember information provided by the parent dialog so that it can paint independently. 您的子窗口可能需要记住父对话框提供的信息,以便可以独立绘制。 By painting the window from the dialog's WM_PAINT handler, you're possibly painting more often than necessary (and possibly aren't causing a validation to occur in the image window). 通过从对话框的WM_PAINT处理程序绘制窗口,您可能绘制了比必要更多的图像(并且可能不会导致图像窗口中发生验证)。

  2. The dialog should probably have the WS_CLIPCHILDREN window style and your image window should probably have WS_CLIPSIBLINGS. 该对话框可能应该具有WS_CLIPCHILDREN窗口样式,并且您的图像窗口可能应该具有WS_CLIPSIBLINGS。 This will prevent the dialog controls from drawing over each other, and it can reduce flicker by allowing for more minimal updates. 这将防止对话框控件彼此重叠,并且可以通过允许进行最少的更新来减少闪烁。

  3. If the image will always completely cover the entire image window, then you want to make sure there's no background erasing happening for the image window, as that can cause a flash of the background color which looks like painting. 如果图像始终完全覆盖整个图像窗口,那么您要确保图像窗口没有背景擦除,因为这会导致看起来像绘画的背景颜色闪烁。 There are several ways to do this, but the easiest is probably to provide a WM_ERASEBKGND handler that just returns TRUE. 有多种方法可以执行此操作,但最简单的方法可能是提供一个仅返回TRUE的WM_ERASEBKGND处理程序。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM