2009-10-25 50 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

顺便说一句,我刚刚切换到您的列表视图,这是伟大的。但碰到了鼠标点击测试的强制性异常,但我没有在代码中使用这些事件。 –