打造自己的ListBox

baihe_591 2008-07-11 08:33:42
因为要做个播放器,用listbox来显示歌曲列表,但是vs自带的listbox实在难看极了,于是自己重新绘制listbox如下:

public class MyList : ListBox
{
public MyList()
{
DrawMode = DrawMode.OwnerDrawFixed;
//this.BackColor = Color.Black;
this.BorderStyle = BorderStyle.None;
}

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs pe)
{
pe.DrawBackground(); //画背景
pe.DrawFocusRectangle(); //画边框
Rectangle bounds = pe.Bounds;

Color ForColor = Color.CadetBlue;//文字颜色
// Check whether the index is valid

if (pe.Index % 2 != 0)
{

}

if (pe.Index >= 0 && pe.Index < Items.Count)
{
object item = this.Items[pe.Index]; //取得需要绘制项的引用
int iOffset = 0;
iOffset += 5;

if (pe.State !=DrawItemState .None&&pe .State !=DrawItemState.Focus )
{
pe.Graphics.DrawRectangle(Pens.YellowGreen, bounds);//绘制边框
using (Brush b = new SolidBrush(System.Drawing.Color .Blue ))
{
pe.Graphics.FillRectangle(b, pe.Bounds);//填充矩形
}

GraphicsPath path = new GraphicsPath();
int x = bounds.X;
int y = bounds.Y;
Point[] Points ={ new Point(0+x, 0+y), new Point(5+x, 5+y), new Point(0+x, 10+y), new Point(0+x, 0+y) };
path.AddLines(Points);
pe.Graphics.DrawPath(Pens.Blue, path);//绘制三角
pe.Graphics.FillPath(Brushes.Green , path);//填充三角

ForColor = System.Drawing.SystemColors.HighlightText;//文字突出显示颜色
}
pe.Graphics.DrawString(item.ToString (), pe.Font, new SolidBrush(ForColor ), bounds.Left + iOffset, bounds.Top); //根据项的颜色绘制文本
}
base.OnDrawItem(pe);
}
}
}


但是问题来了:大家可以调试一下,就会发现当按顺序选择mylistbox的项时一切正常,但不按顺序选择,或从下向上选择时会出现所选项的下边框,这是为什么呢? 同样绘制三角的边框,为什么就没有这种情况?
...全文
308 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
EdsionWang 2008-07-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 baihe_591 的回复:]
12楼,13楼的方法是没办法的办法,我也试过,只是出现这种原因是什么呢?
另外,如果有一个窗体此时覆盖了listboxex的话,再移走窗体,会有listboxex部分文字消失的现象,该怎么解决呢?
[/Quote]

重写onpaint函数 当窗体最大化(小)化或其他窗体覆盖住的话,窗体会重新绘制,先前画的那些form没记住 好像是这么一说~~
panwen516 2008-07-12
  • 打赏
  • 举报
回复
学习了
JeffChung 2008-07-12
  • 打赏
  • 举报
回复
帮你顶一下,接个分——画东西不擅长|||
baihe_591 2008-07-12
  • 打赏
  • 举报
