2009-10-25 158 views
0

這是什麼原因?在列表視圖上繪製會禁用在列表視圖項上重繪

我重寫OnPaintBackground並繪製一個字符串。它不會顯示,直到我在構造函數中調用它:

this.SetStyle (ControlStyles.UserPaint, true); 

但後來我沒有看到列表視圖中的項目。

爲什麼以及如何解決這個問題?

編輯:代碼

protected override void OnPaintBackground (PaintEventArgs pevent) 
    { 
     base.OnPaintBackground (pevent); 

     // Create string to draw. 
     String drawString = "76"; 

     // Create font and brush. 
     Font drawFont = new Font ("Arial", 36); 
     SolidBrush drawBrush = new SolidBrush (Color.Blue); 

     // Create point for upper-left corner of drawing. 
     PointF drawPoint = new PointF (150.0F, 150.0F); 

     // Draw string to screen. 
     pevent.Graphics.DrawString (drawString, drawFont, drawBrush, drawPoint); 

     //pevent.Graphics.FillRectangle (drawBrush, this.ClientRectangle); 
    }`enter code here` 
+0

你打電話base.OnPaintBackground()?你可以發佈你的覆蓋代碼嗎? –

+0

以下屬性和樣式的值是什麼? - ControlStyles.DoubleBuffer - ControlStyles.AllPaintingInWmPaint - ListView.OwnerDraw –

+0

@Chris,添加了代碼。 –

回答

4

正如我在關於這個主題,OnPaint()UserPaint不ListView的工作,最後一個線程說。這幅畫由底層控件處理,不能以這種方式截取。這與其他控件不同

因此,當ControlStyles.UserPainttrue時,不會告知基礎控件重繪本身。相反,所有繪圖都會發送到OnPaintBackground()OnPaint()方法,而您已經發現這些方法什麼也不做。

有兩種方法可以做到你的要求(第二個比第一個好):

第一種方式:攔截WM_PAINT,做基礎處理,然後繪製到列表視圖。事情是這樣的:

public class MyListView : ListView 
{ 
    protected override void WndProc(ref Message m) { 
     switch (m.Msg) { 
      case 0x0F: // WM_PAINT 
       this.HandlePaint(ref m); 
       break; 
      default: 
       base.WndProc(ref m); 
       break; 
     } 
    } 

    protected virtual void HandlePaint(ref Message m) { 
     base.WndProc(ref m); 

     using (Graphics g = this.CreateGraphics()) { 
      StringFormat sf = new StringFormat(); 
      sf.Alignment = StringAlignment.Center; 
      sf.LineAlignment = StringAlignment.Center; 
      sf.Trimming = StringTrimming.EllipsisCharacter; 
      g.DrawString("Some text", new Font("Tahoma", 13), 
       SystemBrushes.ControlDark, this.ClientRectangle, sf); 
     } 
    } 
} 

但是這給當你得出的結論就是列表視圖認爲保持控制的內容在禁區外重繪問題 - 它不會觸發paint事件。

第二種方式:攔截CustomDraw通知(這是而不是與OwnerDraw相同),並偵聽CDDS_POSTPAINT階段。在那個階段,你可以安全地繪製到列表視圖。你可以看看ObjectListView的代碼,看看它是如何完成的。

你也可以只爲自己節省很多麻煩,直接使用ObjectListView :)

+0

謝謝Grammarian,我會切換到你的列表視圖。 –

+0

順便說一句,我剛剛切換到您的列表視圖,這是偉大的。但碰到了鼠標點擊測試的強制性異常,但我沒有在代碼中使用這些事件。 –