I want to use the FillEllipse & DrawEllipse function to act like a LED display. But I was not able to click on the button to disable the blinking again since the subroutine is still running. Any recommendation?
bool alert = false;
bool blink = false;
private void blinking()
{
Graphics pb = pictureBox1.CreateGraphics();
SolidBrush red = new SolidBrush(Color.Red);
SolidBrush green = new SolidBrush(Color.LightGreen);
while (blink == true)
{
pictureBox1.Refresh();
if (alert == true)
{
pb.FillEllipse(red, 20, 20, 50, 50);
alert = false;
}
else
{
//pb.FillEllipse(green, 20, 20, 50, 50);
pb.DrawEllipse(Pens.Red, 20, 20, 50, 50);
alert = true;
}
Thread.Sleep(timer1.Interval);
}
}
private void blink_btn_Click(object sender, EventArgs e)
{
if (blink == false)
{
blink = true;
}
else
{
blink = false;
}
blinking();
}
Besides that you are blocking the UI with your blinking() method, you're not drawing correctly anyway. You should only draw when handling a Paint event. Also, there's not really a good reason to use a PictureBox if all you're going to do is draw something yourself. Just put a Panel, or even make a custom control.
But, sticking with the "draw into the PictureBox" approach, this is what your code really ought to look like:
First, it looks like you already have a Timer attached to the form. Why you're not already using that is beyond me, but you should. Hook up a handler to the Tick event:
private void timer1_Tick(object sender, EventArgs e)
{
alert = !alert;
pictureBox1.Invalidate();
}
Add your handler for the PictureBox.Paint event:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Brush brush = alert ? Brushes.Red : Brushes.LightGreen;
e.Graphics.FillEllipse(brush, 20, 20, 50, 50);
}
Finally, use your button Click handler to toggle the timer:
private void blink_btn_Click(object sender, EventArgs e)
{
timer1.Enabled = !timer1.Enabled;
}
Add code as necessary to draw differently (the above just toggles between the red and green ellipse), to reset the appearance when the timer's not active, etc.
Related
I'm very new(read 3 weeks exp) to C#(programming in general),started with html/css and javascript and now on my way with C#.
I'm trying to make my own simple 'Paint' application in windows form. But i've encountered an issue and just cant wrap my head around it, doesnt matter how much i read or follow other mans code, i'm stuck. The following code works fine but when resizing the application window the drawing dissappears.
As a solution ive read that declaring the Graphics method within the panel1_Paint event this should be resolved And here is my issue. See last code sample, ive come up with this(yes like i said, im new to this)and its not drawing anything.
ive simply tried to recreate the first example under the panel1_Paint event but i guess something went wrong during the mouseMove event and i cant figure out what it is.
Could someone explain to me what i am missing here, that would be very appreciated. thanks in advance.
[Old code]
namespace Painter
{
public partial class Form1 : Form
{
Graphics graphics;
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
graphics = panel1.CreateGraphics();
graphics.DrawLine(pen, startingPoint, endPoint);
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
[New Code]
namespace Painter
{
public partial class Form1 : Form
{
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
if (mousePaint == true)
{
graphics.DrawLine(pen, startingPoint, endPoint);
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
This is nonsense! Always and only use the e.Graphics object from the Paint param!!
Also: To trigger the Paint event do a panel1.Invalidate(); whenever your drawing data have changed!
Also: Make sure you understand just what your mousePaint flag is supposed to control: the mouse painting (i.e. adding new shapes to draw) or the regular painting (i. all shape previously drawn)!? Note that all drawing, current and previous needs to be done from the Paint event, whenever necessary i.e. over and over again!
To be able to do so: Collect all the shpes' data in a List<T>..
To Doublebuffer a Panel you need to subclass it. Your code turns on DoubleBuffering for the Form, which fine but won't help the Panel..
Instead simply use a PictureBox, which is control meant for drawing on!
A DoubleBuffered Panel subclass is as simple as this:
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}
Update: Instead you can also use a Label (with Autosize=false); it also has the DoubleBuffered property turned on out of the box and supports drawing better than Panels do.
The following code works fine but when resizing the application window the drawing dissappears.
This happens because resizing the application window invalidates portion of your panel which causes the portion to be redrawn.
Reason why your second approach is not working (the one labelled as [NEW CODE]) is because the Paint event is called only when relevant component is redrawn. You could partially solve this by forcing redraw of the panel in your MouseDown/MouseMove event handlers but you would still lose your previously painted stuff.
Possible solution is to create instance of Bitmap and paint there. Then just set this Bitmap as BackgroundImage of the panel. You can find more information on that here. Of course you would need to think about stuff like resizing and what should happen to the bitmap if application window gets shrunk or enlarged.
Here is some code that I quickly put together to get you started:
namespace WinForms_PaintTest
{
public partial class Form1 : Form
{
private Pen pen;
private Bitmap bitmap;
public Form1()
{
InitializeComponent();
this.pen = new Pen(Color.Black, 1);
this.bitmap = new Bitmap(this.panel1.Width, this.panel1.Height);
this.panel1.BackgroundImage = this.bitmap;
}
private void panel1_MouseMove(Object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
using (Graphics g = Graphics.FromImage(this.bitmap))
{
g.DrawRectangle(this.pen, e.Location.X, e.Location.Y, 1, 1);
}
this.panel1.Refresh();
}
}
private void Form1_FormClosed(Object sender, FormClosedEventArgs e)
{
this.pen.Dispose();
this.bitmap.Dispose();
}
}
}
Also regarding this:
this.DoubleBuffered = true;
I believe your intention was to prevent the flickering when relevant control is being redrawn? If that is case you need to set this property against the panel and not against the form itself. It is little bit tricky though because DoubleBuffered property of the panel is protected so you will need to either inherit from the panel or resort to reflection. You can find more information here .
I've got a smaller image in my form. When the user hovers over the image it brings up a larger view of the image (that follows the mouse, but stays a certain distance from the mouse). In order to do this I am generating a Form with no FormBorderStyles when the cursor hovers the image.
The problem I'm running into is that the first form doesn't seem to detect any longer that the mouse is hovering or leaving the PictureBox once the form activates. The Form also doesn't follow the cursor.
Here is the slimmed down version of what I've got:
C#
bool formOpen = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.MouseHover += pictureBox1_MouseHover;
pictureBox1.MouseLeave +=pictureBox1_MouseLeave;
}
void pictureBox1_MouseHover(object sender, EventArgs e)
{
if (formOpen == false)
{
Form form = new Form();
form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
form.BackColor = Color.Orchid;
//Show the form
form.Show();
form.Name = "imageForm";
this.AddOwnedForm(form);
//Set event handler for when the mouse leaves the image area.
//form.MouseLeave += form_MouseLeave;
//Set the location of the form and size
form.BackColor = Color.Black;
form.Dock = DockStyle.Fill;
form.Size = new Size(30, 30);
form.BackgroundImageLayout = ImageLayout.Center;
this.TopMost = true;
formOpen = true;
form.Location = new Point(Cursor.Position.X, Cursor.Position.Y);
}
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
//MessageBox.Show("Worked");
}
}
The MouseLeave (and other events) was not recognized because the opening of the popup window and especially making it topmost=true took away the focus from the original form and its PictureBox.
It also didn't move because not code for moving was provided..
Here are a few changes that will make the form move:
You need a reference to it at the form1 level
you need to move it in the MouseMove event
Note that Hover is a once-only type of event. It fires only once until you leave the control.. (Note: Setsu has switched from Hover to Enter. This works fine, but lacks the short delay before showing the 2nd Form. If you want that back you can either switch back to Hover or you can fake the hover delay by a Timer, which is what I often do.)
// class level variable
Form form;
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.MouseEnter += pictureBox1_MouseEnter;
pictureBox1.MouseLeave +=pictureBox1_MouseLeave;
pictureBox1.MouseMove += pictureBox1_MouseMove; // here we move the form..
}
// .. with a little offset. The exact numbers depend on the cursor shape
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if ((form != null) && form.Visible)
{
form.Location = new Point(Cursor.Position.X + 5, Cursor.Position.Y + 5);
}
}
void pictureBox1_MouseEnter(object sender, EventArgs e)
{
// we create it only once. Could also be done at startup!
if (form == null)
{
form = new Form();
form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
//form.BackColor = Color.Orchid;
form.Name = "imageForm";
this.AddOwnedForm(form);
form.BackColor = Color.Black;
form.Dock = DockStyle.Fill;
form.Size = new Size(30, 30);
form.BackgroundImageLayout = ImageLayout.Center;
//this.TopMost = true; // wrong! this will steal the focus!!
form.ShowInTaskbar = false;
}
// later we only show and update it..
form.Show();
form.Location = new Point(Cursor.Position.X + 5, Cursor.Position.Y + 5);
// we want the Focus to be on the main form!
Focus();
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
if (form!= null) form.Hide();
}
MouseHover = Occurs when the mouse pointer rests on the control. (msdn)
Try MouseMove instead.
I want to draw(Fill) a rectangle in to my form when I click on the button. But I can't manage to make it work and dont know what is wrong.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics; //verklaart naar object Graphics
Vierkant vierkant = new Vierkant();
}
private void vierkant_Click(object sender, EventArgs e)
{
SolidBrush myBrush = new SolidBrush(Color.Cyan);
g.FillRectangle(myBrush, 20, 20, 50, 50);
}
Shall the drawing persist or not? Meaning: Shall it still be there after eg a Resize or maximize etc? Also: What is a Vierkant?
To make it persist you can use code like this:
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (paintIt)
using( SolidBrush myBrush = new SolidBrush(Color.Cyan) )
e.Graphics.FillRectangle(myBrush, 20, 20, 50, 50);
}
bool paintIt = false;
private void vierkant_Click(object sender, EventArgs e)
{
paintIt = true;
this.Invalidate();
// ?? what is this supposed to do or be??
// Vierkant vierkant = new Vierkant();
}
This will work if both events are hooked up. For more interesting drawings you will need to store more than a bool flag but Lists of a drawAction class you need to invent which will include the shapes, its data, brushes etc..
If you replace paintIt = true; by paintIt = !paintIt; the Rectangle will appear and disappear on each click..
My question seems a bit lengthy but I know the solution would be slight corrections to my code.I am implementing a sequence of 3 mouse events and a paint event in my form 1
pictureBox1_MouseDown,
pictureBox1_MouseMove,
pictureBox1_Paint,
pictureBox1_MouseUp.
the code should work this way: when i click the mouse and drag it and release the button at desired point then there should appear a custom message box which takes the input values.so i constructed a form(form2) which appears as message box. here is my code of form 1 ,you can understand the problem after seeing the code.
form1:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// "e.X" and "e.Y" are used to get MousePositionX and MousePositionY
rect = new Rectangle(0, 0, e.X, e.Y);
pictureBox1.Invalidate();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// This makes sure that the left mouse button is pressed.
if (e.Button == MouseButtons.Left)
{
// Draws the rectangle as the mouse moves
rect.Width = e.X;
rect.Height = e.Y;
}
pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, rect);
}
}
private WindowsFormsApplication2.Form2 _form2 = new WindowsFormsApplication2.Form2();
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
DialogResult dialogresult = _form2.ShowDialog(this);
if (dialogresult == DialogResult.OK)
{
try
{
for (int i = 0; i < 2; i++)
{
l[i] = e.X;
m[i] = e.Y;
}
}
catch (Exception ex)
{
}
}
}
the problems here are:
1)According to the code when we drag the mouse a rectangle appears and the place where we leave the mouse button a message box appears,now this message box(form2) is unable to read the input values as i dont know how to connect the OK and CANCEl buttons of form2 with the form1.After giving inputs and pressing OK the rectangle should disappear,but here it is not happening.
2)I only need to give the input only two times,i.e i perform the previous sequence of actions(all the mouse events and paint event) only twice ,so i wrote FOR loop accordingly.But the problem is the message box(form2) get fired every time, i release the mouse button.This is causing a serious problem as i have to implement a mousedoubleclick event after giving the two inputs.
Any please give say me necessary corrections i have to make.
thanks in advance.
I am not sure what you mean with "connect the OK and CANCEL buttons of form2 with form1"?
You don't have to "connect" anything. All you need is two buttons on Form2 (OK and Cancel) and in each _click method you need this.DialogResult = DialogResult.OK; for OK and this.DialogResult = DialogResult.Cancel; for Cancel.
Then you continue with your "if" in Form 1.
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
DialogResult dialogresult = _form2.ShowDialog(this);
if (dialogresult == DialogResult.OK)
{
rect.Width = 0;
rect.Height = 0;
pictureBox1.Invalidate();
}
}
That will remove the Rectangle. I don't know if it's a good solution to do it, but it works.
Your Loop inside the Method can't work the way you want: every time you call pictureBox1_MouseUp and reach the for-loop 'i' will be set to '0' and then the loop starts.
You need a int TwoClicks = 0 in constructor of Form1. And you have to change the pictureBox1_MouseUp accordingly:
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (TwoClicks < 2)
{
TwoClicks++;
DialogResult dialogresult = _form2.ShowDialog(this);
if (dialogresult == DialogResult.OK)
{
rect.Width = 0;
rect.Height = 0;
pictureBox1.Invalidate();
}
}
}
Feel free to ask any questions (and describe your first Problem, if I didn't get it right).
I want to add a label to my form , and I want it without any color- I want just it's text to be visible, I don't find this option in the label's properties, can anyone help me please?
Do you want to make the label (except for the text) transparent? Windows Forms (I assume WinForms - is this true) doesn't really support transparency. The easiest way, sometimes, is Label's Backcolor to Transparent.
label1.BackColor = System.Drawing.Color.Transparent;
You will run into problems though, as WinForms really doesn't properly support transparency. Otherwise, see here:
http://www.doogal.co.uk/transparent.php
http://www.codeproject.com/KB/dotnet/transparent_controls_net.aspx
http://www.daniweb.com/code/snippet216425.html
Setting the parent of a usercontrol prevents it from being transparent
Good luck!
If you picture box in the background then use this:
label1.Parent = pictureBox1;
label1.BackColor = Color.Transparent;
Put this code below InitializeComponent(); or in Form_Load Method.
Ref: https://www.c-sharpcorner.com/blogs/how-to-make-a-transparent-label-over-a-picturebox1
You are right. but here is the simplest way for making the back color of the label transparent
In the properties window of that label select Web.. In Web select Transparent
:)
this.label1.BackColor = System.Drawing.Color.Transparent;
Let's view 2 possible cases.
Background is a color.
Double-Click the form background in VS constructor. Then, write this code:
/*
This code will set all your object's background color to the same as the form.
This should be written in the body of <FormName>_Load(object, EventArgs).
*/
Control[] objs = new Control[] { /* your object list, e. g { myLabel, myPicture } */ };
foreach (Control control in objs) {
control.BackColor = Color.Transparent;
// OR
control.BackColor = this.BackColor;
}
Background is a PictureBox.
This is also easy. We just need to make all objects as children of your PictureBox and set it's color to transparent. Code:
/*
This code will set all your object's background to transparent and show the PBox.
This should be written in the body of <FormName>_Load(object, EventArgs)'s foreach loop.
Put everything before it the same as in 1st code fragment.
*/
control.Parent = back;
control.BackColor = Color.Transparent;
Let's see the pictures.
Color
Before
After
PictureBox
Before
After (here foreground were changed, don't mind this)
Generally, labels and textboxes that appear in front of an image is best organized in a panel. When rendering, if labels need to be transparent to an image within the panel, you can switch to image as parent of labels in Form initiation like this:
var oldParent = panel1;
var newParent = pictureBox1;
foreach (var label in oldParent.Controls.OfType<Label>())
{
label.Location = newParent.PointToClient(label.Parent.PointToScreen(label.Location));
label.Parent = newParent;
label.BackColor = Color.Transparent;
}
This uses Graphics.CopyFromScreen so the control needs to be added when it's visable on screen.
public partial class TransparentLabelControl : Label
{
public TransparentLabelControl()
{
this.AutoSize = true;
this.Visible = false;
this.ImageAlign = ContentAlignment.TopLeft;
this.Visible = true;
this.Resize += TransparentLabelControl_Resize;
this.LocationChanged += TransparentLabelControl_LocationChanged;
this.TextChanged += TransparentLabelControl_TextChanged;
this.ParentChanged += TransparentLabelControl_ParentChanged;
}
#region Events
private void TransparentLabelControl_ParentChanged(object sender, EventArgs e)
{
SetTransparent();
if (this.Parent != null)
{
this.Parent.ControlAdded += Parent_ControlAdded;
this.Parent.ControlRemoved += Parent_ControlRemoved;
}
}
private void Parent_ControlRemoved(object sender, ControlEventArgs e)
{
SetTransparent();
}
private void Parent_ControlAdded(object sender, ControlEventArgs e)
{
if (this.Bounds.IntersectsWith(e.Control.Bounds))
{
SetTransparent();
}
}
private void TransparentLabelControl_TextChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_LocationChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_Resize(object sender, EventArgs e)
{
SetTransparent();
}
#endregion
public void SetTransparent()
{
if (this.Parent!= null)
{
this.Visible = false;
this.Image = this.takeComponentScreenShot(this.Parent);
this.Visible = true;
}
}
private Bitmap takeComponentScreenShot(Control control)
{
Rectangle rect = control.RectangleToScreen(this.Bounds);
if (rect.Width == 0 || rect.Height == 0)
{
return null;
}
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
return bmp;
}
}
An easy way to have a label with a picture behind it is to use the Image Property of the label itself. This will print the text over the top of the picture, and enable you to align the image (top/bottom/left/right/centre) as required.picture