WinForms, picturebox's image overlapping custom painted drawings - c#

I have a custom user control with a picture box on it. Then, draw a circle on the control in Paint event.
var size = TextRenderer.MeasureText(this.UnreadCount.ToString(), lblDisplayname.Font);
var rec = new Rectangle(0, 0, size.Width, size.Width);
var smallFont = new Font(lblDisplayname.Font.Name, lblDisplayname.Font.Size - 1);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
format.LineAlignment = StringAlignment.Center;
using (LinearGradientBrush b = new LinearGradientBrush(
rec,
Color.FromArgb(242, 37, 37),
Color.FromArgb(178, 30, 30),
45F))
{
e.Graphics.FillEllipse(b, rec);
e.Graphics.DrawString(this.UnreadCount.ToString(), smallFont, Brushes.White, rec, format);
}
Then, later in the implementation, I set the image of the control's picture box.
MyControl ctrl = new MyControl();
ctrl.picImage.Image = Image.FromFile(imagePath);
ctrl.Refresh();
The issue is that: the picture box's image overlap the drawn circle.
current issue
Requirement is that: The circle is needed to display fully overlapping the image. What might be causing my issue?

The following fuction will return a user control with your requirements ,Posting the code for you to understand the parent child relationship.
Either the graphics has to be drawn on top of the image container or on another transparent container that is on top of the image.
The below sample has 2 panels ,panel1 and panel2 where panel 2 is a child of panel.
Panel1 is the background image and panel 2 has the graphics.Hope it helps.
private UserControl create_MyControl( string filenamepath)
{
//Create User Control
UserControl MyControl = new UserControl();
//Mention the size of control
MyControl.Size = new Size(100, 100);
//Create a panel to hold the background image that you wanted in the picture box
Panel panel1 = new Panel();
//dock the panel1 to fill the control background
panel1.Dock = DockStyle.Fill;
MyControl.Controls.Add(panel1);
//Create another panel as overlay for panel1
Panel panel2 = new Panel();
//dock the panel2 to fill the panel1;
panel2.Dock = DockStyle.Fill;
//Add panel2 as child of panel1
panel1.Controls.Add(panel2);
//Set panel2 background as transparent
panel2.BackColor = Color.Transparent;
// To replicate the variables that you have!
Label lblDisplayname = new Label();
lblDisplayname.Font = new Font("Arial", 24, FontStyle.Regular);
lblDisplayname.Size = panel2.Size;
lblDisplayname.TextAlign = ContentAlignment.TopCenter;
lblDisplayname.Text = "25";
lblDisplayname.Dock = DockStyle.Fill;
panel2.Controls.Add(lblDisplayname);
panel1.BackgroundImage = Image.FromFile(filenamepath);
panel1.BackgroundImageLayout = ImageLayout.Stretch;
//In Panel2 paint event put your code for stuff
panel2.Paint += (s, e) =>
{
var size = TextRenderer.MeasureText("Hello", lblDisplayname.Font);
var rec = new Rectangle(0, 0, size.Width, size.Width);
var smallFont = new Font(lblDisplayname.Font.Name, lblDisplayname.Font.Size - 1);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
format.LineAlignment = StringAlignment.Center;
using (System.Drawing.Drawing2D.LinearGradientBrush b = new System.Drawing.Drawing2D.LinearGradientBrush(
rec,
Color.FromArgb(242, 37, 37),
Color.FromArgb(178, 30, 30),
45F))
{
e.Graphics.FillEllipse(b, rec);
e.Graphics.DrawString("Hello", smallFont, Brushes.White, rec, format);
}
};
return MyControl;
}

Related

Styling Windows Form Tab

I am creating windows Tabbed Application. Everything is good but the tabs are quiet faded and borders are very dull. I have tried changing the border style to 3D as well but no effect. Below is the screenshot
There are forums where people have suggested to use third party library to make Google Chrome type tabs. But I want the native way to get beautiful tabs.
You can take control of how the tabs are drawn by setting the DrawMode = TabDrawMode.OwnerDrawFixed. The example below assumes you have a TabControl named tabControl1 on the form, this will add a new tab with a blue box.
private Rectangle myTabRect;
private Rectangle myInsideRect;
private Rectangle myOutsideRect;
public Form1()
{
InitializeComponent();
TabPage tabPage1 = new TabPage();
// Sets the tabs to be drawn by the parent window Form1.
// OwnerDrawFixed allows access to DrawItem.
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.Controls.Add(tabPage1);
tabControl1.Location = new Point(25, 25);
tabControl1.Size = new Size(250, 250);
tabPage1.TabIndex = 0;
myTabRect = tabControl1.GetTabRect(0);
myInsideRect = new Rectangle(tabControl1.DisplayRectangle.X -1, tabControl1.DisplayRectangle.Y -1, tabControl1.DisplayRectangle.Width + 1, tabControl1.DisplayRectangle.Height + 1);
myOutsideRect = tabControl1.ClientRectangle;
myOutsideRect.Width--;
myOutsideRect.Height--;
ClientSize = new Size(300, 500);
Controls.Add(tabControl1);
tabControl1.DrawItem += new DrawItemEventHandler(OnDrawItem);
}
private void OnDrawItem(object sender, DrawItemEventArgs e)
{
// Draw your tab graphics here
Graphics g = e.Graphics;
Pen p = new Pen(Color.Blue);
g.DrawRectangle(p, myTabRect);
p = new Pen(Color.Red);
g.DrawRectangle(p, myInsideRect);
p = new Pen(Color.Green);
g.DrawRectangle(p, myOutsideRect);
}
You can draw whatever style you like into the graphic context, add text, images, etc