回复
多谢LSD各位朋友,现在重新修改了下,看起来和千千的差不多了,就是滚动条不知道怎么修改,期望有人相助,
代码共享:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace mylistbox
{
public class ListBoxEx : ListBox
{
public int[] PlayIndex;
public bool ShowTriangle;
public bool ShowNumber;

public ListBoxEx()
{
DrawMode = DrawMode.OwnerDrawFixed;

SetStyle(ControlStyles.DoubleBuffer, true);
this.BackColor = Color.Black;
this.BorderStyle = BorderStyle.None;
}

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs pe)
{
// pe.DrawFocusRectangle(); //画边框

if (pe.Index >= 0 && pe.Index < Items.Count)
{
pe.DrawBackground(); //画背景
Rectangle bounds = pe.Bounds;
Color ForColor = Color.FromArgb(0, 130, 255); //文字颜色
Color NumColor = Color.FromArgb(0, 130, 0);//数字颜色
Color SelectedColor = SystemColors.HighlightText;//选中时的颜色
Color TriangleColor = Color.Lime;//三角的颜色
Pen p = Pens.Black;
object item = this.Items[pe.Index]; //取得需要绘制项的引用
int iOffset = 0;
if (pe.Index % 2 != 0)
{
using (Brush b = new SolidBrush(Color.FromArgb(32, 32, 32)))
{
pe.Graphics.FillRectangle(b, bounds);//绘制背景颜色;
}
}

if ((pe.State & DrawItemState.Selected) == DrawItemState.Selected)
{

using (LinearGradientBrush b = new LinearGradientBrush(bounds, Color.FromArgb(49, 105, 206), Color.FromArgb(0, 8, 0), LinearGradientMode.Vertical))
{
pe.Graphics.FillRectangle(b, pe.Bounds);//填充矩形
}
ForColor = SelectedColor;
NumColor = SelectedColor;
TriangleColor = SelectedColor;
p = Pens.White;
// pe.Graphics.DrawRectangle(p, bounds);

}
pe.Graphics.DrawRectangle(p , bounds);//绘制边框

if (Array .IndexOf ( this.PlayIndex,pe.Index)>=0)
{
if (ShowTriangle)
{
GraphicsPath path = new GraphicsPath();
int x = bounds.X;
int y = bounds.Y;

Point[] Points ={ new Point(0 + x, 2 + y), new Point(4 + x, 5 + y), new Point(0 + x, 8 + y), new Point(0 + x, 2 + y) };
path.AddLines(Points);
// pe.Graphics.DrawPath(Pens.Blue, path);//绘制三角
using (Brush b = new SolidBrush(TriangleColor))
{
pe.Graphics.FillPath(b, path);//填充三角
}
}
ForColor = TriangleColor;//文字突出显示颜色
NumColor = TriangleColor;
}

if (ShowNumber)
{
using (Brush b = new SolidBrush(NumColor))
{
pe.Graphics.DrawString((pe.Index + 1).ToString().PadLeft(3) + ".", pe.Font, b, bounds.Left + iOffset, bounds.Top);
}
iOffset += 20;
}

using (Brush b = new SolidBrush(ForColor))
{
pe.Graphics.DrawString(item.ToString(), pe.Font, b, bounds.Left + iOffset + 3, bounds.Top); //根据项的颜色绘制文本
}
}
base.OnDrawItem(pe);
}
}
}
viki117 2008-07-11
  • 打赏
  • 举报
回复
有意思,还没有重画过控件呢。。学习学习
jackynt 2008-07-11
  • 打赏
  • 举报
回复
收录了!~
wzuomin 2008-07-11
  • 打赏
  • 举报
回复
Rectangle.Inflate 方法 (Int32, Int32)-->将此 Rectangle 放大指定量

参数
width:此 Rectangle 的水平放大量。
height:此 Rectangle 的垂直放大量。

备注
此方法放大此矩形,而不是放大它的副本。沿轴放大是沿两个方向(正方向和负方向)进行的。例如,如果 50 x 50 的矩形沿 x 轴放大 50,则结果矩形的长度为 150 个单位,即原始 50,负方向 50,正方向 50,以保持矩形的几何中心不变。

如果 x 或 y 为负数,则 Rectangle 结构沿着相应的方向缩小。

baihe_591 2008-07-11
  • 打赏
  • 举报
回复
5楼, r.Inflate(0, -1);放大-1倍,这样的话,那就不能显示出边框来了.
wzuomin 2008-07-11
  • 打赏
  • 举报
回复

public class MyList : ListBox
{
public MyList()
{
DrawMode = DrawMode.OwnerDrawFixed;
//this.BackColor = Color.Black;
this.BorderStyle = BorderStyle.None;
}

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs pe)
{
pe.DrawBackground(); //画背景
pe.DrawFocusRectangle(); //画边框
Rectangle bounds = pe.Bounds;

Color ForColor = Color.CadetBlue;//文字颜色
// Check whether the index is valid

if (pe.Index % 2 != 0)
{

}

if (pe.Index >= 0 && pe.Index < Items.Count)
{
object item = this.Items[pe.Index]; //取得需要绘制项的引用
int iOffset = 0;
iOffset += 5;

if (pe.State !=DrawItemState .None&&pe .State !=DrawItemState.Focus )
{
Rectangle r = bounds;
r.Inflate(0, -1);//--------------------------------------------> 注意:这儿做了修改
pe.Graphics.DrawRectangle(Pens.YellowGreen, r);//绘制边框
using (Brush b = new SolidBrush(System.Drawing.Color .Blue ))
{
pe.Graphics.FillRectangle(b, r);//填充矩形
}

GraphicsPath path = new GraphicsPath();
int x = bounds.X;
int y = bounds.Y;
Point[] Points ={ new Point(0+x, 0+y), new Point(5+x, 5+y), new Point(0+x, 10+y), new Point(0+x, 0+y) };
path.AddLines(Points);
pe.Graphics.DrawPath(Pens.Blue, path);//绘制三角
pe.Graphics.FillPath(Brushes.Green , path);//填充三角

ForColor = System.Drawing.SystemColors.HighlightText;//文字突出显示颜色
}
pe.Graphics.DrawString(item.ToString (), pe.Font, new SolidBrush(ForColor ), bounds.Left + iOffset, bounds.Top); //根据项的颜色绘制文本
}
base.OnDrawItem(pe);
}
}
LiloZhu 2008-07-11
  • 打赏
  • 举报
