How to create a form in shape of rhomb? - c#

How to create a form in shape of rhomb?
I managed to create a shape in form of ellipse with the help of this:
private void Form1_Load(object sender, EventArgs e)
{
System.Drawing.Drawing2D.GraphicsPath myPath = new System.Drawing.Drawing2D.GraphicsPath();
myPath.AddEllipse(45, 60, 200, 200);
Region myRegion = new Region(myPath);
this.Region = myRegion;
}
How can I do it but making rhomb?

Use myPath.AddLines instead of the myPath.AddEllipse:
private void Form1_Load(object sender, EventArgs e)
{
using (GraphicsPath myPath = new GraphicsPath())
{
myPath.AddLines(new[]
{
new Point(0, Height / 2),
new Point(Width / 2, 0),
new Point(Width, Height / 2),
new Point(Width / 2, Height)
});
Region = new Region(myPath);
}
}

Above answer by #Dmitry helped me a lot. However, it does not draw a complete rhombus, as claimed. The last segment is not drawn due to absent final point, which must coincide with the starting point. Line array should contain five points, not four.
I have made some corrections and come up with this function, which draws a rhombus withing a given rectangle:
private void DrawRhombus(Graphics graphics, Rectangle rectangle)
{
using (GraphicsPath myPath = new GraphicsPath())
{
myPath.AddLines(new[]
{
new Point(rectangle.X, rectangle.Y + (rectangle.Height / 2)),
new Point(rectangle.X + (rectangle.Width / 2), rectangle.Y),
new Point(rectangle.X + rectangle.Width, rectangle.Y + (rectangle.Height / 2)),
new Point(rectangle.X + (rectangle.Width / 2), rectangle.Y + rectangle.Height),
new Point(rectangle.X, rectangle.Y + (rectangle.Height / 2))
});
using (Pen pen = new Pen(Color.Black, 1))
graphics.DrawPath(pen, myPath);
}
}

Related

Creating vertical lines inside panel in WinForm

I am trying to create vertical lines inside a panel in my winform application. I am able to draw the lines but they are not what I am expecting to be. My requirements are:
The lines must be drawn from the middle of the panel vertically.
The lines must be drawn on both the sides with equal height.
The problem is when I am trying to draw the lines they are drawn from top of the panel and are upside down.
My target is to get something like:
This is how I am trying to do it:
public void DrawLines(System.Drawing.Graphics g, float height)
{
Pen thePen = new Pen(Color.Red, 1.0F);
PointF[] points1 =
{
new PointF(5,5),
new PointF(5, 50)
};
PointF[] points2 =
{
new PointF(7,5),
new PointF(7, 60)
};
PointF[] points3 =
{
new PointF(9,5),
new PointF(9, 55)
};
//Tried this as well
//PointF[] points1 =
// {
// new PointF(5,50),
// new PointF(5, 5)
// };
//PointF[] points2 =
// {
// new PointF(7,60),
// new PointF(7, 5)
// };
//PointF[] points3 =
// {
// new PointF(9,55),
// new PointF(9, 5)
// };
g.DrawLines(thePen, points1);
g.DrawLines(thePen, points2);
g.DrawLines(thePen, points3);
}
Right now I am calling this function on button click.
DrawLines(panel1.CreateGraphics(), 20.0F);
In real time this will be called inside a loop and line height will be passed as a parameter.
As already commented, Y coordinates are flipped when drawing on the Panel. You can test this by simply displaying mouse coordinates.
To draw the Lines you want to get the Middle of the panel and work from there. In your example you had an unused height variable, so i added funtionality to that. Here is a working example.
public MyForm()
{
InitializeComponent();
_myPen = new Pen(Color.Red, 1.0F);
}
private Pen _myPen;
private void DrawLines(Graphics g, int width = 0, int height = 0)
{
// Get the middle of the panel
int panelMiddle = panel.Height / 2;
// Lines going up from the mittle
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 5, height + panelMiddle -5),
new PointF(width + 5, height + panelMiddle - 50)
});
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 7, height + panelMiddle-5),
new PointF(width + 7, height + panelMiddle - 60)
});
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 9, height + panelMiddle-5),
new PointF(width + 9, height + panelMiddle - 55)
});
// Lines going down from the middle
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 5, height + panelMiddle +5),
new PointF(width + 5, height + panelMiddle + 50)
});
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 7, height + panelMiddle+5),
new PointF(width + 7, height + panelMiddle + 60)
});
g.DrawLines(_myPen,
new PointF[]
{
new PointF(width + 9, height + panelMiddle+5),
new PointF(width + 9, height + panelMiddle + 55)
});
}
private void panel_Paint(object sender, PaintEventArgs e)
{
DrawLines(e.Graphics);
DrawLines(e.Graphics,panel.Width - 14);
}

