|
ListView でプロセスを表示する (その1)
|
開発環境: Visual Studio 2003次のような機能のForm アプリケーションを作る。
- プロセスの詳細情報を1秒ごとに ListView に表示する。
補足: ここでは、
System.Diagnostics.Process.GetProcessesを使用しているが、フォーマンスカウンターを使うほうが、お作法として正しい使い方
です。
注意: ListView では、先頭のカラムしか編集ができない。(SubItems は編集できない。)
詳細は、Visual Studio のヘルプを見てください。
回避策は、やろうとしていることによりますが、
1、データベースを使う。
2、行を選択したイベントを拾って、編集用のダイアログを出して、そこで修正する。
3、DataGrid を使ったリスト表示→結構めんどくさい。
4、Excel をインストールしてあるのなら、Excel の SpreadSheet ActiveX コントロールを貼り付ける。→Excel
があるのなら、それを使ったほうが早いんじゃない?
ってところですかねぇ。
作り方
1. フォームに ツールボックスより、ListView を貼り付ける。
2. フォームに ツールボックスより、タイマーを貼り付ける。
3. Form、Timer、ListView のプロパティを次のようにセットする。
Formのプロパティ
プロパティ | 値 |
Text | Process ListView |
ListView のプロパティ
プロパティ | 値 |
Dock | Fill |
Timerのプロパティ
プロパティ | 値 |
Enabled | True |
Interval | 1000 |
4. Timer のプロパティより、Tick イベントに OnTick をタイプすると、自動的にイベントが追加され、コードが表示される。
あとは、イベント発生時に、ListView を更新するための AddProcesses() を呼び出す。
private void OnTick(object sender, System.EventArgs e)
{
AddProcesses();
}
5. ListView の設定を行う。
this.listView1.View = View.Details; //
カラムのタイトル行を表示する。これが気が付かない。
this.listView1.AllowColumnReorder = true; // カラムの移動を可能にする。
this.listView1.GridLines = true; // グリッドラインを表示する。
this.listView1.Sorting = SortOrder.Ascending; // 第1カラムでの昇順とする。
6. カラムを追加する。
this.listView1.Columns.Clear(); // 一応、クリアしておく。
this.listView1.Columns.Add("ProcessName", 50, HorizontalAlignment.Left); //
カラムの追加。
this.listView1.Columns.Add("Id", 50, HorizontalAlignment.Right); // カラムの追加。
--- 省略 ---
7. タイマーで呼ばれたら、行を表示する。
// ちらつきを抑えるために、BeginUpdate()を呼ぶ。
this.listView1.BeginUpdate();
// プロセスの情報を得る。
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();
// 各プロセスごとに、ListViewItemをアロケートする。
ListViewItem[] items = new ListViewItem[processes.Length];
for (int i = 0; i < processes.Length; i++)
{
// 各ListViewItem にプロセスの情報をAdd していく。
items[i] = new ListViewItem(processes[i].ProcessName);
items[i].SubItems.Add(processes[i].Id.ToString());
--- 省略 ---
}
// ListViewItems をクリアする。
this.listView1.Items.Clear();
// AddRange でまとめて ListViewItems を追加する。
this.listView1.Items.AddRange(items);
// EndUpdate() で表示を再開する。
this.listView1.EndUpdate();
メモ:
- BeginUpdate(), EndUpdate() を使っても、ちらつきは発生し、ほとんど効果がない。
- AddRange() ではなく、Add でも、ほとんど性能的に問題なかった。この程度のリストの数では、問題にならないのかも。
- 毎回、new ListViewItem をしていて、問題ないかと思い、ListViewItem
を使いまわすようにしてみたが、ほとんど性能的(使用メモリサイズ、パフォーマンス)に大差なし。内部でバッファリングしてるのではないか。何も考えずに、MSのサンプルどおりに組んでも問題なさそう。
- このプログラムは、かなりリソース(VMで、20MB)を食います。この程度で、こんなにくっちゃって大丈夫なのか?
- 標準では、任意の行でソートができない。それ用のインターフェースが用意されている。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace ListView
{
/// <summary>
/// Form1 の概要の説明です。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.Timer timer1;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Windows フォーム デザイナ サポートに必要です。
//
InitializeComponent();
//
// TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
//
InitListView();
}
/// <summary>
/// 使用されているリソースに後処理を実行します。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.listView1 = new System.Windows.Forms.ListView();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// listView1
//
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(292, 266);
this.listView1.TabIndex = 0;
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.OnTick);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.listView1});
this.Name = "Form1";
this.Text = "Process ListView";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void InitListView()
{
this.listView1.View = View.Details;
this.listView1.AllowColumnReorder = true;
this.listView1.GridLines = true;
this.listView1.Sorting = SortOrder.Ascending;
this.listView1.Columns.Clear();
this.listView1.Columns.Add("ProcessName", 50, HorizontalAlignment.Left);
this.listView1.Columns.Add("Id", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("BasePriority", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("HandleCount", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("Threads", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("StartTime", 50, HorizontalAlignment.Left);
this.listView1.Columns.Add("PrivilegedProcessorTime", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("TotalProcessorTime", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("UserProcessorTime", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("VirtualMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PeakVirtualMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PeakWorkingSet", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("WorkingSet", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PagedMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PeakPagedMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PrivateMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("NonpagedSystemMemorySize", 50, HorizontalAlignment.Right);
this.listView1.Columns.Add("PagedSystemMemorySize", 50, HorizontalAlignment.Right);
}
private void AddProcesses()
{
this.listView1.BeginUpdate();
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();
ListViewItem[] items = new ListViewItem[processes.Length];
for (int i = 0; i < processes.Length; i++)
{
items[i] = new ListViewItem(processes[i].ProcessName);
items[i].SubItems.Add(processes[i].Id.ToString());
items[i].SubItems.Add(processes[i].BasePriority.ToString());
items[i].SubItems.Add(processes[i].HandleCount.ToString());
items[i].SubItems.Add(processes[i].Threads.Count.ToString());
items[i].SubItems.Add(processes[i].StartTime.ToString("T"));
items[i].SubItems.Add(processes[i].PrivilegedProcessorTime.ToString());
items[i].SubItems.Add(processes[i].TotalProcessorTime.ToString());
items[i].SubItems.Add(processes[i].UserProcessorTime.ToString());
items[i].SubItems.Add( (processes[i].VirtualMemorySize/1024/1024).ToString() + " MB");
items[i].SubItems.Add( (processes[i].PeakVirtualMemorySize/1024/1024).ToString() + " MB");
items[i].SubItems.Add( (processes[i].PeakWorkingSet/1024/1024).ToString() + " MB");
items[i].SubItems.Add( (processes[i].WorkingSet/1024/1024).ToString() + " MB");
items[i].SubItems.Add( (processes[i].PagedMemorySize/1024).ToString() + " kB");
items[i].SubItems.Add( (processes[i].PeakPagedMemorySize/1024).ToString() + " kB");
items[i].SubItems.Add( (processes[i].PrivateMemorySize/1024).ToString() + " kB");
items[i].SubItems.Add( (processes[i].NonpagedSystemMemorySize/1024).ToString() + " kB");
items[i].SubItems.Add( (processes[i].PagedSystemMemorySize/1024).ToString() + " kB");
}
this.listView1.Items.Clear();
this.listView1.Items.AddRange(items);
this.listView1.EndUpdate();
}
private void OnTick(object sender, System.EventArgs e)
{
AddProcesses();
}
}
}