背景:公司經常會需要將日志信息,輸出到一個對話框中顯示出來。之前一直采用的listbox控件,操作簡單,使用方便,但是遺憾的是,不能自由控制每一行的狀態。
於是想了如下幾個方案:
(1)重繪listbox的OnDrawItem函數,這個難度比較大,一頓操作之后,發現實現不了,於是放棄
(2)給每個listbox添加DrawItem事件,這個比較簡單,網上也有很多例子。但是針對每個listbox都需要添加相應的事件,操作麻煩且沒有通用性。
(3)於是想到了第三個辦法,也是最終實現的方法,換成ListView控件
具體實現過程
1.在ListView的默認狀態下,輸出一行數據,發現會自動換行,將LabelWrap設置為False即可解決
2.當然,選中的時候,我們也希望是一行數據,所以可以將FullRowSelect設置為True。
3.接下來就是嘗試Listview控件的view屬性了,需要自己不斷的嘗試,才能找到最好的結果
(1)LargeImage和SmallImage,看似可以正常使用,但是如果字體大小不一樣的話,會將每一行數據自動排列(放棄)
(2)list,只有橫向滾動條。放棄
(3)tile,不能增加橫向滾動條,放棄
(4)最終只有detail有可能達到我們想要的目的
4.在detail下,第一次插入一行數據,會發現數據根本不顯示,原因是因為在detail模式下,需要增加一列才可以顯示。
5.然后會發現每次更改字體的大小什么的,標題欄也會隨之改動,非常的難看,於是將HeaderStyle設置為None,即可將其隱藏起來。
6.因為ListviewItem的寬度固定,如果文字長度較長,會變成省略號,所以就需要計算當前文字的寬度。基本算法如下
Graphics g = Graphics.FromImage(new Bitmap(1, 1)); SizeF s = g.MeasureString(strMessage, font);
其中strMessage為輸出的字符串,font為設置的字體,此方法需要用到GDI+的簡單只是,因為需要new一個對象,所以建立一個小的即可。
7.關鍵算法如下
1 ListViewItem lvi = new ListViewItem(); 2 3 lvi.Font = font; 4 lvi.ForeColor = color; 5 lvi.Text = strMessage; 6 7 Graphics g = Graphics.FromImage(new Bitmap(1, 1)); 8 SizeF s = g.MeasureString(strMessage, font); 9 10 if (s.Width > listView.Columns[0].Width) 11 { 12 listView.Columns[0].Width = (int)s.Width + 10; 13 } 14 15 listView.Invoke((EventHandler)(delegate 16 { 17 listView.Items.Insert(0, lvi); 18 19 listView.Font = lvi.Font; 20 21 22 23 int nCount = listView.Items.Count; 24 if (nCount >= 50) 25 { 26 listView.Items.RemoveAt(nCount - 1); 27 } 28 }));
8.最終的實現結果如下:

