我创建了一个继承自 ListBox 的自定义多行 ListBox 控件。在表单中,ListBox 位置位于 ElementHost 中托管的 WPF 圆形透明面板上方。现在,我想要的是 ListBox 背景色是透明的。显然,这在 Winforms 中是不允许的,ListBox 不能是透明的。然后,我尝试了一些东西,但总是有一个问题。
我想要实现的是:
如您所见,这非常有效,但实际上我遇到了两个问题。
我得到的第一个是当我选择一个项目时。字母变得非常难看。只需将下一张图片与第一张图片进行比较。你可以看到它们看起来都很丑,因为它们都被选中了。
我遇到的第二个问题是当我向下/向上滚动 ListBox 时。透明的颜色消失了,我得到了黑色。
我记得在表单中使用可滚动面板遇到了这个问题。面板是透明的,解决方法是在面板滚动事件中调用 Invalidate() 方法。但我在 ListBox 中没有该事件。
另外,我想隐藏滚动条但可以滚动。
我附上了 CustomListBox 代码,这样你就可以看到我做了什么。如果您也想要一个简单的多行 ListBox,您可以随意使用它。
以防万一,我用来将 ListBox 设置为透明的方式是重写 CreateParams。
公共类 MultiLineListBox : System.Windows.Forms.ListBox { public MultiLineListBox() { this.DrawMode = DrawMode.OwnerDrawVariable; this.ScrollAlwaysVisible = true; }
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
if(Site!=null)
return;
if(e.Index > -1)
{
string s = Items[e.Index].ToString();
SizeF sf = e.Graphics.MeasureString(s,Font,Width);
int htex = (e.Index==0) ? 15 : 10;
e.ItemHeight = (int)sf.Height + htex;
e.ItemWidth = Width;
}
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
if(Site!=null)
return;
if(e.Index > -1)
{
string s = Items[e.Index].ToString();
if((e.State & DrawItemState.Focus)==0)
{
e.Graphics.DrawString(s,Font,new SolidBrush(Color.White),e.Bounds);
e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255, 26, 36, 41)),e.Bounds);
}
else
{
e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255, 0, 185, 57)), e.Bounds);
//e.Graphics.DrawString(s,Font,new SolidBrush(Color.FromArgb(255, 0, 161, 47)),e.Bounds);
}
}
}
}
哦,我差点忘了。我尝试覆盖 OnPaintBackGround(),它通过将 SetStyle 设置为 userPaint 来工作。但这更不可取,因为我不仅遇到了与其他解决方案相同的问题,而且没有显示文本,所以我坚持第一个解决方案。
希望有人可以帮助我!