How do I dynamically layer objects ontop of eachother in Windows Forms?

I'm using a FlowLayoutPanel to dynamically display an array of PictureBoxes and Labels. They're going in the order: PictureBox-Label-PictureBox-Label and so on. I need those labels to appear above each picture so they'll match, basically layring them ontop of picturebox margins. I tried using Controls.SetChildIndex(temp, 2); but it seem to just swap the postion of the picturebox. I also tried using temp.BringToFront(); but then all the pictureboxes being displayed at the top of the panel and all the labels are below (I need each label to match each picturebox above them). Here's the code:
public void RunMeta()
{
Label mostPickedLabel = new Label();
mostPickedLabel.Text = "Most picked heroes";
flowLayoutPanel1.Controls.Add(mostPickedLabel);
mostPickedLabel.Margin = new Padding(15, 0, 1000, 0);
mostPickedLabel.Font = new Font("Lucida Sans Unicode", 15);
mostPickedLabel.ForeColor = Color.DarkCyan;
mostPickedLabel.Size = new Size(200, 30);
foreach (var mostPickedHero in FetchDataFromDota2Site.MostUsedHeroesAndImages)
{
PictureBox temp = new PictureBox();
temp.ImageLocation = mostPickedHero.ImageSource;
temp.SizeMode = PictureBoxSizeMode.StretchImage;
temp.Left = temp.Width * flowLayoutPanel1.Controls.Count;
temp.Margin = new Padding(15, 30, 15, 30);
flowLayoutPanel1.Controls.Add(temp);
flowLayoutPanel1.AutoScroll = true;
Label heroName = new Label();
heroName.Text = mostPickedHero.MostPickedHeroName;
heroName.Font = new Font("Lucida Sans Unicode", 8);
heroName.ForeColor = Color.White;
flowLayoutPanel1.Controls.Add(heroName);
}
}

My code complies but doesn't show the ellipse in C#

So I am trying to make a red ellipse flash in the middle but for some reason my codes runs and complies but no ellipse is drawn
As you can see in the code part I have put the drawing part in the default constructor, I have also tried creating a private function that draws it and tried calling it in the default constructor but that didn't work either
using System;
using System.Drawing;
using System.Windows.Forms;
public class RedLuserinterface : Form
{
private Panel panelTop = new Panel();
private Panel panelMid = new Panel();
private Panel panelBot = new Panel();
private Label title = new Label();
private Button pauseBut = new Button();
private Button resumeBut = new Button();
private Button exitBut = new Button();
private Size minInterfaceSize = new Size(400, 600);
private Size maxInterfaceSize = new Size(400, 600);
public RedLuserinterface()
{ //Set the size of the user interface box.
MaximumSize = minInterfaceSize;
MinimumSize = maxInterfaceSize;
//Initialize text strings
Text = "Red Light Assignment";
title.Text = "Red Light Program";
pauseBut.Text = "Pause";
resumeBut.Text = "Resume";
exitBut.Text = "Exit";
//Set Sizes
Size = new Size(400, 600);
panelTop.Size = new Size(400, 30);
panelMid.Size = new Size(400, 160);
panelBot.Size = new Size(400, 50);
title.Size = new Size(120, 30);
pauseBut.Size = new Size(85, 30);
resumeBut.Size = new Size(85, 30);
exitBut.Size = new Size(85, 30);
//Set Locations
title.Location = new Point(140, 20);
panelTop.Location = new Point(0, 0);
panelMid.Location = new Point(0, 30);
panelBot.Location = new Point(0, 480);
pauseBut.Location = new Point(50, 500);
resumeBut.Location = new Point(40, 150);
exitBut.Location = new Point(250, 500);
//Add controls to the form
Controls.Add(title);
Controls.Add(panelTop);
Controls.Add(panelMid);
Controls.Add(panelBot);
Controls.Add(pauseBut);
Controls.Add(resumeBut);
Controls.Add(exitBut);
//Set Color
panelTop.BackColor = Color.Green;
panelMid.BackColor = Color.Blue;
panelBot.BackColor = Color.Yellow;
//Create solid brush and draw ellipse
SolidBrush redBrush = new SolidBrush(Color.Red);
Graphics circle = this.CreateGraphics();
circle.FillEllipse(redBrush, 0, 0, 200, 200);
//send some stuff to the back
panelTop.SendToBack();
panelMid.SendToBack();
panelBot.SendToBack();
pauseBut.Enabled = true;
resumeBut.Enabled = false;
exitBut.Click += new EventHandler(stoprun);
//dispose stuff
redBrush.Dispose();
circle.Dispose();
}
}
You need to paint your ellipse when the Form engine requires you to do it. The form engine will call the Paint event handler if you define one and will pass the Graphics object to use to paint the ellipse. So you should remove the lines in the form constructor and add the proper delegate for the Paint event, then in the Paint event draw the ellipse
public RedLuserinterface()
{
.....
// Remove these lines
// SolidBrush redBrush = new SolidBrush(Color.Red);
// Graphics circle = this.CreateGraphics();
// circle.FillEllipse(redBrush, 0, 0, 200, 200)
....
exitBut.Click += new EventHandler(stoprun);
this.Paint += onFormPaint;
// No more needed here
// redBrush.Dispose();
// circle.Dispose()
}
private void onFormPain(object sender, PaintEventArgs e)
{
SolidBrush redBrush = new SolidBrush(Color.Red);
e.Graphics.FillEllipse(redBrush, 50,250, 200, 200);
redBrush.Dispose();
}

