有時候我們使用ListBox元件會想要針對Item的新增、插入、與刪除做些反應,可能像是有個Item插入時我們會想把游標移到最下面之類的。但內建的ListBox並未將這樣的訊息開放出來,所以我們無法直接的去做這樣的處理,必須要自行去接收視窗訊息才行。

我們可以建立個控制項,繼承自ListBox,並視需要來接收想要處理的視窗訊息。像是想要偵測Item新增的話我們可以偵測LB_ADDSTRING、想要偵測Item插入的話可以偵測LB_INSERTSTRING、想要偵測Item刪除的話可以偵測LB_DELETESTRING。 private const int LB_ADDSTRING = 0x180; private const int LB_INSERTSTRING = 0x181; private const int LB_DELETESTRING = 0x182;

偵測時需覆寫WndProc方法,並在方法內判斷Msg是否是我們所感興趣的訊息。有的訊息會內含較為詳細的資訊,像是Item的索引與值,若有需要可從wparam與lparam中擷取。

		protected override void WndProc(ref Message m)
		{
			var itemIndex = 0;
			var itemValue = string.Empty;

			switch (m.Msg)
			{
				case LB_ADDSTRING:
					itemValue = Marshal.PtrToStringUni(m.LParam);
					OnItemAdded(EventArgs.Empty);
					break;
				case LB_INSERTSTRING:
					itemIndex = (int)m.WParam;
					itemValue = Marshal.PtrToStringUni(m.LParam);
					OnItemInserted(EventArgs.Empty);
					break;
				case LB_DELETESTRING:
					itemIndex = (int)m.WParam;
					OnItemDeleted(EventArgs.Empty);
					break;
				default:
					break;
			}
			base.WndProc(ref m);
		} 

這邊附上較為完整的測試範例:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;

namespace WindowsFormsApplication4 { public partial class Form1 : Form { class ListBoxEx : ListBox { #region Const private const int LB_ADDSTRING = 0x180; private const int LB_INSERTSTRING = 0x181; private const int LB_DELETESTRING = 0x182; #endregion

		#region Event
		public event EventHandler ItemAdded;
		public event EventHandler ItemInserted;
		public event EventHandler ItemDeleted;
		#endregion

		#region Protected Method
		protected void OnItemAdded(EventArgs e)
		{
			if (ItemAdded == null)
				return;
			ItemAdded(this, e);
		}

		protected void OnItemInserted(EventArgs e)
		{
			if (ItemInserted == null)
				return;
			ItemInserted(this, e);
		}

		protected void OnItemDeleted(EventArgs e)
		{
			if (ItemDeleted == null)
				return;
			ItemDeleted(this, e);
		}

		protected override void WndProc(ref Message m)
		{
			var itemIndex = 0;
			var itemValue = string.Empty;

			switch (m.Msg)
			{
				case LB_ADDSTRING:
					itemValue = Marshal.PtrToStringUni(m.LParam);
					OnItemAdded(EventArgs.Empty);
					break;
				case LB_INSERTSTRING:
					itemIndex = (int)m.WParam;
					itemValue = Marshal.PtrToStringUni(m.LParam);
					OnItemInserted(EventArgs.Empty);
					break;
				case LB_DELETESTRING:
					itemIndex = (int)m.WParam;
					OnItemDeleted(EventArgs.Empty);
					break;
				default:
					break;
			}
			base.WndProc(ref m);
		} 
		#endregion
	}

	#region Var
	private ListBoxEx _listBox; 
	#endregion

	#region Private Property
	private ListBoxEx m_ListBox
	{
		get
		{
			return _listBox ?? (_listBox = new ListBoxEx() 
			{
				Dock = DockStyle.Fill
			});
		}
	} 
	#endregion

	#region Constructor
	public Form1()
	{
		InitializeComponent();

		m_ListBox.ItemAdded += m_ListBox_ItemAdded;
		m_ListBox.ItemDeleted += m_ListBox_ItemDeleted;
		m_ListBox.ItemInserted += m_ListBox_ItemInserted;

		this.panel1.Controls.Add(m_ListBox);
	} 
	#endregion

	#region Event Process
	private void button1_Click(object sender, EventArgs e)
	{
		m_ListBox.Items.Add(Guid.NewGuid().ToString());
	}

	private void button2_Click(object sender, EventArgs e)
	{
		var index = m_ListBox.SelectedIndex >= 0 ? m_ListBox.SelectedIndex : 0;
		m_ListBox.Items.Insert(index, Guid.NewGuid().ToString());
	}

	private void button3_Click(object sender, EventArgs e)
	{
		if (m_ListBox.SelectedIndex == -1)
			return;
		m_ListBox.Items.RemoveAt(m_ListBox.SelectedIndex);
	}

	void m_ListBox_ItemInserted(object sender, EventArgs e)
	{
		lbxLog.Items.Add("Item inserted");
	}

	void m_ListBox_ItemDeleted(object sender, EventArgs e)
	{
		lbxLog.Items.Add("Item deleted");
	}

	void m_ListBox_ItemAdded(object sender, EventArgs e)
	{
		lbxLog.Items.Add("Item added");
	} 
	#endregion
}

}

運行後的結果如下,新增、插入、與刪除都能夠即時的偵測。

How to detect if items are added to a ListBox (or CheckedListBox) control

LB_ADDSTRING message (Windows)

LB_DELETESTRING message (Windows)

LB_INSERTSTRING message (Windows)