Loading

C# winfrom ListView控件实现自由设置每一行字体及背景色等

 

背景:公司经常会需要将日志信息,输出到一个对话框中显示出来。之前一直采用的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.最终的实现结果如下:

    

 

posted @ 2020-04-14 11:31  ligiggy  阅读(4604)  评论(0编辑  收藏  举报