2009-10-15 42 views
0

我寫了一個自定義控件呈現一些圖形。圖形本身渲染起來相當昂貴,但一旦渲染它很少發生變化。我的問題是,如果你在圖形真快移動鼠標表面也保持調用控件的重寫Paint方法,然後會帶來較高的CPU處罰:C#OnPaint mousemove高CPU使用率

私人無效UserControl1_Paint(對象發件人,PaintEventArgs的E)

由於鼠標指針下面的圖形/圖像實際上並沒有改變,可以使用哪些技術來避免這種情況或最小化任何不必要的重繪?

+0

感謝迄今爲止的答案。我應該補充說我使用control.Invalidate當我知道有什麼改變。當鼠標移動時,Paint方法被.NET調用(不是我!)。 –

+2

當鼠標移過控件時,OnPaint不會被調用,而是發生其他事情。 –

+1

我剛剛測試了一個簡單的項目,以確保Paint不會被鼠標移動調用,除非我在OnMouseMove中調用Invalidate(正如其他人在此提到的那樣)。你確定代碼中沒有其他的條件使得調用在不應該被調用時失效嗎?嘗試添加一些日誌記錄代碼來記錄呼叫失效和鼠標移動,並看看他們是否打電話,因爲你打算。 – rslite

回答

3

編輯:看到你的編輯後,我可以向你保證的OnPaint不是默認調用時通過控制鼠標移動。你的代碼中的東西肯定會導致重新繪製,你只是還沒有看到它。也許發佈一些代碼可以幫助我們發現問題。

您是否使MouseMove上的控件無效?這可能是一個壞主意,如果你真的需要這樣做(即,你正在製作一個圖形編輯器或其他東西),那麼你就必須明白一個區域實際上被重新繪製了多大。所以,解決方案;請勿在MouseMove中繪製您的控件。

否則,我不希望OnPaint在鼠標移過控件時觸發。您也可以只生成一次圖像,然後將其繪製到Graphics對象上,直到需要重新生成。

+0

謝謝。你一定是對的。我實際上覆蓋了另一個控件的行爲,所以它可能會在表單中做一些調皮的事情,導致鼠標移動失敗 –

2

您可以使用緩衝區圖像,在更改內容時繪製緩衝區圖像,並在Paint方法中將圖像複製到屏幕上。應該很快。您也可以使用剪輯區域來僅複製需要更新的部分。這應該會減少CPU使用率。

如果需要,您還可以使用IsDirty標誌來了解何時更新緩衝區映像(即完全重新繪製它)。

+0

這是目前我所做的。但是我想知道是否有辦法在鼠標移動時停止調用Paint的環境。 –

+0

光標在控件上移動時,不會調用OnPaint。 –

-1

您可以使用此代碼來剿,恢復控制的重繪:] 好運。

using System; 
    using System.Windows.Forms; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Runtime.InteropServices; 

namespace pl.emag.audiopc.gui { 
    // ************************************************************************ 
//`enter code here` 
    // ************************************************************************ 
    public class PaintingHelper { 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     public static void SuspendDrawing(Control parent) { 
      SendMessage(parent.Handle, WM_SETREDRAW, false, 0); 
     } 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     public static void ResumeDrawing(Control parent) { 
      SendMessage(parent.Handle, WM_SETREDRAW, true, 0); 
      parent.Refresh(); 
     } 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     [DllImport("user32.dll")] 
     private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, 
      bool wParam, Int32 lParam); 
     // ******************************************************************** 
     // 
     // ******************************************************************** 
     private const int WM_SETREDRAW = 11; 
    } 
} 
2

您不應直接致電Paint

相反,調用InvalidateControl.Invalidate)。這排隊需要重新繪製,Windows將自己照顧電話。這樣,可以通過對Paint的一次調用來服務很多快速失效(重新繪製請求)。

1

在Paint方法中可能導致高CPU負載的事情之一是不正確的(非託管)資源釋放。確保你做Dispose()所有的筆,畫筆等等(可能所有的System.Drawing類實例都有一些非託管資源綁定到它們)。 基本上你應該儘快處理對象的Dispose()。不要緩存或任何東西 - GDI +資源是系統資源,應該儘快返回給系統。獲取它們(例如創建新的Brush類實例)應該很快,但我現在沒有什麼可以支持這個語句。