Draw on Image in Winforms - c#

I am drawing a rectangle on a image which is within a picture box. The problem I have is that the rectangle is drawn behind the image. Please see the picture attached.
How can I draw on top of the image?
My on paint of the picture is as below. My paint is on my picturebox - I wonder if that is the problem ? but there is no paint on the image?
Rectangle ZoomRect1 = new Rectangle(Math.Min(ZoomToRectangleLeftButtonLocation.X, ZoomToRectangleCurrentButtonLocation.X),
Math.Min(ZoomToRectangleLeftButtonLocation.Y, ZoomToRectangleCurrentButtonLocation.Y),
Math.Abs(ZoomToRectangleLeftButtonLocation.X - ZoomToRectangleCurrentButtonLocation.X),
Math.Abs(ZoomToRectangleLeftButtonLocation.Y - ZoomToRectangleCurrentButtonLocation.Y));
Graphics g1 = e.Graphics;
Pen pen = new Pen(Color.Red, 2);
g1.DrawRectangle(pen, ZoomRect1);
pen.Dispose();

I believe you are using OnPaint method of the form ! Not the pictureBox and that's why the rectangle is in form.
To draw rec on PictureBox you have to do like :
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Rectangle ee = new Rectangle(10, 10, 30, 30);
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, ee);
}
}
And here the graphics e is for the pictureBox not the form itself.
EDIT
If the first answer didn't help : try this out.
Add this method where ever you want and call it
public void paintOnPictureBox()
{
Rectangle ee = new Rectangle(10, 10, 50, 50);
Graphics gr = Graphics.FromImage(pictureBox1.Image);
using (Pen pen = new Pen(Color.Green, 2))
{
gr.DrawRectangle(pen, ee);
}
}
DON'T FORGET : on pictureBox OnPaint event, add this line :
this.Refresh();
and the results :
EDIT 2 :
It's bad to add
this.Refresh();
in the onPaint method since it may cause other components to flickering. As it slows the form on showing and operating !
It's better to add it in the end of painting method like :
public void paintOnPictureBox()
{
Rectangle ee = new Rectangle(10, 10, 50, 50);
Graphics gr = Graphics.FromImage(pictureBox1.Image);
using (Pen pen = new Pen(Color.Green, 2))
{
gr.DrawRectangle(pen, ee);
}
this.Refresh();
}

I guess you are setting image source to control
Try to draw image, than rectangle
Graphics g1 = e.Graphics;
g1.DrawImage(...);
Pen pen = new Pen(Color.Red, 2);
g1.DrawRectangle(pen, ZoomRect1);
pen.Dispose();

Related

Creating another Graphics with different coordinates?

Is it possible to create another Graphics form an existing Graphics with a different coordinate system? For example, let's say that the black rectangle is the ClipRectangle of the Graphics object I got in OnPaint(). If I only want to draw inside the blue rectangle, I would have to constantly calculate the offset. That is, to draw at the logical point (0,0) in the blue rectangle, I would have to add the x and y offsets. That makes drawing code complicated.
Is there a way to create some sort of virtual Graphics using the Graphics above but with a different coordinate system? Something like below
//not actual code
var virtualG = Graphics.FromExistingGraphics(e.Graphics, 200/*x1*/, 200/*y1*/, 1000/*x2*/, 600/*y2*/);
//Doing the same thing as e.Graphics.DrawLine(pen, 200, 200, 400, 400)
virtualG.DrawLine(pen, 0, 0, 200, 200);
//Draws nothing, NOT the same as e.Graphics.DrawLine(pen, 1100, 200, 1200, 400)
//, because its outside of the virtualG's bounds.
virtualG.DrawLine(pen, 900, 0, 1000, 200);
I thought about creating a new Graphics using bitmap, draw there and then copy the bitmap to the specified location of the Graphics from OnPaint, but that could be slow.
If you don't want any scaling, and simply want to move the origin to (200, 200), then use TranslateTransform as suggested previously. If you want to clip any drawings outside that rectangle, then use SetClip.
Here's an example, showing the same set of lines drawn before and after translating and clipping. The black lines are before, while the blue line is after (the second blue line is clipped and therefore not visible). The red rectangle shows the clipping region:
Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class Line
{
public Point ptA;
public Point ptB;
public void Draw(Graphics G, Color color)
{
using (Pen P = new Pen(color))
{
G.DrawLine(P, ptA, ptB);
}
}
}
private List<Line> Lines = new List<Line>();
private void Form1_Load(object sender, EventArgs e)
{
Lines.Add(new Line() { ptA = new Point(0,0), ptB = new Point(200, 200)});
Lines.Add(new Line() { ptA = new Point(900, 0), ptB = new Point(1000, 200) });
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics G = e.Graphics;
G.Clear(Color.DarkGray);
foreach(Line line in Lines)
{
line.Draw(G, Color.Black);
}
Rectangle rc = new Rectangle(new Point(200, 200), new Size(800, 400));
G.DrawRectangle(Pens.Red, rc);
G.SetClip(rc);
G.TranslateTransform(rc.Left, rc.Top); // origin is now at (200, 200)
foreach (Line line in Lines)
{
line.Draw(G, Color.Blue);
}
}
}

