I am developing a project that needs to look like the attached screenshot.
I have a WinForm with VideoPanelCtl panel on top of it. The panel's handle is passed to the instantiated VLC component/control that results in video displayed on that panel.
I also tried to put another panel on top of the VideoPanelCtl at the upper end of the video panel and make it transparent and the controls that are sitting on top of this top panel also should have transparent background as shown in attached screenshot. However, my approach did not work despite that I used a a custom panel derived from panel control with bkg repainting (see code below) The panel that I was creating in code like this simply was obscured by the video...and if I had put controls on it (buttons and labels) they probably would be obscured too...
I call this from form's Load handler of the WinForm:
private void InitTopPanel()
{
mExtendedPanelTop = new ExtendedPanel();
mExtendedPanelTop.Opacity = 50; // totally transparent
videoPanelCtl.Controls.Add(mExtendedPanelTop);
mExtendedPanelTop.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
mExtendedPanelTop.Dock = System.Windows.Forms.DockStyle.Top;
mExtendedPanelTop.Location = new System.Drawing.Point(0, 0);
mExtendedPanelTop.Name = "ExtendedPanelTop";
mExtendedPanelTop.Size = new System.Drawing.Size(1090, 48);
mExtendedPanelTop.TabIndex = 0;
//mExtendedPanelTop.Paint += mExtendedPanelTop_Paint;
}
public class ExtendedPanel : Panel
{
private const int WS_EX_TRANSPARENT = 0x20;
public ExtendedPanel()
{
SetStyle(ControlStyles.Opaque, true);
}
private int opacity = 50;
//[DefaultValue(50)]
public int Opacity
{
get
{
return this.opacity;
}
set
{
if (value < 0 || value > 100)
throw new ArgumentException("value must be between 0 and 100");
this.opacity = value;
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
protected override void OnPaint(PaintEventArgs e)
{
using (var brush = new SolidBrush(Color.FromArgb(this.opacity * 255 / 100, this.BackColor)))
{
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
base.OnPaint(e);
}
}
How do I achieve the controls on top of video that sit on transparent panel and also have transparent background?
How do I achieve semi-transparent label on top of video with text (red label background) that says "Video Connection Lost"? (see attached)
I resolved it by using WPF control that contains the Canvas and the Canvas containing MediaElement and Label (or other controls). Then setting ZIndex of Label higher to cause visibility. Thus, I get visible label on running video (within MediaElement) with Label having transparent background.
Related
I am adding a new way to distinguish the user privileges in my program.
It is a small circular panel that appears after the username and that changes color depending on its privileges and that is shown after the user nick leaving a spacing of 5 pixels
:
private void SetNick(string nick)
{
this.NickLabel.Text = nick;
this.NickLabel.Left = ((this.ProfilePicturePanel.ClientSize.Width - this.NickLabel.Width) / 2) - 5;
Hector.Framework.Utils.Ellipse.Apply(this.BadgePanel, 6);
this.BadgePanel.Top = this.NickLabel.Top + 3;
this.BadgePanel.Left = this.NickLabel.Width + this.BadgePanel.Width + 5;
}
The nick of the user has a minimum of 3 characters and a maximum of 6 characters, then when the nickname has 6 characters (example: Jhon S), the panel is aligned correctly:
But if the nickname have 3 characters (example: Ben), then this happens:
It is assumed that the panel should always be shown near the label leaving a space of 5 pixels even if the label changes its content.
Could you tell me what I'm doing wrong?
You can override the Label Control and write your own implementation that draws your badge directly in the Label. Here's a simple example.
public class LabelWithBadge : Label
{
public Color BadgeColor { get; set; }
private Size BadgeSize { get; set; }
public LabelWithBadge()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
if (BadgeColor == null)
BadgeColor = Color.Red;
if (BadgeSize == null)
BadgeSize = new Size(20, 20);
}
protected override Size SizeFromClientSize(Size clientSize)
{
var textSize = TextRenderer.MeasureText("doesn't matter", this.Font);
this.BadgeSize = new Size(textSize.Height, textSize.Height);
var baseSize = base.SizeFromClientSize(clientSize);
return new Size(baseSize.Width + BadgeSize.Width, baseSize.Height);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillEllipse(new SolidBrush(this.BadgeColor), this.ClientSize.Width - this.BadgeSize.Width, 0, this.BadgeSize.Width, this.BadgeSize.Height);
}
}
By overriding SizeFromClientSize you can control the AutoSize ability of the label, and pad it to make room for your badge.
If you want to support manual sizing for the badge, then you'll need to tweak this to work with AutoSize off.
Then I set Styles on the control to handle painting. Overriding OnPaint allows you to draw in the extra padded on in the SizeFromClientSize override.
I added a property for the Badge Color. The Badge Size is determined by the font on the control using TextRenderer.MeasureText. So if you make the font bigger, the badge get's bigger with it.
This control will show up in your Toolbox when you build. Then you can use it like any other label but this one has a badge in it.
I'm trying to create a program within winForm in C# where an image will follow the mouse outside the application.
I have no clue how to draw an image outside of the form, let alone have it follow the mouse. My solution was going to be - create a borderless form and have the it follow the mouse - but this solution will not work because I cannot move a form via code.
The mouse needs to be able to click and function independently from this image.
How would I go about doing this?
it must do so without changing the way the mouse is used.
Set WS_EX_TRANSPARENT for the extended styles to make your form ignore mouse clicks. Set TopMost to True and Opacity to something less than 100% to make it semi-transparent. Move your form with a Timer. Something like:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Opacity = .5;
this.TopMost = true;
this.BackColor = Color.Yellow;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
// Makes the form circular:
System.Drawing.Drawing2D.GraphicsPath GP = new System.Drawing.Drawing2D.GraphicsPath();
GP.AddEllipse(this.ClientRectangle);
this.Region = new Region(GP);
}
const int WS_EX_TRANSPARENT = 0x20;
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Point pt = Cursor.Position;
pt.Offset(-1 * this.Width / 2, -1 * this.Height / 2);
this.Location = pt;
}
}
check this thread :
How to drag and move winform using mouse
seems you want to do something like this.
Hope this helps!
I'm working on ImageButton, in which I paint every state(i've got several images for each state) of this button (like mouseOver, mouseDown etc.).
I've made control transparent using this code:
public ImageButton()
{
InitializeComponent();
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
}
protected override CreateParams CreateParams
{
get
{
CreateParams parms = base.CreateParams;
parms.ExStyle |= 0x20;
return parms;
}
}
But there's a problem, after few switches of state, corners becoming sharp and ugly, to solve this problem I need to clear background, but if my control is transparent then it's impossible.
I've tried this solution: Clearing the graphics of a transparent panel C#
but it's slow and makes control flickering.
Do you have any ideas how to clear this background and keep transparency of control?
Ok, I've solved this problem.
I've worked around it by setting control as not transparent and I draw canvas which is under my control, as background of my ImageButton.
Solution (in Paint event):
//gets position of button and transforms it to point on whole screen
//(because in next step we'll get screenshot of whole window [with borders etc])
Point btnpos = this.Parent.PointToScreen(new Point(Location.X, Location.Y));
//now our point will be relative to the edges of form
//[including borders, which we'll have on our bitmap]
if (this.Parent is Form)
{
btnpos.X -= this.Parent.Left;
btnpos.Y -= this.Parent.Top;
}
else
{
btnpos.X = this.Left;
btnpos.Y = this.Top;
}
//gets screenshot of whole form
Bitmap b = new Bitmap(this.Parent.Width, this.Parent.Height);
this.Parent.DrawToBitmap(b, new Rectangle(new Point(0, 0), this.Parent.Size));
//draws background (which simulates transparency)
e.Graphics.DrawImage(b,
new Rectangle(new Point(0, 0), this.Size),
new Rectangle(btnpos, this.Size),
GraphicsUnit.Pixel);
//do whatever you want to draw your stuff
PS. It doesn't work in designtime.
What is the easiest way to make a transparent overlay over the elements in my form?
I wish to make a simple black (with opacity = 0.5) overlay for my form and activate it if my application is doing something (like a fadescreen).
Thank you.
You can create a transparent control by inherit a control you want use
a Tranparent Panel example :
class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return createParams;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
SolidBrush brush = new SolidBrush(Color.FromArgb(100, 0, 0, 0));
e.Graphics.FillRectangle(brush,0,0,this.Width,this.Height);
}
}
And Use this after form laded.s:
void Form1_Load(object sender, EventArgs e)
{
TransparentPanel overlay = new TransparentPanel();
overlay.BackColor = Color.FromArgb(50, Color.Black);
overlay.Width = this.Width;
overlay.Height = this.Height;
this.Controls.Add(overlay);
overlay.BringToFront();
}
The easiest is to override the application OnPaint method, and inside it add the following lines:
if( doingSomething )
{
using( SolidBrush brush = new SolidBrush( Color.FromArgb(128, 0, 0, 0)))
{
e.Graphics.FillRectangle( brush, 0, 0, width, height );
}
}
Then, at the place in code when your doing something, set doingSomething to true, and call Invalidate. When the work is complete, set doingSomething to false, and call Invalidate again.
Have you tried adding a semi-transparent control to your form that covers the entire form area? Have the control dock to the entire form, so that it resizes with the form. Make sure it is topmost in the Z-order, so that all the other controls are rendered below it.
I am trying to extend the System.Windows.Forms.Label class to support vertically drawn text. I do this by creating a new property called MyLabelOrientation that the user can set to Horizontal or Vertical. When the user changes this setting, the values for width and height are swapped to resize the control to its new orientation. Finally, I override the OnPaint function to draw my Label.
I would like to extend the AutoSize property for this control as well so that my Label will auto-size to the text it contains. For the horizontal orientation, the base functionality implements this for me. For the vertical orientation, I create a Graphics object and set the height of the control to the width of the SizeF object returned from Graphics.MeasureString(Text, Font). You can see an example of the code I'm using below.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;
public class MyLabel : Label
{
public enum MyLabelOrientation {Horizontal, Vertical};
protected MyLabelOrientation m_orientation = MyLabelOrientation.Horizontal;
[Category("Appearance")]
public virtual MyLabelOrientation Orientation
{
get { return m_orientation; }
set
{
m_orientation = value;
int temp = Height;
Width = Height;
Height = temp;
Refresh();
}
}
private Size ResizeLabel()
{
Graphics g = Graphics.FromHwnd(this.Handle);
SizeF newSize = g.MeasureString(Text, Font);
if (m_orientation == MyLabelOrientation.Horizontal)
Width = (int)newSize.Width;
else
Height = (int)newSize.Width;
}
protected override void OnPaint(PaintEventArgs e)
{
Brush textBrush = new SolidBrush(this.ForeColor);
if (m_orientation == LabelOrientation.Vertical)
{
e.Graphics.TranslateTransform(Width, 0);
e.Graphics.RotateTransform(90);
e.Graphics.DrawString(Text, Font, textBrush, Padding.Left, Padding.Top);
}
else
{
base.OnPaint(e);
}
}
}
However, setting AutoSize to true seems to prevent and/or override any changes to the size of the control. This means that I can't change the width or height when I want to change the Label's orientation. I'm wondering if this behavior can be overridden, so that I can test whether AutoSize is set, and then adjust the size of the control according to it's orientation.
I know this a a pretty old question, but i stumbled across it today and was wondering how to do the same thing.
My solution to the problem was overriding the GetPreferredSize(Size proposedSize) method. I used a button class that houses an arrow in addition to the text which, of course, was not taken into account using the AutoSize property so i added additional space and it works fine for me.
Given the problem of changing orientation or switching width and height, you could completely change the way the preferred size is calculated.
public override Size GetPreferredSize(Size proposedSize)
{
Size s = base.GetPreferredSize(proposedSize);
if (AutoSize)
{
s.Width += 15;
}
return s;
}
I have not done this before, I believe you can theoretically override a property declaration (via the new keyword) and check the orientation before proceeding:
override public bool AutoSize
{
set
{
if( /* orientation is horizontal */ )
{
base.AutoSize = value;
}
else
{
// do what you need to do
}
}
}
If think a solution is to override OnResize itself :
protected override void OnResize(EventArgs e)
{
if (AutoSize)
{
// Perform your own resizing logic
}
else
OnResize(e);
}