I wanted my panel to be truly transparent, so I followed the instructions on this article: https://web.archive.org/web/20121226091810/http://www.bobpowell.net/transcontrols.htm
However, I've forced my panel to always show the Vertical scroll bar. It initially is not rendered unless I hover my mouse cursor over it, at which point it begins to appear. What more can be added to the above article to ensure that my panel's scrollbars are always visible, other than setting VerticalScroll.Visible to true?
Here is what I have so far for my custom Panel class. This is using C# .NET 4.0 in Visual Studio 2010:
public class SkinnedList : Panel
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return cp;
}
}
public SkinnedList()
{
AdjustFormScrollbars( true );
}
public new void AdjustFormScrollbars( bool visible )
{
VerticalScroll.Visible = true;
HorizontalScroll.Visible = false;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Do not render background
}
protected void InvalidateEx()
{
if( Parent != null )
{
Rectangle rc = new Rectangle( Location, Size );
Parent.Invalidate( rc, true );
}
}
}
That's the window style you picked. The control is transparent, meaning if not active it should blend in to the background, and only be interactive when needed.
Some suggestions, I don't know if any of them will work for your case:
Nest your transparent Panel in a normal Panel, and have the transparent one AutoSize itself to fit its contents. Then, the scrollbars will be on the containing Panel and will scroll the autosized, transparent Panel. This keeps the scrollbars always visible as needed, but may spoil your transparent effect.
Put your transparent Panel in a UserControl that has navigation buttons (up, down, pageup, pagedown, etc) that will trigger events on the transparent Panel (Scroll is the big one). This will require your transparent Panel to have handlers for the button click events, in which it will call its own OnScroll() method. This won't look like a standard scrollbar, and you won't be able to click and drag (unless you use a slider), but you can get around easily enough.
The InvalidateEx() method isn't correct, you need to map the rectangle from panel coordinates to parent coordinates. Like this:
protected void InvalidateEx() {
if (Parent != null) {
Rectangle rc = new Rectangle(0, 0, this.ClientSize.Width - SystemInformation.VerticalScrollBarWidth, this.ClientSize.Height);
rc = this.RectangleToScreen(rc);
rc = Parent.RectangleToClient(rc);
Parent.Invalidate(rc, false);
}
}
The best way to get the scroll bar is to use the AutoScrollMinSize property:
public SkinnedList() {
this.AutoScroll = true;
this.AutoScrollMinSize = new Size(0, 1000);
this.Scroll += delegate { this.InvalidateEx(); };
}
This should fix your problems, except one. You'll notice the effect of the "Show window content while dragging" system option. It is best described as 'doing the pogo'. No fix for this, you cannot reasonably turn the system option off. This just can't work well.
User contributions licensed under CC BY-SA 3.0