回复
板凳我来坐
baihe_591 2008-07-11
  • 打赏
  • 举报
回复
沉的这么快,自己顶.
baihe_591 2008-07-11
  • 打赏
  • 举报
回复
沙发自己坐
lovefootball 2008-07-11
  • 打赏
  • 举报
回复
边框的问题是FillRectangle和DrawRectangle引起的
他们所指的长宽并不一样

DrawRectangle ( Pens.Black, 0,0, 5,4);
最终会得到长为6个象素宽为5个象素的矩形框。

比如说你想上下的边框都显示出来
那么应该这样
pe.Graphics.FillRectangle(new SolidBrush(System.Drawing.Color.SkyBlue), bounds);
pe.Graphics.DrawRectangle(Pens.Red, new Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height - 1));
如果都不显示出来
pe.Graphics.DrawRectangle(Pens.Red, new Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height - 1));
pe.Graphics.FillRectangle(new SolidBrush(System.Drawing.Color.SkyBlue), bounds);

至于部分字符被遮盖
我没这种情况
我很懒 2008-07-11
  • 打赏
  • 举报
回复
public class MyList : ListBox
{
public MyList()
{
DrawMode = DrawMode.OwnerDrawFixed;
//this.BackColor = Color.Black;
this.BorderStyle = BorderStyle.None;
}

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs pe)
{
pe.DrawBackground(); //画背景
pe.DrawFocusRectangle(); //画边框
Rectangle bounds = pe.Bounds;

Color ForColor = Color.CadetBlue;//文字颜色
// Check whether the index is valid

if (pe.Index % 2 != 0)
{

}

if (pe.Index >= 0 && pe.Index < Items.Count)
{
object item = this.Items[pe.Index]; //取得需要绘制项的引用
int iOffset = 0;
iOffset += 5;

if (pe.State !=DrawItemState .None&&pe .State !=DrawItemState.Focus )
{
Rectangle r = bounds;
r.Inflate(0, -1);//--------------------------------------------> 注意:这儿做了修改
pe.Graphics.DrawRectangle(Pens.YellowGreen, r);//绘制边框
using (Brush b = new SolidBrush(System.Drawing.Color .Blue ))
{
pe.Graphics.FillRectangle(b, r);//填充矩形
}

GraphicsPath path = new GraphicsPath();
int x = bounds.X;
int y = bounds.Y;
Point[] Points ={ new Point(0+x, 0+y), new Point(5+x, 5+y), new Point(0+x, 10+y), new Point(0+x, 0+y) };
path.AddLines(Points);
pe.Graphics.DrawPath(Pens.Blue, path);//绘制三角
pe.Graphics.FillPath(Brushes.Green , path);//填充三角

ForColor = System.Drawing.SystemColors.HighlightText;//文字突出显示颜色
}
pe.Graphics.DrawString(item.ToString (), pe.Font, new SolidBrush(ForColor ), bounds.Left + iOffset, bounds.Top); //根据项的颜色绘制文本
}
base.OnDrawItem(pe);
}
}

gdi
lalac 2008-07-11
  • 打赏
  • 举报
回复
原因是GDI+在DrawingRectangle是包括右边线的,例如Rectangle(0,0,1,1)画出来是4个像素点,显然它包括右边线!lz在从上到下选择时,绘制过程先画上面的item,然后下面的,下面的会盖住上一个item画出来的边,所以看不见边线!当从下到上选择时,绘制过程有一些改变(lz输出pe.Index即可知道)导致不能覆盖掉下边线!
baihe_591 2008-07-11
  • 打赏
  • 举报
回复
12楼,13楼的方法是没办法的办法,我也试过,只是出现这种原因是什么呢?
另外,如果有一个窗体此时覆盖了listboxex的话,再移走窗体,会有listboxex部分文字消失的现象,该怎么解决呢?
zhnzzy 2008-07-11
  • 打赏
  • 举报
回复
可否对Items.Count 进行 FOREACH

object item = this.Items[pe.Index]; //取得需要绘制项的引用
如果不为该项,先擦掉边框
lovefootball 2008-07-11
  • 打赏
  • 举报
回复
if (pe.State !=DrawItemState .None&&pe .State !=DrawItemState.Focus)
加个else


else
{
pe.Graphics.DrawRectangle(Pens.White, bounds);
}

把你刚才画的得擦掉
GhostAdai 2008-07-11
  • 打赏
  • 举报
回复
先顶了再试
yilanwuyu123 2008-07-11
  • 打赏
  • 举报
回复
mark

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