C#封装类似任务管理器CPU使用记录图
在逛CodeProject的時候,偶然發現了一個老外寫的代碼,里面有一個自定義的用戶控件,類似任務管理器里面CPU使用記錄的圖表,如下截圖:
因為自己之前沒有做過這樣的圖表,覺得很贊,所以將這個用戶控件給摳了下來,做了一個小的demo,接下來我就分析下這個用戶控件的實現過程。
先看代碼:
/// <summary> /// Summary description for UsageHistoryControl. /// </summary> public class UsageHistoryControl : UserControl {/// <summary> /// Required designer variable./// </summary>private Container components = null;private const int squareWidth = 12;private const int maxLastValuesCount = 2000;private const int shiftStep = 3;private int shift = 0;private int [] lastValues1 = new int[maxLastValuesCount];private int [] lastValues2 = new int[maxLastValuesCount];private int nextValueIndex;private int lastValuesCount;private int max = 100;private int min = 0;public UsageHistoryControl(){// This call is required by the Windows.Forms Form Designer. InitializeComponent();EnableDoubleBuffering();Reset();}public void Reset(){lastValues1.Initialize();lastValues2.Initialize();nextValueIndex = 0;lastValuesCount = 0;Invalidate();}/// <summary> /// Clean up any resources being used./// </summary>protected override void Dispose( bool disposing ){if( disposing ){if(components != null){components.Dispose();}}base.Dispose( disposing );}#region Component Designer generated code/// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor./// </summary>private void InitializeComponent(){// // UsageHistoryControl// this.BackColor = System.Drawing.Color.Black;this.Name = "UsageHistoryControl";}#endregionprivate void EnableDoubleBuffering(){// Set the value of the double-buffering style bits to true.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint,true);UpdateStyles();}protected override void OnResize(EventArgs e){// Invalidate the control to get a repaint. Invalidate();}//在任何需要引發Paint事件時,都會執行這個方法,如大小變動,invalidate()等 protected override void OnPaint(PaintEventArgs e){Graphics g = e.Graphics;for(int i = 0; i <= ClientRectangle.Width+squareWidth; i += squareWidth){g.DrawLine(Pens.Green, i-shift, 0, i-shift, ClientRectangle.Height);}for(int i = 0; i < ClientRectangle.Height; i += squareWidth){g.DrawLine(Pens.Green, 0, i, ClientRectangle.Width, i);}int startValueIndex = (nextValueIndex-1+maxLastValuesCount)%maxLastValuesCount;int prevVal1 = GetRelativeValue(lastValues1[startValueIndex]);int prevVal2 = GetRelativeValue(lastValues2[startValueIndex]);for(int i = 1; i < lastValuesCount; ++i){int index = nextValueIndex - 1 - i;if (index < 0){index += maxLastValuesCount;}int val1 = GetRelativeValue(lastValues1[index]);int val2 = GetRelativeValue(lastValues2[index]);g.DrawLine(Pens.Red,ClientRectangle.Width - (i - 1) * shiftStep, ClientRectangle.Height - prevVal2,ClientRectangle.Width - i * shiftStep, ClientRectangle.Height - val2);g.DrawLine(Pens.LawnGreen,ClientRectangle.Width-(i-1)*shiftStep, ClientRectangle.Height-prevVal1,ClientRectangle.Width-i*shiftStep, ClientRectangle.Height-val1);prevVal1 = val1;prevVal2 = val2;}}private int GetRelativeValue(int val){int result = val * (ClientRectangle.Height-2) / max + 1;return result;}public void AddValues(int val1,int val2){lastValues1[nextValueIndex] = val1;lastValues2[nextValueIndex] = val2;nextValueIndex++;nextValueIndex %= maxLastValuesCount;lastValuesCount++;if (lastValuesCount > maxLastValuesCount){lastValuesCount = maxLastValuesCount;}shift += shiftStep;//shift %= squareWidth; shift = shift % squareWidth; Invalidate();}public int Maximum{get{return max;}set{// Make sure that the maximum value is never set lower than the minimum value.if (value < min){min = value;}max = value;// Invalidate the control to get a repaint. Invalidate();}}}注意到構造函數中的方法“EnableDoubleBuffering() ”,它的作用是啟用GDI+的雙緩沖,可以有效防止界面在重繪的時候發生閃爍。關于雙緩沖的介紹可以參考這里:http://www.cnblogs.com/bnuvincent/archive/2009/08/04/1538484.html,http://blog.csdn.net/gisfarmer/article/details/4366707。另一個方法Reset() 就是初始化一些變量,不過其中值得一提的就是”值類型的默認構造函數“,這個大家平時可能很少見,最多的就是引用類型的構造函數,比喻說類。
具體實現畫線的方法就是重寫了基類的OnPaint方法,因為在實現雙緩沖的時候必須要重寫這個方法。該方法先是重繪原生的界面,上面沒有任何的線條,然后在更具傳進來的參數畫線,不過這里
for(int i = 1; i < lastValuesCount; ++i){}感覺不是很好,隨著lastValuesCount的值越來越大,每次循環的次數就越來越多了,因為從未做過類似的事情,不知畫圖是不是真的這樣?
具體調用就很簡單了,因為要實現類似CPU那樣的使用記錄,所以在調用界面上拖了一個時間控件,在該控件的Tick事件里面傳值
private void timer1_Tick(object sender, EventArgs e) {Random rand = new Random(); this.usageHistoryControl1.AddValues(rand.Next(100),rand.Next(50,100)); }哦,原來這個圖是這樣實現的,想當初學習GDI+的時候,就怎么沒有想到做一個這樣的Demo了?
老外文章地址:http://www.codeproject.com/Articles/7933/Smart-Thread-Pool?
示例代碼下載:http://files.cnblogs.com/wucj/DrawLine.rar
?
轉載于:https://www.cnblogs.com/wucj/archive/2013/05/30/3106106.html
總結
以上是生活随笔為你收集整理的C#封装类似任务管理器CPU使用记录图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android面试小结
- 下一篇: [转载] 七龙珠第一部——第070话 五