I have the following paint event (form) that is drawing the rectangle:
void LogicSimulationViewerForm_Paint(object sender, PaintEventArgs e) {
Rectangle rect = new Rectangle(100, 100, 400, 100);
Graphics c = rtbLogicCode.CreateGraphics();
c.DrawRectangle(new Pen(Color.Black, 3), rect);
}
The rectangle is shown for a brief moment and then disappears immediately. The rectangle will only show momentarily again when the user resizes the form.
How can I solve this issue?
Don't use the Control.CreateGraphics() method, use the PaintEventArgs.Graphics property:
void LogicSimulationViewerForm_Paint(object sender, PaintEventArgs e) {
Rectangle rect = new Rectangle(100, 100, 400, 100);
e.Graphics.DrawRectangle(Pens.Black, rect);
}
Related
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 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();
Below is my code for changing my panel information into a Bitmap.
The Bitmap is first generated by my panel information and then saved to as a image file.
I confirmed that the width, height, and bounds represent the right information given by my panel.
I am currently unsure of why my result bmp/jpeg file is different from the image on my panel.
//bitmap saving function
Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);
Debug.WriteLine("bounds: " + panel1.ClientRectangle);
this.panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
bmp.Save(#"C:\Documents and Settings\Flaw\Desktop\Test.bmp", ImageFormat.Bmp);
//drawing function
System.Drawing.Graphics graphicsObj;
graphicsObj = this.panel1.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Black, 5);
graphicsObj.Clear(Color.White);
//graphicsObj.DrawLine(myPen, 50, 50, 100, 100);
if (bCircle)
{
graphicsObj.DrawEllipse(myPen, x, y, 100, 100);
}
else if (bSquare)
{
graphicsObj.DrawRectangle(myPen, x, y, 100, 100);
}
The result I get by saving the bitmap.
The image that is on my panel1 (cropped from my Window Form)
Your Bounds property is the relationship the panel has to the parent container, so this won't always work:
this.panel1.DrawToBitmap(bmp, panel1.Bounds);
Try this instead:
this.panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
Your bitmap size should also use the ClientSize properties, since the panel's Width and Height properties include any border sizes:
Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);
Per your update, CreateGraphics is a temporary canvas and won't be a part of the panel, so there was nothing to save. Use the panel's paint event instead:
private void panel1_Paint(object sender, PaintEventArgs e) {
using (Pen myPen = new Pen(Color.Black, 5)) {
e.Graphics.Clear(Color.White);
if (bCircle) {
e.Graphics.DrawEllipse(myPen, x, y, 100, 100);
} else if (bSquare) {
e.Graphics.DrawRectangle(myPen, x, y, 100, 100);
}
}
}
To make an update, you just need to invalidate the control:
panel1.Invalidate();
I used
Pen pen = new Pen(Color.Red);
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
to shape the border of rectangle but now I only need to show the corner of that rectangle.
You can draw it by yourself by DrawLine function in Paint event handler, something like this:
Pen pen = new Pen(Color.Red);
private void Form1_Load(object sender, System.EventArgs e)
{
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
}
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawLine(pen, 0, 0, pictureBox1.Right, 0);
g.DrawLine(pen, 0, 0, 0, pictureBox1.Bottom);
}
It's a use case, maybe you need other coordinates, but you can fix it easily.
You could use 2 lines to get the effect you want:
private void MainForm_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Red);
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
e.Graphics.DrawLine(pen, 0, 0, 50, 0 );
e.Graphics.DrawLine(pen, 0, 0, 0, 50);
}
This draws the corner of a rectangle in the top left corner of the form.
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);
}