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

谢谢。

+2

“OnPaint”事件处理程序不应该创建自己的DC来绘制。你应该使用'CPaintDC'类。 –

+0

@CodyGray:谢谢。我已经尝试过,但它似乎不适合我。可能是因为我创建的paint-DC属于对话框本身,而不属于我试图绘制的窗口。你能否提供一些更具体的证据来证明为什么“OnPaint'事件处理程序不应该创建它自己的DC”?谢谢。 – goodvibration

+3

嗯...你为什么处理的一个窗口(对话)油漆事件,并试图画上一个*不同*窗口?如果你想在一个窗口上绘制,处理*该窗口的*绘制事件。 –

回答

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

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

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

+0

谢谢。该图像不包括整个图像窗口,所以我不能覆盖'OnEraseBkgnd'回调并返回TRUE。 – goodvibration

+0

您可以使您的绘图处理程序小心擦除窗口的未覆盖区域,然后跳过WM_ERASEBKGND。这可以通过避免画两次像素来防止闪光。然而,在一个具有桌面合成的现代系统上,你甚至可能不会注意到闪存。 –

0

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

相关问题