Can I do a circle Picture Box in C#? [duplicate]

How to round edges in picturebox control. I Want to get angles like ellipse have but i dont know how to do it. I Use C#. Thanks!
putting 1 Picture box on the form and write this code
also you can change the the minus number beside of Width and Height to get best result
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
gp.AddEllipse(0, 0, pictureBox1.Width - 3, pictureBox1.Height - 3);
Region rg = new Region(gp);
pictureBox1.Region = rg;
Yes, no problem, you can give a control an arbitrary shape with its Region property. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class OvalPictureBox : PictureBox {
public OvalPictureBox() {
this.BackColor = Color.DarkGray;
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
using (var gp = new GraphicsPath()) {
gp.AddEllipse(new Rectangle(0, 0, this.Width-1, this.Height-1));
this.Region = new Region(gp);
}
}
}
Round edges as in round corners?
If so check out http://social.msdn.microsoft.com/forums/en-US/winforms/thread/603084bb-1aae-45d1-84ae-8544386d58fd
Rectangle r = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
int d = 50;
gp.AddArc(r.X, r.Y, d, d, 180, 90);
gp.AddArc(r.X + r.Width - d, r.Y, d, d, 270, 90);
gp.AddArc(r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90);
gp.AddArc(r.X, r.Y + r.Height - d, d, d, 90, 90);
pictureBox1.Region = new Region(gp);
Thank you, Hans. But I also need a smooth look. I did some research on this subject, but I could not find a solution. Then I tried to do it myself and found the solution below. Maybe someone else needs it.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(0, 0, this.Width - 1, this.Height - 1);
Region = new Region(gp);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(new Pen(new SolidBrush(this.BackColor), 1), 0, 0, this.Width - 1, this.Height - 1);
}
}

Using a matrix to rotate rectangles individually

Having a bit of a drawing complication you would call it. My math is a bit rusty when it comes to Matrices and drawing rotations on shapes. Here is a bit of code:
private void Form1_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
DoRotation(e);
g.DrawRectangle(new Pen(Color.Black), r1);
g.DrawRectangle(new Pen(Color.Black), r2);
// draw a line (PEN, CenterOfObject(X, Y), endpoint(X,Y) )
g.DrawLine(new Pen(Color.Black), new Point((r1.X + 50), (r1.Y + 75)), new Point((/*r1.X + */50), (/*r1.Y - */25)));
this.lblPoint.Text = "X-pos: " + r1.X + " Y-pos: " + r1.Y;
//this.Invalidate();
}
public void DoRotation(PaintEventArgs e)
{
// move the rotation point to the center of object
e.Graphics.TranslateTransform((r1.X + 50), (r1.Y + 75));
//rotate
e.Graphics.RotateTransform((float)rotAngle);
//move back to the top left corner of the object
e.Graphics.TranslateTransform(-(r1.X + 50), -(r1.Y + 75));
}
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
case Keys.T:
rotAngle += 1.0f;
}
when I rotate (what I think should be r1) both r1 and r2 rotate. I need to be able to rotate each shape individually as I add more shapes.
I would use a function similar to this:
public void RotateRectangle(Graphics g, Rectangle r, float angle) {
using (Matrix m = new Matrix()) {
m.RotateAt(angle, new PointF(r.Left + (r.Width / 2),
r.Top + (r.Height / 2)));
g.Transform = m;
g.DrawRectangle(Pens.Black, r);
g.ResetTransform();
}
}
It uses a matrix to perform the rotation at a certain point, which should be the middle of each rectangle.
Then in your paint method, use it to draw your rectangles:
g.SmoothingMode = SmoothingMode.HighQuality;
//g.DrawRectangle(new Pen(Color.Black), r1);
//DoRotation(e);
//g.DrawRectangle(new Pen(Color.Black), r2);
RotateRectangle(g, r1, 45);
RotateRectangle(g, r2, 65);
Also, here is the line to connect the two rectangles:
g.DrawLine(Pens.Black, new Point(r1.Left + r1.Width / 2, r1.Top + r1.Height / 2),
new Point(r2.Left + r2.Width / 2, r2.Top + r2.Height / 2));
Using these settings:
private Rectangle r1 = new Rectangle(100, 60, 32, 32);
private Rectangle r2 = new Rectangle(160, 100, 32, 32);
resulted in:

