How can you create a C# Winforms control which goes out of the bounds of its region? Such as a drop down box. Kind of like if you had a DropDownBox in a Small Sized Panel.
Windows Forms doesn't support windows like that well, it is pretty fundamentally incompatible with the designer. Here's some code to get you started. You can't use this control in the designer, it must be created at run-time. You also must call its Dispose() method yourself.
using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
public class MyListBox : ListBox {
private Control mParent;
private Point mPos;
private bool mInitialized;
public MyListBox(Control parent) {
mParent = parent;
mInitialized = true;
this.SetTopLevel(true);
parent.LocationChanged += new EventHandler(parent_LocationChanged);
mPos = mParent.Location;
}
public new Point Location {
get { return mParent.PointToClient(this.Location); }
set {
Point zero = mParent.PointToScreen(Point.Empty);
base.Location = new Point(zero.X + value.X, zero.Y + value.Y);
}
}
protected override Size DefaultSize {
get {
return mInitialized ? base.DefaultSize : Size.Empty;
}
}
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
if (this.mInitialized)
base.SetBoundsCore(x, y, width, height, specified);
}
void parent_LocationChanged(object sender, EventArgs e) {
base.Location = new Point(base.Left + mParent.Left - mPos.X, base.Top + mParent.Top - mPos.Y);
mPos = mParent.Location;
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
if (mParent != null && !DesignMode) {
cp.Style = (int)(((long)cp.Style & 0xffff) | 0x90200000);
cp.Parent = mParent.Handle;
Point pos = mParent.PointToScreen(Point.Empty);
cp.X = pos.X;
cp.Y = pos.Y;
cp.Width = base.DefaultSize.Width;
cp.Height = base.DefaultSize.Height;
}
return cp;
}
}
}
I did something similiar to that recently, and I used a ListBox. The cool think about a listbox, is that you can display it anywhere you want to, even out of bounds of your control. That way, when you detect via a button click or whatever, that you need to display the DropDown that you want, just populate the ListBox and display it anywhere you want. I got the idea from here:
http://msdn.microsoft.com/en-us/library/aa480727.aspx
They show how to build a Custom DataGridView with filtering, and to display the filter values, they place a ListBox under the header cell.
There is a good article here:
http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp
This has a class which handles some of the tricky aspects of getting this to work correctly, such as keeping the application window titlebar active, handling Alt-Tab and cancelling with a mouse click.
Related
I'm using 3 ListBox Controls and I want to remove their Scrollbars, so they're appearance may looking cleaner.
I have it so when I select an item in any, it selects the same in the rest. Only problem is that I have no idea how to make them scroll together.
E.g., if I scrolled down in the first Listbox, the position of the other two should match the position of the the first one.
I'd also like to know how to remove the Scrollbar, since there is no property for this.
Here's an example of a ListBox stripped of its Vertical ScrollBar that can handle Mouse Wheel messages and scroll itself.
The Vertical ScrollBar is removed by default, unless the ScrollAlwaysVisible property is set to true or the custom public VerticalScrollBar property is set to true.
The LisBox is scrolled setting its TopIndex property. There's a Min/Max check in WndProc where WM_MOUSEWHEEL is handled that ensures that the list is not scrolled beyond its limits.
It's kind of a redundant check, but may come in handy if you needs to be perform a more complex calculation to determine the current offset.
When the ListBox is scrolled, it raises the custom public Scroll event. You could create a custom EventArgs class to pass specific values to the Event Handler, if required. Here, I'm just synchronizing all ListBox Controls using the TopIndex property.
Note that the Mouse Wheel scrolls the ListBox by 1 Item, while also pressing SHIFT sets the scroll to 3 Items. Modify this behavior as required.
using System.ComponentModel;
using System.Windows.Forms;
[DesignerCategory("code")]
public class ListBoxEx : ListBox
{
public event EventHandler<EventArgs> Scroll;
private const int WS_VSCROLL = 0x200000;
private const int WM_MOUSEWHEEL = 0x020A;
private const int MK_SHIFT = 0x0004;
private bool m_VerticalScrollBar = false;
public ListBoxEx() { }
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
if (!ScrollAlwaysVisible && !m_VerticalScrollBar) {
cp.Style &=~WS_VSCROLL;
}
return cp;
}
}
[DefaultValue(false)]
public bool VerticalScrollBar {
get => m_VerticalScrollBar;
set {
if (value != m_VerticalScrollBar) {
m_VerticalScrollBar = value;
RecreateHandle();
}
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg) {
case WM_MOUSEWHEEL:
var wparm = m.WParam.ToInt64();
int button = (short)wparm;
int delta = (int)(wparm >> 16);
int direction = Math.Sign(delta);
int steps = button == MK_SHIFT ? 3 : 1;
TopIndex = Math.Max(Math.Min(Items.Count - 1, TopIndex - (steps * direction)), 0);
Scroll?.Invoke(this, EventArgs.Empty);
m.Result = IntPtr.Zero;
break;
}
}
}
Add three instances of this Custom Control to a Form and subscribe to the SelectedIndexChanged event of the first one (for example). E.g.,
private void listBoxEx1_SelectedIndexChanged(object sender, EventArgs e)
{
var lb = (sender as ListBox);
if (listBoxEx2.Items.Count > lb.SelectedIndex) {
listBoxEx2.SelectedIndex = lb.SelectedIndex;
}
if (listBoxEx3.Items.Count > lb.SelectedIndex) {
listBoxEx3.SelectedIndex = lb.SelectedIndex;
}
}
Now, if you want to sync-scroll the three Controls, subscribe to the custom Scroll event of the first:
private void listBoxEx1_Scroll(object sender, EventArgs e)
{
var lb = sender as ListBox;
listBoxEx2.TopIndex = lb.TopIndex;
listBoxEx3.TopIndex = lb.TopIndex;
}
This is how it works:
The code sample also handles ListBox Controls with different number of Items
Edit:
How to use:
ListBoxEx is a Custom Control class.
To create this Control:
Add a new Class file to the Project, name it ListBoxEx.
Overwrite the class definition in that file with the class content you find here.
Add on top the 2 using directives you find in this code.
Build the Project.
Now, in the ToolBox, you can find the new ListBoxEx Control.
To replicate what is shown here:
Drop 3 instances of it onto a Form.
In the designer, select the first object (listBoxEx1).
In the PropertyGrid, switch to the events (⚡) view. Find the Scroll and SelectedIndexChanged events and double-click each. It will create the event handlers for you.
Copy the content of the event handler you find here inside the new event handlers just created.
Or, subscribe to the events in code:
Copy the listBoxEx1_Scroll and listBoxEx1_SelectedIndexChanged handlers you find here (including their content) and paste them inside the Form that contains the ListBoxEx Controls.
Add this to the Form Constructor, after InitializeComponent(), to subscribe to the Scroll and SelectedIndexChanged events of listBoxEx1:
listBoxEx1.Scroll += this.listBoxEx1_Scroll;
listBoxEx1.SelectedIndexChanged += this.listBoxEx1_SelectedIndexChanged;
I am trying to make an application that is drawing Dendrograms like this one.
So I added a PictureBox to the winform, and for start, I wanted to wrote all labels like in the picture with this code:
foreach (var line1 in lines)
{
i++;
gpx.DrawString(line1, myFont, Brushes.Green, new PointF(2, 10 * i));
}
But the problem is that I have a lot of labels so it writes only a few of them on 800x600 px. I wanted to add scrolling bars, but it doesn't work at all. It works only when I am setting an Image to PictureBox.
Is there any other way, with or without PictureBox?
PictureBox is a very simple control, it is only good to display a picture. The one capability it doesn't have that you need is the ability to scroll the content. So don't use it.
Creating your own control is very simple in Winforms. A basic starting point is to begin with Panel, a control that supports scrolling, and derive your own class for it so you customize it to be suitable for the task. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto a form. Note how you can set the Lines property, either with the designer or your code. Use the Paint event to draw the dendrogram. Or extend the OnPaint() method in the class, you can make it as fancy as you want.
using System;
using System.Drawing;
using System.Windows.Forms;
class DendrogramViewer : Panel {
public DendrogramViewer() {
this.DoubleBuffered = this.ResizeRedraw = true;
this.BackColor = Color.FromKnownColor(KnownColor.Window);
}
public override System.Drawing.Font Font {
get { return base.Font; }
set { base.Font = value; setSize(); }
}
private int lines;
public int Lines {
get { return lines; }
set { lines = value; setSize(); }
}
private void setSize() {
var minheight = this.Font.Height * lines;
this.AutoScrollMinSize = new Size(0, minheight);
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
base.OnPaint(e);
}
}
Why can't I set the BackColor of a Label to Transparent? I have done it before, but now it just don't want to...
I created a new UserControl, added a progressbar and a label to it. When I set the BackColor of the label to transparent it is still gray =/ Why is this?
What I wanted was to have the label on top of the progressbar so that its text was "in" the progressbar...
Add a new class to your project and post the code shown below. Build. Drop the new control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
public class TransparentLabel : Label {
public TransparentLabel() {
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
}
protected override CreateParams CreateParams {
get {
CreateParams parms = base.CreateParams;
parms.ExStyle |= 0x20; // Turn on WS_EX_TRANSPARENT
return parms;
}
}
}
WinForms doesn't really support transparent controls, but you can make a transparent control yourself. See my answer here.
In your case you should probably subclass the progress bar and override the OnPaint method to draw a text on the progress bar.
Most simple solution is following:
Set background color to transparency either in visual editor or in constructor of your form:
this.label1.BackColor = System.Drawing.Color.Transparent;
Set Parent property of your label to control that you want to be visible behind the text. This can be done in form constructor or in Load method:
this.label1.Parent = progressBar1;
Its true that this is not true transparency as in DirectX. The result you see on display is composed only from two layers. You cant sum up more than two layers with this approach (each layer having its own transparency defined by alpha parameter). But its suitable for many practical situations you can encounter in Winforms programming.
Use a LinkLabel not a normal Label
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel)
{
this.MakeTransparentLabel(LinkLabel, Color.White);
}
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel, Color ForeColor)
{
LinkLabel.ForeColor = ForeColor;
LinkLabel.LinkColor = ForeColor;
LinkLabel.VisitedLinkColor = ForeColor;
LinkLabel.ActiveLinkColor = ForeColor;
LinkLabel.DisabledLinkColor = ForeColor;
LinkLabel.LinkArea = new LinkArea(0, 0);
LinkLabel.LinkBehavior = LinkBehavior.NeverUnderline;
LinkLabel.Cursor = Cursors.Arrow;
LinkLabel.BackColor = Color.Transparent;
}
private void SetTransparentLabelText(System.Windows.Forms.LinkLabel LinkLabel, string Text)
{
if (string.IsNullOrEmpty(Text)) { LinkLabel.Text = " "; return; }
LinkLabel.Text = Text;
}
This is a very simple solution and works great:
public class MyLabel : Label
{
private bool fTransparent = false;
public bool Transparent
{
get { return fTransparent; }
set { fTransparent = value; }
}
public MyLabel() : base()
{
}
protected override CreateParams CreateParams
{
get
{
if (fTransparent)
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
else return base.CreateParams;
}
}
protected override void WndProc(ref Message m)
{
if (fTransparent)
{
if (m.Msg != 0x14 /*WM_ERASEBKGND*/ && m.Msg != 0x0F /*WM_PAINT*/)
base.WndProc(ref m);
else
{
if (m.Msg == 0x0F) // WM_PAINT
base.OnPaint(new PaintEventArgs(Graphics.FromHwnd(Handle), ClientRectangle));
DefWndProc(ref m);
}
}
else base.WndProc(ref m);
}
}
When label backcolor is transparent, then label only takes picture of its underlying control the first time when it is created, after that label backcolor is constant. And each time when label repaints itself, it repaints to that fixed color or pattern.
Overriding CreateParams affects on how window for control will be created, this enables real transparency.
Overriding WndProc you control which messages should be passed to base class. We must filtrate WM_ERASEBKGND and WM_PAINT, but we also have to trigger paint event.
If you want to focus on designing your windows application, I suggest you use WPF.
Making controles transparent in WPF is very easy.
<TextBox Width="200" Height="40" Opacity="0.5"/>
Here is a transparent control I wrote a while ago which displays rotated text. Most of the code comes from here, though IIRC I had to make a few tweaks to get it to work.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;
namespace MyNamespace
{
public partial class RotatedText : UserControl
{
private readonly Timer _invalidationTimer;
private const int WS_EX_TRANSPARENT = 0x00000020;
public RotatedText()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
InitializeComponent();
_invalidationTimer = new Timer {Interval = 500, Enabled = true};
_invalidationTimer.Tick += TickHandler;
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Appearance")]
[Description("Text which appears in control")]
public string Text { get; set; }
#region Transparent background
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TRANSPARENT;
return cp;
}
}
private void TickHandler(object sender, EventArgs e)
{
InvalidateEx();
}
private void InvalidateEx()
{
if (Parent != null)
Parent.Invalidate(Bounds, false);
else
Invalidate();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Intentionally do nothing - stops background from drawing
//base.OnPaintBackground(e);
}
#endregion
//Rotate text and draw
protected override void OnPaint(PaintEventArgs e)
{
double angleRadians = Math.Atan2(Height, Width);
float angleDegrees = -1*(float) (angleRadians*180/Math.PI);
angleDegrees *= 0.9f;
e.Graphics.RotateTransform(angleDegrees, MatrixOrder.Append);
e.Graphics.TranslateTransform(20, Height - 75, MatrixOrder.Append);
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
Font font = new Font("Ariel", 50);
e.Graphics.DrawString(Text, font, Brushes.Gray, 1, 2); //Shadow
e.Graphics.DrawString(Text, font, Brushes.Red, 0, 0);
}
}
}
So as the comment to my previous answer stated, Control is the default behaviour, and is what I remembered as being Transparent.
Anyway, have you tried setting the background property of your UserControl, or the container your label is in (Panel, Form, whatever?), your label should reflect that color :)
Old Answer:
Its been a while since I did winforms programming, but as I recall labels are transparent per default? thus its only the text that gets an actual color and the bacground color mimics whatever is behind it :)
It is possible to do exactly what you want to achieve. It just takes a little time to play with controls. It is possible to create a Label control with transparent background, and place it on top of Progressbar control.
Check my answer to another SO question.
as to an explanation for your problem, windows doesn't do transparency for background controls like you'd expect-i'm guessing the gray background is actually the form's surface. whatever controls are drawn between the form surface and your label are ignored.
Select BackColor, go the Web tab, and select Transparent. Generates the following.
this.label1.BackColor = System.Drawing.Color.Transparent;
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!
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.
Why can't I set the BackColor of a Label to Transparent? I have done it before, but now it just don't want to...
I created a new UserControl, added a progressbar and a label to it. When I set the BackColor of the label to transparent it is still gray =/ Why is this?
What I wanted was to have the label on top of the progressbar so that its text was "in" the progressbar...
Add a new class to your project and post the code shown below. Build. Drop the new control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
public class TransparentLabel : Label {
public TransparentLabel() {
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
}
protected override CreateParams CreateParams {
get {
CreateParams parms = base.CreateParams;
parms.ExStyle |= 0x20; // Turn on WS_EX_TRANSPARENT
return parms;
}
}
}
WinForms doesn't really support transparent controls, but you can make a transparent control yourself. See my answer here.
In your case you should probably subclass the progress bar and override the OnPaint method to draw a text on the progress bar.
Most simple solution is following:
Set background color to transparency either in visual editor or in constructor of your form:
this.label1.BackColor = System.Drawing.Color.Transparent;
Set Parent property of your label to control that you want to be visible behind the text. This can be done in form constructor or in Load method:
this.label1.Parent = progressBar1;
Its true that this is not true transparency as in DirectX. The result you see on display is composed only from two layers. You cant sum up more than two layers with this approach (each layer having its own transparency defined by alpha parameter). But its suitable for many practical situations you can encounter in Winforms programming.
Use a LinkLabel not a normal Label
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel)
{
this.MakeTransparentLabel(LinkLabel, Color.White);
}
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel, Color ForeColor)
{
LinkLabel.ForeColor = ForeColor;
LinkLabel.LinkColor = ForeColor;
LinkLabel.VisitedLinkColor = ForeColor;
LinkLabel.ActiveLinkColor = ForeColor;
LinkLabel.DisabledLinkColor = ForeColor;
LinkLabel.LinkArea = new LinkArea(0, 0);
LinkLabel.LinkBehavior = LinkBehavior.NeverUnderline;
LinkLabel.Cursor = Cursors.Arrow;
LinkLabel.BackColor = Color.Transparent;
}
private void SetTransparentLabelText(System.Windows.Forms.LinkLabel LinkLabel, string Text)
{
if (string.IsNullOrEmpty(Text)) { LinkLabel.Text = " "; return; }
LinkLabel.Text = Text;
}
This is a very simple solution and works great:
public class MyLabel : Label
{
private bool fTransparent = false;
public bool Transparent
{
get { return fTransparent; }
set { fTransparent = value; }
}
public MyLabel() : base()
{
}
protected override CreateParams CreateParams
{
get
{
if (fTransparent)
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
else return base.CreateParams;
}
}
protected override void WndProc(ref Message m)
{
if (fTransparent)
{
if (m.Msg != 0x14 /*WM_ERASEBKGND*/ && m.Msg != 0x0F /*WM_PAINT*/)
base.WndProc(ref m);
else
{
if (m.Msg == 0x0F) // WM_PAINT
base.OnPaint(new PaintEventArgs(Graphics.FromHwnd(Handle), ClientRectangle));
DefWndProc(ref m);
}
}
else base.WndProc(ref m);
}
}
When label backcolor is transparent, then label only takes picture of its underlying control the first time when it is created, after that label backcolor is constant. And each time when label repaints itself, it repaints to that fixed color or pattern.
Overriding CreateParams affects on how window for control will be created, this enables real transparency.
Overriding WndProc you control which messages should be passed to base class. We must filtrate WM_ERASEBKGND and WM_PAINT, but we also have to trigger paint event.
If you want to focus on designing your windows application, I suggest you use WPF.
Making controles transparent in WPF is very easy.
<TextBox Width="200" Height="40" Opacity="0.5"/>
Here is a transparent control I wrote a while ago which displays rotated text. Most of the code comes from here, though IIRC I had to make a few tweaks to get it to work.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;
namespace MyNamespace
{
public partial class RotatedText : UserControl
{
private readonly Timer _invalidationTimer;
private const int WS_EX_TRANSPARENT = 0x00000020;
public RotatedText()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
InitializeComponent();
_invalidationTimer = new Timer {Interval = 500, Enabled = true};
_invalidationTimer.Tick += TickHandler;
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Appearance")]
[Description("Text which appears in control")]
public string Text { get; set; }
#region Transparent background
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TRANSPARENT;
return cp;
}
}
private void TickHandler(object sender, EventArgs e)
{
InvalidateEx();
}
private void InvalidateEx()
{
if (Parent != null)
Parent.Invalidate(Bounds, false);
else
Invalidate();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Intentionally do nothing - stops background from drawing
//base.OnPaintBackground(e);
}
#endregion
//Rotate text and draw
protected override void OnPaint(PaintEventArgs e)
{
double angleRadians = Math.Atan2(Height, Width);
float angleDegrees = -1*(float) (angleRadians*180/Math.PI);
angleDegrees *= 0.9f;
e.Graphics.RotateTransform(angleDegrees, MatrixOrder.Append);
e.Graphics.TranslateTransform(20, Height - 75, MatrixOrder.Append);
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
Font font = new Font("Ariel", 50);
e.Graphics.DrawString(Text, font, Brushes.Gray, 1, 2); //Shadow
e.Graphics.DrawString(Text, font, Brushes.Red, 0, 0);
}
}
}
So as the comment to my previous answer stated, Control is the default behaviour, and is what I remembered as being Transparent.
Anyway, have you tried setting the background property of your UserControl, or the container your label is in (Panel, Form, whatever?), your label should reflect that color :)
Old Answer:
Its been a while since I did winforms programming, but as I recall labels are transparent per default? thus its only the text that gets an actual color and the bacground color mimics whatever is behind it :)
It is possible to do exactly what you want to achieve. It just takes a little time to play with controls. It is possible to create a Label control with transparent background, and place it on top of Progressbar control.
Check my answer to another SO question.
as to an explanation for your problem, windows doesn't do transparency for background controls like you'd expect-i'm guessing the gray background is actually the form's surface. whatever controls are drawn between the form surface and your label are ignored.
Select BackColor, go the Web tab, and select Transparent. Generates the following.
this.label1.BackColor = System.Drawing.Color.Transparent;