how can i call a method with system arguments in a mouse click event:
public void DrawStringRectangleF(PaintEventArgs e)
{
// Create string to draw.
String drawString = "Sample Text";
// Create font and brush.
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create rectangle for drawing.
float x = 150.0F;
float y = 150.0F;
float width = 200.0F;
float height = 50.0F;
RectangleF drawRect = new RectangleF(x, y, width, height);
// Draw rectangle to screen.
Pen blackPen = new Pen(Color.Black);
e.Graphics.DrawRectangle(blackPen, x, y, width, height);
// Draw string to screen.
e.Graphics.DrawString(drawString, drawFont, drawBrush, drawRect);
}
i want to call this method in this event:
private void button1_Click(object sender, EventArgs e)
{
// calling DrawStringRectangleF(PaintEventArgs e) here
}
it's easy to call a method if the parameters are variables just by mentioning the values when calling these methods, but how to call it in such a case?!
In order to satisfy the existing method signature you could encapsulate the Graphics instance that you wish to use to draw the rectangle within an instance of the PaintEventArgs class like this
using (var controlGraphics = CreateGraphics())
{
var paintEventArgs = new PaintEventArgs(controlGraphics, ClientRectangle);
DrawStringRectangleF(paintEventArgs);
}
The Control.CreateGraphics method will produce a Graphics instance that you can use to paint on the underlying control (or form).
Understand that everything painted with that Graphics object will be erased each time the control is invalidated so you must re-draw the graphic continuously.
You may consider adapting the method signature so that it accepts an instance of Graphics instead which should make for a cleaner solution.
Here's an example using the Paint() event and a List of a custom class to store the information about what should be drawn:
public partial class Form1 : Form
{
public class TextData
{
public string Text;
public string FontName;
public int FontSize;
public RectangleF TextRectF;
public Color TextColor;
}
private List<TextData> Texts = new List<TextData>();
public Form1()
{
InitializeComponent();
this.Paint += new PaintEventHandler(Form1_Paint);
TextData td = new TextData();
td.Text = "Example";
td.FontName = "Courier";
td.FontSize = 24;
td.TextRectF = new RectangleF(50.0F, 50.0F, 175.0F, 75.0F);
td.TextColor = Color.Red;
Texts.Add(td);
}
void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (TextData td in Texts)
{
using (Pen drawPen = new Pen(td.TextColor))
{
e.Graphics.DrawRectangle(drawPen, Rectangle.Round(td.TextRectF));
}
using (Font drawFont = new Font(td.FontName, td.FontSize))
{
using (SolidBrush drawBrush = new SolidBrush(td.TextColor))
{
e.Graphics.DrawString(td.Text, drawFont, drawBrush, td.TextRectF);
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
TextData td = new TextData();
td.Text = "Sample Text";
td.FontName = "Arial";
td.FontSize = 16;
td.TextRectF = new RectangleF(150.0F, 150.0F, 200.0F, 50.0F);
td.TextColor = Color.Black;
Texts.Add(td);
this.Refresh();
}
}
Related
My problem is:
When I try to save the graphics object to a bitmap image it does not save correctly, instead the image is black in color and there is nothing else in the file.
I've seen other answers, but I think it's different when you draw multiple times in the graphics object.
So, here's my attempt, please let me know where my issue is.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace PenFlip
{
public partial class Match : Form
{
Graphics g;
private int x = -1;
private int y = -1;
private bool moving;
private Pen pen;
private Bitmap testBmp;
public Match()
{
InitializeComponent();
g = panel1.CreateGraphics();
g.SmoothingMode = SmoothingMode.AntiAlias;
pen = new Pen(Color.Black, 5);
pen.StartCap = pen.EndCap = LineCap.Round;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox pictureBox = (PictureBox) sender;
pen.Color = pictureBox.BackColor;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
moving = true;
x = e.X;
y = e.Y;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (moving && x != -1 && y != -1)
{
g.DrawLine(pen, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
moving = false;
x = -1;
y = -1;
g.Save();
}
private void button1_Click(object sender, EventArgs e)
{
// prints out the black image
testBmp = new Bitmap(400, 200, g);
testBmp.Save(#"test.bmp", ImageFormat.Bmp);
}
}
}
Uh, usage of Bitmap is tricky and has a lot of pitfalls (that's why it's use is deprecated, btw). Try to create the Graphics object from an in-memory bitmap, instead of grabbing it from a control. The bitmap should be the primary object, not the Graphics instance. You don't know what the control does to your bitmap.
So in the constructor, do something like:
public Match()
{
InitializeComponent();
bitmap = new Bitmap(panel1.Width, panel1.Height, PixelFormat.Format32bppArgb);
pen = new Pen(Color.Black, 5);
pen.StartCap = pen.EndCap = LineCap.Round;
}
and in each function, create a graphics object from the bitmap:
using (var graphics = Graphics.FromImage(image))
{
graphics.Draw(...);
}
You need to update the panel manually now, e.g. by attaching to it's OnPaint event.
i have to ZOOM-IN & ZOOM-OUT specific portion of 2D-graphics like (line, Rectangle, circle) which i have drawn on winform.
I am not used any picture box, panel.
I crated simple program to draw circle & on button click try to zoom
but it showing error "parameter is not valid"
in method Drawing() # Line- DeviceContexct.Transform = mainViewTransform;
public Graphics DeviceContexct;
public Matrix mainViewTransform = new Matrix();
private void ScalingCircle_Paint( object sender, PaintEventArgs e )
{
Pen myPen = new Pen(Color.Blue, 1);
e.Graphics.DrawRectangle(myPen, 50, 50, 100, 100);
mainViewTransform.Scale(3, 2);
DeviceContexct = e.Graphics;
}
private void Drawing(Graphics gr)
{
Pen myPen2 = new Pen(Color.Red, 1);
DeviceContexct.Transform = mainViewTransform;
DeviceContexct.DrawRectangle(myPen2, 50, 50, 100, 100);
}
private void button1_Click( object sender, EventArgs e )
{
Drawing(DeviceContexct);
}
I prefer to draw into Bitmaps with System.Drawing.Graphics object.
Then you can use your graphics object with "go.DrawImage(...)" to draw the bitmap directly into your winforms and actually give it a scale.
https://msdn.microsoft.com/en-us//library/ms142040(v=vs.110).aspx
I got the solution, thanks for your help.
I only need to call refresh/invalidate etc on button click.
public partial class ScalingCircle : Form
{
public Graphics DeviceContexct;
// current transformation matrix of main view (offset & scaling)
public Matrix mainViewTransform = new Matrix();
public int scale = 1;
public ScalingCircle()
{
InitializeComponent();
DeviceContexct = Graphics.FromHwnd(this.Handle);
DeviceContexct = this.CreateGraphics();
}
public void ScalingCircle_Paint(object sender, PaintEventArgs e)
{
DeviceContexct = e.Graphics;
DeviceContexct.PageUnit = GraphicsUnit.Pixel;
DeviceContexct.Transform = mainViewTransform;
ScalingCircle1(scale);
}
private void ScalingCircle1(int x )
{
Pen myPen2 = new Pen(Color.Black, 1);
DeviceContexct.Transform = mainViewTransform;
Rectangle myRectangle = new Rectangle(50, 50, 100 * x, 100 * x);
DeviceContexct.FillRectangle(new SolidBrush(Color.BurlyWood), myRectangle);
}
private void ScalingCircle_Load( object sender, EventArgs e )
{
this.ResizeRedraw = true;
}
private void button1_Click( object sender, EventArgs e )
{
scale += 5;
this.Refresh();
}
private void button2_Click( object sender, EventArgs e )
{
if (scale > 1)
{
scale -= 5;
this.Refresh();
}
}
}
You can use transformations for that. The graphics object you use for painting things has a Transformation property of type System.Drawing.Drawing2D.Matrix.
Graphics also has the ScaleTransform method.
I haven't used it myself, but that is how microsofts Chart does it.
https://msdn.microsoft.com/de-de/library/system.drawing.drawing2d.matrix(v=vs.110).aspx
https://msdn.microsoft.com/de-de/library/system.drawing.graphics.scaletransform(v=vs.110).aspx
I have created a custom control and bind it to Form. I have draw graphics text in the control and added to Form. But it was not displaying the Form. This is my code.
//Create a custom control
public class DrawTextImage : Control
{
public void DrawBox(PaintEventArgs e, Size size)
{
e.Graphics.Clear(Color.White);
int a = 0;
SolidBrush textColor = new SolidBrush(Color.Black);
using (SolidBrush brush = new SolidBrush(Color.Red))
{
e.Graphics.FillRectangle(brush, new Rectangle(a, a, size.Width, size.Height));
e.Graphics.DrawString("Text", Font, textColor, new PointF(50, 50));
}
}
}
//Load Form1
public Form1()
{
InitializeComponent();
DrawTextImage call = new DrawTextImage();
call.Text = "TextControl";
call.Name = "TextContrl";
Size siz = new Size(200, 100);
call.Location = new Point(0, 0);
call.Visible = true;
call.Size = siz;
call.DrawBox(new PaintEventArgs(call.CreateGraphics(), call.ClientRectangle), siz);
this.Controls.Add(call);
}
Any help on this, what did I do wrong?
You should be using the control's own Paint event, not a custom method that you have to call manually.
public class DrawTextImage : Control
{
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
int a = 0;
SolidBrush textColor = new SolidBrush(Color.Black);
using (SolidBrush brush = new SolidBrush(Color.Red))
{
//Note: here you might want to replace the Size parameter with e.Bounds
e.Graphics.FillRectangle(brush, new Rectangle(a, a, Size.Width, Size.Height));
e.Graphics.DrawString("Text", Font, textColor, new PointF(50, 50));
}
}
}
Remove the call to DrawBox, it's unnecessary.
The Paint event is fired automatically whenever a redraw of the control surface is required. You can ask for this yourself in code by using the control's Invalidate() or Refresh() methods.
I am adding one panel to another panel it works but circle which is in inspanel not shown. how can i solved this.
I am using below code. It works but not show circle
public static int xTemp = 0;
public static int yTemp = 0;
private void button1_Click(object sender, EventArgs e)
{
Panel insPanel = new Panel();
Random xRandom = new Random();
xTemp= xRandom.Next(20,100);
Random yRandom = new Random();
yTemp = yRandom.Next(20, 100);
insPanel.Location = new Point(xTemp, yTemp);
insPanel.Width=40;
insPanel.Height = 40;
insPanel.Visible = true;
insPanel.BorderStyle = BorderStyle.FixedSingle;
insPanel.Paint += new PaintEventHandler(insPanel_Paint);
panel1.Controls.Add(insPanel);
}
void insPanel_Paint(object sender, PaintEventArgs e)
{
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
System.Drawing.Graphics formGraphics =this.CreateGraphics();
formGraphics.FillEllipse(myBrush, new Rectangle(xTemp,yTemp, 10, 10));
myBrush.Dispose();
formGraphics.Dispose();
}
Main issue: you're trying to draw your circle at wrong coordinates.
xTemp and yTemp are coordinates of insPanel relative to panel1. But when you drawing your circle, you should use coordinates relative to panel you're drawing at - insPanel.
Another issue: there is no need to create and dispose graphics each time you're drawing something on your panel. You can use e.Graphics from Paint eventhandler arguments.
Based on above, your code could look like:
void insPanel_Paint(object sender, PaintEventArgs e)
{
using (var myBrush = new SolidBrush(Color.Red))
{
e.Graphics.FillEllipse(myBrush, new Rectangle(0, 0, 10, 10));
}
}
Also note - since paint event can occur very frequently, it could be a good idea not to create and dispose brush every time, but use brush cached in your class private field.
Use e.Graphics instead of this.CreateGraphics:
System.Drawing.Graphics formGraphics = e.Graphics;
One more issue is you're getting coordinates in range of 20 - 100 (xRandom.Next(20,100)) and your panel dimensions are just 40, 40.
I' ve drawn roundRectangle using Graphics Path OnPaintEvent
and I already added mouseevent to know if cursor was over the g.p .
void Round_MouseMove(object sender, MouseEventArgs e)
{
Point mousePt = new Point(e.X, e.Y);
if (_path != null)
if (_path.IsVisible(e.Location))
MessageBox.Show("GraphicsPath has been hovered!");
}
Question: is there a way to resize or redraw(hide previous then draw new) a graphicsPath runtime?
Invoke Invalidate for redrawn the Form, so the OnPaint(PaintEventArgs e) will be executed.
Check the following example:
public sealed partial class GraphicsPathForm : Form
{
private bool _graphicsPathIsVisible;
private readonly Pen _pen = new Pen(Color.Red, 2);
private readonly Brush _brush = new SolidBrush(Color.FromArgb(249, 214, 214));
private readonly GraphicsPath _graphicsPath = new GraphicsPath();
private Rectangle _rectangle = new Rectangle(10, 30, 100, 100);
public GraphicsPathForm()
{
InitializeComponent();
_graphicsPath.AddRectangle(_rectangle);
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.Bilinear;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawPath(_pen, _graphicsPath);
if (_graphicsPathIsVisible)
g.FillPath(_brush, _graphicsPath);
base.OnPaint(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
var isVisible = _graphicsPath.IsVisible(e.Location);
if (isVisible == _graphicsPathIsVisible)
return;
const int zoom = 5;
if (isVisible)
{
if (!_graphicsPathIsVisible)
{
_rectangle.Inflate(zoom, zoom);
_graphicsPath.Reset();
_graphicsPath.AddRectangle(_rectangle);
}
}
else
{
if (_graphicsPathIsVisible)
{
_rectangle.Inflate(-zoom, -zoom);
_graphicsPath.Reset();
_graphicsPath.AddRectangle(_rectangle);
}
}
_graphicsPathIsVisible = isVisible;
Invalidate();
base.OnMouseMove(e);
}
}
I hope it helps.