Side-aligned tabs in tabcontrol

Since I'm a C# beginner I don't know what's to do in my case. I wanted a side-aligned tab control so I have found this:
https://msdn.microsoft.com/en-us/library/ms404305%28v=vs.110%29.aspx
Now the tabpage names are not getting displayed at all. How do I "draw" them? I hope someone can help me. The DrawItem method:
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
Brush _textBrush;
// Get the item from the collection.
TabPage _tabPage = tabControl1.TabPages[e.Index];
// Get the real bounds for the tab rectangle.
Rectangle _tabBounds = tabControl1.GetTabRect(e.Index);
if (e.State == DrawItemState.Selected)
{
// Draw a different background color, and don't paint a focus rectangle.
_textBrush = new SolidBrush(Color.Red);
g.FillRectangle(Brushes.Gray, e.Bounds);
}
else
{
_textBrush = new System.Drawing.SolidBrush(e.ForeColor);
e.DrawBackground();
}
// Use our own font.
Font _tabFont = new Font("Arial", (float)10.0, FontStyle.Bold, GraphicsUnit.Pixel);
// Draw string. Center the text.
StringFormat _stringFlags = new StringFormat();
_stringFlags.Alignment = StringAlignment.Center;
_stringFlags.LineAlignment = StringAlignment.Center;
g.DrawString(_tabPage.Text, _tabFont, _textBrush, _tabBounds, new StringFormat(_stringFlags));
}

How to align separator in ContextMenuStrip

Here is my code for ContextMenuStrip:
ContextMenuStrip _menuStrip = new ContextMenuStrip();
Image image = new Bitmap("icon_main.ico");
_menuStrip.Items.Add("First item", image);
ToolStripSeparator stripSeparator1 = new ToolStripSeparator();
stripSeparator1.Alignment = ToolStripItemAlignment.Right;//right alignment
_menuStrip.Items.Add(stripSeparator1);
_menuStrip.Items.Add("Second item", image);
ToolStripSeparator stripSeparator = new ToolStripSeparator();
stripSeparator.Alignment = ToolStripItemAlignment.Left;//left alignment
_menuStrip.Items.Add(stripSeparator);
_menuStrip.Items.Add("Exit", image, OnClickExit);
_mainIcon.ContextMenuStrip = _menuStrip;
Strange thing is that separators are not aligned - I have a little space between edge of ContextMenuStrip and separator, even if I try to align the separator (I've tried both - left and right alignment):
It's not a big graphical failure, but I'm asking myself how this can be aligned perfectly:
Any ideas what should I do?
You should use Paint event (msdn):
...
ToolStripSeparator stripSeparator = new ToolStripSeparator();
stripSeparator.Paint += stripSeparator_Paint;
_menuStrip.Items.Add(stripSeparator);
...
Paint event handler:
void stripSeparator_Paint(object sender, PaintEventArgs e)
{
ToolStripSeparator stripSeparator = sender as ToolStripSeparator;
ContextMenuStrip menuStrip = stripSeparator.Owner as ContextMenuStrip;
e.Graphics.FillRectangle(new SolidBrush(Color.Transparent), new Rectangle(0, 0, stripSeparator.Width, stripSeparator.Height));
using (Pen pen = new Pen(Color.LightGray, 1))
{
e.Graphics.DrawLine(pen, new Point(23, stripSeparator.Height / 2), new Point(menuStrip.Width, stripSeparator.Height / 2));
}
}

Categories