I made a box that I drew using Graphics.DrawLine() for each edge. But I would like the box to be able to move around the screen freely, along with changing the size of the edges. The box is created by using a middle point and width and height, then basic math to find the 4 points which the lines connect to. My question is: How can I update the position of the lines? Do I have to clear the graphics and re-draw the lines each frame? Any answers will be helpful. Thank you.
Here is the code I am using:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Point box_Middle = new Point(300, 300);
int boxWidth = 100;
int boxHeight = 200;
Pen boxPen = new Pen(Color.Red, 3);
DrawBox(e, boxPen, box_Middle, boxWidth, boxHeight);
}
void DrawBox (PaintEventArgs e, Pen pen, Point middle, int width, int height)
{
graphics = e.Graphics;
graphics.TextRenderingHint = System.Drawing.
Text.TextRenderingHint.
SingleBitPerPixelGridFit;
// Draw Box
Point topLeft = new Point(middle.X - width / 2, middle.Y - height / 2);
Point topRight = new Point(topLeft.X + width, topLeft.Y);
Point bottomLeft = new Point(topLeft.X, topLeft.Y + height);
Point bottomRight = new Point(topRight.X, bottomLeft.Y);
graphics.DrawLine(pen, topLeft, topRight);
graphics.DrawLine(pen, topLeft, bottomLeft);
graphics.DrawLine(pen, bottomLeft, bottomRight);
graphics.DrawLine(pen, topRight, bottomRight);
}
Related
I would like to draw a thick, transparent arrow with an arrowhead:
Here's the code that draws the arrow shaft. Notice that I have to offset the rectangle so the calculations are done from the midpoint of the rectangle.
private void DrawMovementArrow(bool color, double StartX, double StartY, double EndX, double EndY)
{
SolidColorBrush partiallyTransparentSolidColorBrush;
Rectangle myRectangle = new Rectangle();
// This will be replaced by piece size
int width = 35;
myRectangle.Width = width;
// Apparently necessary to offset the drawing of the path so that the point is in the center of the path; not the edge.
StartX -= width / 2;
EndX -= width / 2;
myRectangle.Height = Map.EuclideanDistance(StartX, StartY, EndX, EndY) ;
int angle = CalculateAngle(StartX , StartY , EndX , EndY );
// This selects the midpoint of edge of the rectangle to rotate around (weird system)
myRectangle.RenderTransformOrigin = new Point(0.5, 0);
angle = angle - 180;
RotateTransform rotateTransform1 = new RotateTransform(angle, 0 , 0 );
myRectangle.RenderTransform = rotateTransform1;
if (color)
partiallyTransparentSolidColorBrush = new SolidColorBrush(Colors.Blue);
else
partiallyTransparentSolidColorBrush = new SolidColorBrush(Colors.Red);
partiallyTransparentSolidColorBrush.Opacity = 0.4;
myRectangle.Fill = partiallyTransparentSolidColorBrush;
MovementCanvas1.Children.Clear();
MovementCanvas1.Children.Add(myRectangle);
Canvas.SetTop(myRectangle, StartY);
Canvas.SetLeft(myRectangle, StartX);
DrawArrowhead(color, EndX, EndY, angle + 90, width);
ShowUnitCenter(MovementArrowList[0]);
}
Note that this code selects a point in the middle of the edge to rotate the rectangle:
// This selects the midpoint of edge of the rectangle to rotate around (weird system)
myRectangle.RenderTransformOrigin = new Point(0.5, 0);
The problem is that I can't find that point with the arrowhead (triangle). Here's the code that draws the arrowhead:
public void DrawArrowhead(bool color, double x, double y, int angle, int width)
{
x += width /2 ;
width = width + (width / 2);
//Add the Polygon Element
Polygon myPolygon = new Polygon();
myPolygon.Opacity = 0.4;
if (color)
{
myPolygon.Fill = new SolidColorBrush(Colors.Blue);
myPolygon.Stroke = System.Windows.Media.Brushes.Blue;
}
else
{
myPolygon.Fill = new SolidColorBrush(Colors.Red);
myPolygon.Stroke = System.Windows.Media.Brushes.Red;
}
myPolygon.StrokeThickness = 0;
RotateTransform rotateTransform1 = new RotateTransform(angle, 0, 0);
myPolygon.RenderTransform = rotateTransform1;
// This selects the midpoint of edge of the triangle to rotate around (weird system)
myPolygon.RenderTransformOrigin = new Point(0.0, 0.5);
System.Windows.Point Point1 = new System.Windows.Point(0, 0);
System.Windows.Point Point2 = new System.Windows.Point(width / 2, width / 2);
System.Windows.Point Point3 = new System.Windows.Point(0,width);
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(Point1);
myPointCollection.Add(Point2);
myPointCollection.Add(Point3);
myPolygon.Points = myPointCollection;
MovementCanvas1.Children.Add(myPolygon);
Canvas.SetTop(myPolygon, y );
Canvas.SetLeft(myPolygon, x );
}
Note the myPointCollection that creates the triangle. The problem is that I've tried almost every conceivable combination of values in RenderTransformOrigin to find the point that (center bottom of triangle) to use for the rotation point. Nothing seems to be working out.
Can anybody suggest the correct value?
Edit Solved
I solved it by changing the points of the triangle. That was easier than trying to figure out the rotation point.
Changing the points that made up the triangle solved the problem. This was easier than trying to find the rotation point.
Firstly, for context, I'm a beginner in C# and I'm playing around with forms.
I have attempted to draw a rectangle to a panel ("myPanel") on a form ("Form1") but there is a margin or some sort of padding which I cannot remove.
I have set the "padding" and "margin" properties of "myPanel" to 0 with no success.
The code is:
namespace Forms___Playing_with_Graphics
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void myPanel_Paint(object sender, PaintEventArgs e)
{
// rectangle, slightly smaller than size of panel
int topLeftx = myPanel.Location.X;
int topLefty = myPanel.Location.Y;
int width = myPanel.Size.Width - 5;
int height = myPanel.Size.Height - 5;
Graphics g = e.Graphics;
Rectangle r = new Rectangle(topLeftx, topLefty, width, height);
Pen p = new Pen(Color.Black, 5F);
g.DrawRectangle(p, r);
}
}
}
A screenshot of the result:
How do I remove this padding between the rectangle and the inside left and top edges? My naive expectation was for the rectangle to start in the very top-left corner.
Any help would be greatly appreciated.
Top left corner has coordinates x = 0, y = 0. But you should also keep in mind width of rectangle border. If you want rectangle border to fit exactly to the panel which contains it, then you should step inside half of border width:
private void myPanel_Paint(object sender, PaintEventArgs e)
{
float borderWidth = 5f;
float topLeftx = borderWidth / 2;
float topLefty = borderWidth / 2;
float width = panel2.ClientSize.Width - borderWidth;
float height = panel2.ClientSize.Height - borderWidth;
Graphics g = e.Graphics;
Pen pen = new Pen(Color.Black, borderWidth);
g.DrawRectangle(pen, topLeftx, topLefty, width, height);
}
Result:
I have a Form that contain a panel, and in this panel I draw shapes, like rectangles and circles, I need to zoom into this shapes, I saw couple options but most of them using PictureBox. Should I use Bitmap creating the panel area as a bitmap and change the zooming factor ?? would this help me also further if I want to have Panning and not draw images not into the fit in the panel size.
Here is a snapshot of my code
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = panel1.CreateGraphics();
SolidBrush myBrush = new SolidBrush(Color.Black);
Pen p = new Pen(Color.Black);
int RecScale = 1;
foreach (CircuitData.ResistorRow resistorRow in ResistorData.Resistor)
{
RectangleF rec = new RectangleF((float)(resistorRow.CenterX - resistorRow.Length / 2), (float)(resistorRow.CenterY - resistorRow.Width/ 2), (float)resistorRow.Length, (float)resistorRow.Width);
float orientation = 360 - (float)resistorRow.Orientation;
PointF center = new PointF((float)resistorRow.CenterX, (float)resistorRow.CenterY);
PointF[] points = CreatePolygon(rec, center, orientation);
if (!Double.IsNaN(resistorRow.HiX) && !Double.IsNaN(resistorRow.HiY))
{
g.FillEllipse(myBrush, (float)resistorRow.HiX - 5 , (float)resistorRow.HiY - 5, 10, 10);
g.DrawLine(p, new PointF((float)resistorRow.HiX, (float)resistorRow.HiY), center);
}
g.FillPolygon(myBrush, points);
}
}
Can a sample code be provided.
Many Thanks
Jp
Here is a way to scale the drawing by scaling the Graphics object:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.ScaleTransform(zoom, zoom);
// some demo drawing:
Rectangle rect = panel1.ClientRectangle;
g.DrawEllipse(Pens.Firebrick, rect);
using (Pen pen = new Pen(Color.DarkBlue, 4f)) g.DrawLine(pen, 22, 22, 88, 88);
}
Here we store the zoom level:
float zoom = 1f;
Here we set it and update the Panel:
private void trackBar1_Scroll(object sender, EventArgs e)
{
// for zooming between, say 5% - 500%
// let the value go from 50-50000, and initialize to 100 !
zoom = trackBar1.Value / 100f;
panel1.Invalidate();
}
Two example screenshots:
Note how nicely this scales the Pen widths as well. Turning on antialiasing would be a good idea..: g.SmoothingMode = SmoothingMode.AntiAlias;
Since you're drawing from scratch, couldn't you resize you drawing base on zoom factor?
You could multiply your drawing dimensions by your zoom factor. Assuming your zoom factor would be:
0.5 for 50 % zoom (which would reduce the drawing size)
1.0 for 100% (Real size)
1.5 for 150 % (bigger size), you could calc the width this way:
object.Width = originalWidth * zoomFactor;
I draw the ellipse with the code as shown below. How can I make the height of the red color is inside the ellipse can be changed for example from 0% -100%. If 0% the meanings the level of red height is empty. If 50% the meanings height level of the red color is half of the ellipse. If 100% the meanings height level of the red color is full. Thank You.
private void panel1_Paint(object sender, PaintEventArgs e)
{
Rectangle r1= new Rectangle(10, 130, 60, 60);
// Create solid brush.
SolidBrush redBrush = new SolidBrush(Color.Red);
// Create location and size of ellipse.
float x = 20F;
float y = 20F;
float width = 80.0F;
float height = 200.0F;
// Fill ellipse on screen.
e.Graphics.FillEllipse(redBrush, x, y, width, height);
}
Please, try the following code:
void panel1_Paint(object sender, PaintEventArgs e)
float percent = 0.75f;
RectangleF bounds = new RectangleF(20, 20, 80, 200);
FillEllipse(e.Graphics, bounds, percent);
}
static void FillEllipse(Graphics g, RectangleF bounds, float percent) {
g.DrawEllipse(Pens.Red, bounds);
g.SetClip(new RectangleF(
bounds.X,
bounds.Y + (1f - percent) * bounds.Height,
bounds.Width,
percent * bounds.Height));
g.FillEllipse(Brushes.Red, bounds);
g.ResetClip();
}
I am using OnPaint method in my class Class1 : Panel.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
}
to rotate and draw rectangle I am using
Matrix m = new Matrix();
m.RotateAt(90, rotationPoint);
g.Transform = m;
g.FillRectangle(Brushes.Black, rectangle)
the problem is, that rotation isn't working as I want it to.
Red square is rotation point and it's located in the middle-top of rectangle. How to set x, y and rotation point so rotation would work properly?
After rotating at 90 degress it should look like this
red pixel is still at the same location.
Rotation point is not the point, which you want to rotate. It is point, around which graphics is rotated. So if you draw a rectangle on the top of the graphics and want to rotate it (rectangle) - then you should set rotation point as center of graphics and rotate image to 90 degrees.
Here is example, that does almost what you want:
base.OnPaint(e);
var g = e.Graphics;
var width = g.VisibleClipBounds.Width;
var height = g.VisibleClipBounds.Height;
var rotationPoint = new PointF(width / 2, height / 2); ;
// draw center point
g.FillRectangle(Brushes.Red, new RectangleF(rotationPoint.X - 5, rotationPoint.Y - 5, 10, 10));
using (var path = new GraphicsPath())
{
var rectangle = new RectangleF((width - 10) / 2, 0, 10, 10);
var m = new Matrix();
m.RotateAt(90, rotationPoint);
path.AddRectangle(rectangle);
path.Transform(m);
// draw rotated point
g.FillPath(Brushes.Black, path);
}