2017-05-29 123 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是最小化繪製位圖閃爍的正確位置。

相關問題