Rounded edges in picturebox C#

How to round edges in picturebox control. I Want to get angles like ellipse have but i dont know how to do it. I Use C#. Thanks!
putting 1 Picture box on the form and write this code
also you can change the the minus number beside of Width and Height to get best result
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
gp.AddEllipse(0, 0, pictureBox1.Width - 3, pictureBox1.Height - 3);
Region rg = new Region(gp);
pictureBox1.Region = rg;
Yes, no problem, you can give a control an arbitrary shape with its Region property. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class OvalPictureBox : PictureBox {
public OvalPictureBox() {
this.BackColor = Color.DarkGray;
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
using (var gp = new GraphicsPath()) {
gp.AddEllipse(new Rectangle(0, 0, this.Width-1, this.Height-1));
this.Region = new Region(gp);
}
}
}
Round edges as in round corners?
If so check out http://social.msdn.microsoft.com/forums/en-US/winforms/thread/603084bb-1aae-45d1-84ae-8544386d58fd
Rectangle r = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
int d = 50;
gp.AddArc(r.X, r.Y, d, d, 180, 90);
gp.AddArc(r.X + r.Width - d, r.Y, d, d, 270, 90);
gp.AddArc(r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90);
gp.AddArc(r.X, r.Y + r.Height - d, d, d, 90, 90);
pictureBox1.Region = new Region(gp);
Thank you, Hans. But I also need a smooth look. I did some research on this subject, but I could not find a solution. Then I tried to do it myself and found the solution below. Maybe someone else needs it.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(0, 0, this.Width - 1, this.Height - 1);
Region = new Region(gp);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(new Pen(new SolidBrush(this.BackColor), 1), 0, 0, this.Width - 1, this.Height - 1);
}
}

Problem with a Moving & Rotating Map?

