WinForm自定义ListBox显示样式,多列分不同颜色显示,效果如下图:
首先向winForm窗口拖入一个ListBox控件,命名为lstConsole,同时将DrawMode设置为:OwnerDrawFixed,这里一定要注意否则我们接下来的工作都不会起作用。
然后我们来自定义ListBoxItem,代码如下:
public class ColoredListBoxItem
{
/// <summary>
/// creates a new ColoredListBoxItem
/// </summary>
/// <param name="prefix">the prefix which will be used</param>
/// <param name="text">the real message</param>
/// <param name="color">the color of both</param>
public ColoredListBoxItem(DateTime time, string prefix, string text, Color color)
{
Time = time;
Text = text;
Prefix = prefix;
TextColor = color;
}
/// <summary>
/// the real message
/// </summary>
public DateTime Time { get; set; }
/// <summary>
/// the prefix of the text
/// </summary>
public string Prefix { get; set; }
/// <summary>
/// the real message
/// </summary>
public string Text { get; set; }
/// <summary>
/// the color of the message
/// </summary>
public Color TextColor { get; set; }
}
public enum LogType
{
/// <summary>
/// OpenVPN changed the internal state.l
/// </summary>
Created,
/// <summary>
/// The management interface wants to say something.
/// </summary>
Changed,
/// <summary>
/// A "normal" message is logged by OpenVPN via Management Interface.
/// </summary>
Deleted,
/// <summary>
/// A debug message is sent. This is primary for internal usage.
/// </summary>
Renamed
}
接下来,切换到事件,向lstConsole添加DrawItem事件:lstConsole_DrawItem,代码如下:
private void lstConsole_DrawItem(object sender, DrawItemEventArgs e)
{
// just in case the list is empty...
if (e.Index == -1)
return;
// prefixes are drawed bold
Font prefixFont = new Font(e.Font, FontStyle.Bold);
ColoredListBoxItem li = (ColoredListBoxItem)((ListBox)sender).Items[e.Index];
Brush br = new SolidBrush(li.TextColor);
// calculate the width of the longest time
int timeWidth = (int)e.Graphics.MeasureString(" " + new DateTime(2222, 12, 22, 22, 22, 22, 222, CultureInfo.CurrentCulture.Calendar, DateTimeKind.Local).ToString(), prefixFont, e.Bounds.Width, StringFormat.GenericDefault).Width;
// calculate the width of the longest prefix
int prefixWidth = (int)e.Graphics.MeasureString(" [Management]", prefixFont, e.Bounds.Width, StringFormat.GenericDefault).Width;
// prepare the prefix
string prefix = "";
switch (li.Prefix)
{
case "Created":
prefix = "[创建文件] ";
break;
case "Changed":
prefix = "[修改文件] ";
break;
case "Deleted":
prefix = "[删除文件] ";
break;
case "Renamed":
prefix = "[重命名文件] ";
break;
default:
break;
}
e.DrawBackground();
Rectangle newBounds = new Rectangle(e.Bounds.Location, e.Bounds.Size);
// draw the time
e.Graphics.DrawString(li.Time.ToString(), prefixFont, br, newBounds, StringFormat.GenericDefault);
// calculate the new rectangle
newBounds.X += timeWidth;
newBounds.Width -= timeWidth;
// draw the prefix
e.Graphics.DrawString(prefix, prefixFont, br, newBounds, StringFormat.GenericDefault);
// calculate the new rectangle
newBounds.X += prefixWidth;
newBounds.Width -= prefixWidth;
// draw the text
e.Graphics.DrawString(
li.Text, e.Font, br, newBounds.X, newBounds.Y,
StringFormat.GenericDefault);
// draw the focus
e.DrawFocusRectangle();
}
最后一步,向ListBox添加Item显示的数据:
public void AddLog(LogType prefix, string text)
{
if (lstConsole.InvokeRequired)
{
try
{
//lstConsole.BeginInvoke(new UtilsHelper.Action<LogType, string>(AddLog), prefix, text);
}
catch (ObjectDisposedException)
{
}
return;
}
Color rowColor;
switch (prefix)
{
case LogType.Created:
rowColor = Color.Green;
break;
case LogType.Changed:
rowColor = Color.DarkBlue;
break;
case LogType.Deleted:
rowColor = Color.Brown;
break;
default: // e.g. State
rowColor = Color.Black;
break;
}
lstConsole.BeginUpdate();
if (lstConsole.Items.Count == 2048)
lstConsole.Items.RemoveAt(0);
lstConsole.Items.Add(new ColoredListBoxItem(DateTime.Now, prefix.ToString(), text, rowColor));
int h = lstConsole.ClientSize.Height - lstConsole.Margin.Vertical;
int i = lstConsole.Items.Count - 1;
while (h >= 0 && i > 0)
{
int nh = lstConsole.GetItemHeight(i);
if (nh > h)
break;
else
{
h -= nh;
i--;
}
}
lstConsole.TopIndex = i;
lstConsole.EndUpdate();
}
展示效果软件下载地址:下载Windows文件监视器