I want to draw an ellipse on top of my button, form application C#

I have some problems with drawing a circle/ellipse on top of my buttons since i draw them onto the form and not the button itself meaning they end up getting covered by the buttons.
right now I draw the ellipse like this
Pen green = new Pen(Color.Green, 1);
Rectangle rectEllipse = new Rectangle(100, 40, 30, 30);
e.Graphics.DrawEllipse(black, rectEllipse);
You have to draw on Button, not on Form:
private void myButton_Paint(object sender, PaintEventArgs e) {
//DONE: wrap IDisposable into using
using (Pen green = new Pen(Color.Green, 1)) {
Rectangle rectEllipse = new Rectangle(10, 10, 30, 30);
// typo? You, probably, mean "green", not "black"
e.Graphics.DrawEllipse(green, rectEllipse);
}
}

Draw an outline of form with graphics

Basically I have a form with no border, I want to keep it like that. It's in a fixed position. I'm trying to draw an outline of the form size in the form (so it looks like a border) I'm having trouble and never really used "drawing" techniques in forms.
Pen pen = new Pen(Color.Black, 20);
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
Graphics g = CreateGraphics();
g.DrawRectangle(pen, rect);
Do it in OnPaint:
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
Pen pen = new Pen(Color.Black, 20);
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
e.Graphics.DrawRectangle(pen, rect);
}

Drawing a rectangle over panel

I need to draw a rectangle into a panel. I dont know the color in advance, I get the color during runtime, I dont know how to set the color not to a fixed value, and second - when i try to draw the rectangle, it does nothing at all. Here is my code that should draw the rectangle (infact it does in another project, but thats just in a plain form, not into a panel)
Graphics g;
g = CreateGraphics();
Pen p;
Rectangle r;
p = new Pen(Brushes.Blue);
r = new Rectangle(1, 1, 578, 38);
g.DrawRectangle(p, r);`
So I need to replace (Brushes.Blue) with a variable and I need to draw the rectangle in a panel on its coordinates set in this code..
Construct your Pen using the Pen(Color) constructor instead of the Pen(Brush) one. Then you can define your color once you know it.
You should perform drawing in the Paint event of the panel. This event occurs whenever windows decides it's time to repaint the panel, and the PaintEventArgs contain a Graphics object you can draw the rectangle on.
The Brush is an abstract class, but you can use the SolidBrush object to create a custom colored brush at runtime:
int red = 255;
int green = 0;
int blue = 0;
Brush myBrush = new SolidBrush(Color.FromArgb(red, green, blue));
Here you are:
private Color _color; // save the color somewhere
private bool iKnowDaColor = false; // this will be set to true when we know the color
public Form1() {
InitializeComponents();
// on invalidate we want to be able to draw the rectangle
panel1.Paint += new PaintEventHandler(panel_Paint);
}
void panel_Paint(object sender, PaintEventArgs e) {
// if we know the color paint the rectangle
if(iKnowDaColor) {
e.Graphics.DrawRectangle(new Pen(_color),
1, 1, 578, 38);
}
}
And when you know the color:
_color = ...
iKnowDaColor = true;
// causes the panel to invalidate and our painting procedure to be called
panel.Invalidate();
I haven't tested this but should give you the basic idea.
put the following code in the appropriate place :
Graphics g = panel1.CreateGraphics();
int redInt=255, blueInt=255, greenInt=255; //255 is example, give it what u know
Pen p = new Pen(Color.FromArgb(redInt,blueInt,greenInt));
Rectangle r = new Rectangle(1, 1, 578, 38);
g.DrawRectangle(p, r);
and if you wanted to draw the rectangle somewhere else, say the form, you could do g = this.CreateGraphics.
I think that the better way of doing that is to extend the Panel class and add some custom OnPaint event logic.
public class PanelRect : Panel
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Graphics g = e.Graphics)
{
Rectangle rect = ClientRectangle;
rect.Location = new Point(20, 20); // specify rectangle relative position here (relative to parent container)
rect.Size = new Size(30, 30); // specify rectangle size here
using (Brush brush = new SolidBrush(Color.Aqua)) // specify color here and brush type here
{
g.FillRectangle(brush, rect);
}
}
}
}
P.S. This is not an advanced example, but might help you. You can move size, location and color etc to properties so you can easily change them from designer.
P.S. P.S. If you need a non-filled rectangle just use Pen object instead of Brush (you might also change the FillRectangle to something more suitable).

How can I use the Pen tool to draw a simple black line on a PictureBox's Image object?

I'm trying to draw a line that goes from middle top to bottom.
I know I have to use the Pen class to accomplish this.
private void RepaintPreview()
{
Pen blackPen = new Pen(Brushes.Black);
blackPen.Width = 1.0f;
blackPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
ptbTablePreview.Image.draw?
}
Basically, how can I draw this line on the image? Thank you.
I tried the following, and it works with me:
1- I set the image of the picturebox in design time
2- I handled the Paint event of the picturebox, and added the following code:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
using (Pen p = new Pen(Color.Black, 2))
{
e.Graphics.DrawLine(p, new Point(pictureBox1.Width / 2, 0), new Point(pictureBox1.Width / 2, pictureBox1.Height));
}
}

Categories