Reputation: 2899
I created a custom multiline ListBox control inherited from ListBox. In the form, the ListBox position is above a WPF rounded and transparent panel hosted in an ElementHost. Now, what I want, is that ListBox backcolor to be transparent. Obviously, this is not allowed in Winforms, a ListBox cant be transparent. Then, I have tried some things, but there is always an issue.
What I want to achieve is this:
As you can see, this works perfectly, but actually I´m having two problems.
The first I get is when I select an item. The letters became pretty ugly. Just compare the next image with the first one. You can see all of them looks ugly because all of them were selected.
The second problem I have, is when I scroll down/up the ListBox. The transparent color just dissapears and I get a black color.
I remember getting this issue with a scrollable panel in a Form. The panel was transparent and the way to solve it was to call Invalidate() method in the panel Scroll event. But I don´t have that event in the ListBox.
Also, I want to hide the scrollbar but to be scrollable.
I attach the CustomListBox code so you can see what I have done. You are free to take it if you want a simple multiline ListBox too.
Just in case, the way that I used to set the ListBox to transparent, was by overriding CreateParams.
public class 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);
}
}
}
}
Oh, I almost forget. I tried overriding the OnPaintBackGround(), it worked by setting SetStyle to userPaint. But it was even more undesirable, because I was not just having the same problems as the other solution, but also the text was not showed, so, I sticked to the first solution.
Hope somebody can help me out!
Upvotes: 0
Views: 5578
Reputation: 42229
You could try this...
protected override void OnPaintBackground(PaintEventArgs pevent)
{
IntPtr hdc = pevent.Graphics.GetHdc();
Rectangle rect = this.ClientRectangle;
NativeMethods.DrawThemeParentBackground(this.Handle, hdc, ref rect);
pevent.Graphics.ReleaseHdc(hdc);
}
internal static class NativeMethods
{
[DllImport("uxtheme", ExactSpelling = true)]
public extern static Int32 DrawThemeParentBackground(IntPtr hWnd, IntPtr hdc, ref Rectangle pRect);
}
Its worked for me when I've needed to paint a transparent background color for a control that did not support it. I used it with a TabControl.
Upvotes: 2