摘要:
Paint事件被触发了多少次?比较简单的方式,我们自己做一个perfmon能用的counter。看代码:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 4 if (!PerformanceCounterCategory.Exists("GDI+ Monitor")) 5 { 6 CounterCreationDataCollection ccdc = new CounterCreationDataCollection(); 7 8 CounterCreationData totalPaint = new CounterCreationData(); 9 totalPaint.CounterName = "# operator executed";10 totalPaint.CounterHelp = "Counts of OnPaint events called";11 totalPaint.CounterType = PerformanceCounterType.NumberOfItems32;1213 ccdc.Add(totalPaint);1415 PerformanceCounterCategory.Create("GDI+ Monitor", "Some counters for GDI+ objects", PerformanceCounterCategoryType.MultiInstance, ccdc);16 }17 }好,点一下button1之后,我们就可以在perfmon中看到GDI+ Monitor这个category了,然后只有一个counter,就是# operator executed然后在winform中增加这么一段:
paintcall = new PerformanceCounter(); paintcall.CategoryName = "GDI+ Monitor"; paintcall.CounterName = "# operator executed"; paintcall.MachineName = "."; paintcall.ReadOnly = false;好了,代码里面可以用paintcall这个变量了。我们现在的需求是监视Paint被触发了多少次,那么可以在代码中这么写:
1 Graphics g2 = e.Graphics; 2 3 Bitmap bmp = new Bitmap(this.Width, this.Height); 4 Graphics g = Graphics.FromImage(bmp); 5 6 paintcall.Increment(); 7 8 Rectangle r = new Rectangle(0, 0, this.Width, this.Height); 9 g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);1011 g2.DrawImage(bmp, new Point(0, 0));1213 g.Dispose();14 g = null;1516 bmp.Dispose();17 bmp = null;看上面第6行,这句会把paint call增加一。当然,其他方法有很多,这里不写了。好,跑一下perfmon,然后把我们新增加的counter add上,嗯,可以看到当窗口无效的时候,计数器就增加了。有一个小的细节,当窗口稍微改动大小的时候,你会发现Paint被调用了多次,这个实在很郁闷。so,稍微做点手脚:
1 private bool resize = false; 2 private void Form1_ResizeEnd(object sender, EventArgs e) 3 { 4 resize = false; 5 this.Invalidate(); 6 } 7 8 private void Form1_ResizeBegin(object sender, EventArgs e) 9 {10 resize = true;11 }然后我们修改一下Paint事件的代码如下:
1 private void Form1_Paint(object sender, PaintEventArgs e) 2 { 3 if (true == resize) return; 4 5 Graphics g2 = e.Graphics; 6 7 Bitmap bmp = new Bitmap(this.Width, this.Height); 8 Graphics g = Graphics.FromImage(bmp); 910 paintcall.Increment();1112 Rectangle r = new Rectangle(0, 0, this.Width, this.Height);13 g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);1415 g2.DrawImage(bmp, new Point(0, 0));1617 g.Dispose();18 g = null;1920 bmp.Dispose();21 bmp = null;22 }注意第三行,我们判断,如果在resize过程中,那么就直接返回。这样,虽然界面像白板一样,但是却少了很多Paint操作,从性能上会好不少。 ...[
阅读全文]