I have a image of a Map and a smaller PictureBox control.
I'm getting input from my joysyick. My the Y takes the image up and left
Adn the X actually rotates the image..
My problem is when i rotate the Image, the Y axis rotates with it, so when i move up again it wont really go up.. it will go the the new direction the Y axis points too..
Here is my code if you could understand my problam..
public void UpdateTurret()
{
while (js != null)
{
js.GetData();
Thread.Sleep(80);
MapY += js.State.Y;
MapRotation += js.State.X;
{
Image map = Properties.Resources.Map;
Bitmap bmp = (Bitmap)map.Clone();
Graphics g = Graphics.FromImage((Image)bmp);
g.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2 - (MapY / 2));
g.RotateTransform(MapRotation);
g.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2 + (MapY / 2));
g.DrawImage(bmp, 0, 0);
Graphics gfx = Graphics.FromImage((Image)bmp);
gfx.DrawPie(new Pen(Color.Blue, 5), bmp.Width/2 - 5, bmp.Height/2 - 5, 5, 5, 0, 360);
gfx.DrawImage(bmp, 0, MapY);
picBoxMap.Image = (Image)bmp;
float rot = MapRotation;
rot = (float)Math.Abs((rot - 360*Math.Ceiling(rot / 360)));
DrawString = (rot).ToString() + "° Y:" + MapY.ToString();
}
}
}
My problem now is that the rotation point is always centered, i want my rotation point to be the new position i reached.
So i figured out it should be like this:
g.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2 - MapY);
g.RotateTransform(MapRotation);
g.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2 + MapY);
But this cause another bug. Now when i rotate the Image, the Y axis rotates with it, so when i move up again it wont really go up.. it will go the the new direction the Y axis points too..
Anyone has an idea on solving this issue?
EDIT:
Here is my new code:
public void UpdateTurret()
{
while (js != null)
{
js.GetData();
Thread.Sleep(80);
MapY += js.State.Y;
MapRotation += js.State.X;
{
Image map = Properties.Resources.Map;
Size mapSize = map.Size;
Bitmap bmp = (Bitmap)map.Clone();
Graphics g = Graphics.FromImage((Image)bmp);
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-mapSize.Width / 2, -mapSize.Height / 2, MatrixOrder.Append);
transformMatrix.Rotate(MapRotation, MatrixOrder.Append);
transformMatrix.Translate(mapSize.Width / 2, mapSize.Height / 2, MatrixOrder.Append);
transformMatrix.Translate(0, MapY, MatrixOrder.Append);
g.Transform = transformMatrix;
g.DrawImage(bmp, 0,0);
picBoxMap.Image = (Image)bmp;
float rot = MapRotation;
rot = (float)Math.Abs((rot - 360*Math.Ceiling(rot / 360)));
DrawString = (rot).ToString() + "° Y:" + MapY.ToString();
}
}
//Draw Cross
Graphics gfx = picBoxMap.CreateGraphics();
Rectangle rc = picBoxMap.ClientRectangle;
gfx.DrawLine(Pens.Red, rc.Width / 2, rc.Height / 2 + 10, rc.Width / 2, rc.Height / 2 - 10);
gfx.DrawLine(Pens.Red, rc.Width / 2 + 10, rc.Height / 2, rc.Width / 2 - 10, rc.Height / 2);
}
My problem now is that after i move the map on the Y axis, the rotation point stays on the center point.
And look after i only rotated the map:
You can see i didn't move the Y axis but it did changed.. because the Rotation point is at the center of the image and not where to red cross is.
I need the rotation point to be at the same position of the red cross.
Possibly a better approach is to use the Matrix.Rotate() and Matrix.Translate() methods to get a matrix to set the Graphics.Transform to.
Then you can simply draw your map at the origin (ignoring moving and rotating it), and the graphics object will do the rest.
See the examples in the Matrix method links for more info. In their example they draw a rectangle, but you could easily draw your image instead.
In my unedited answer i was wrong. I've corrected my code below.
The key things to note are:
You want the point the map rotates at to vary according to where the player is, so you should translate the map first (since this will then effect where the rotation happens).
I've changed the code to use the RotateAt so it's easier to understand. This way we don't need to worry about the extra translations to get the rotation point at the origin then back again.
As you want the arrow keys to mean up with respect to the rotated image we can't do it as simply as normal. I've added Cos and Sin terms in, deduced using basic trigonometry.
I've now got 2 pictureboxes, the first shows only the translation, and the direction of the player, the second is a radar like view (which is what you're after). So, this answer has the 2 main map display types, fixed north in picturebox1, rotating north in picturebox2.
Arrow keys move the image, Q and E rotate it.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private PictureBox pictureBox1;
private PictureBox pictureBox2;
private Image imageToDraw = null;
private float imageRotation = 0.0f;
private PointF imageTranslation = new PointF();
public Form1()
{
InitializeComponent();
pictureBox1 = new PictureBox() { Top = 20, Left = 10, Width = 280, Height = 310, BorderStyle = BorderStyle.FixedSingle };
pictureBox2 = new PictureBox() { Top = 20, Left = pictureBox1.Right + 10, Width = 280, Height = 310, BorderStyle = BorderStyle.FixedSingle };
pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
pictureBox2.Paint += new PaintEventHandler(pictureBox2_Paint);
this.Controls.Add(pictureBox1);
this.Controls.Add(pictureBox2);
this.Controls.Add(new Label() { Text = "Left = translation only, Right = translation and rotation", Width = Width / 2 });
this.ClientSize = new Size(pictureBox2.Right + 10, pictureBox2.Bottom + 10);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Activated(object sender, EventArgs e)
{
try
{
imageToDraw = Image.FromFile("C:\\Map.jpg");
}
catch (Exception)
{
MessageBox.Show("Ensure C:\\Map.jpg exists!");
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (imageToDraw != null)
imageToDraw.Dispose();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
const float MoveSpeed = 5.0f;
switch (e.KeyCode)
{
case Keys.Q:
imageRotation -= 1.0f;
break;
case Keys.E:
imageRotation += 1.0f;
break;
case Keys.Up:
imageTranslation = new PointF(imageTranslation.X - (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y - (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Down:
imageTranslation = new PointF(imageTranslation.X + (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y + (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Left:
imageTranslation = new PointF(imageTranslation.X - (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y + (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Right:
imageTranslation = new PointF(imageTranslation.X + (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y - (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
}
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (imageToDraw != null)
{
e.Graphics.ResetTransform();
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-imageTranslation.X, -imageTranslation.Y);
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawImage(imageToDraw, Point.Empty);
transformMatrix = new Matrix();
transformMatrix.Translate(50, 50);
transformMatrix.RotateAt(-imageRotation, new PointF(20, 20));
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawString("^", new Font(DefaultFont.FontFamily, 40), Brushes.Black, 0, 0);
}
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
if (imageToDraw != null)
{
e.Graphics.ResetTransform();
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-imageTranslation.X, -imageTranslation.Y);
transformMatrix.RotateAt(imageRotation, new PointF(pictureBox1.Width / 2 + imageTranslation.X, pictureBox1.Height / 2 + imageTranslation.Y));
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawImage(imageToDraw, Point.Empty);
}
}
}
}

Categories

Resources