How to connect pictureboxes with connecting line - c#

first sorry for my English. I am programming application in windows forms. It is something like Packet Tracer. I have four buttons. When I click on them, they dynamicaly create pictureboxes with picture of Router or Switch,.... Each time I click on the button, new picture box(Switch or Router,...), is created. I can also move with this pictureboxes by mouse.
I need to create a button, which connects selected pictureboxes with line(Cable). This pictureboxes should be selected by click on them. It sholud be able to move with this objects(movable line).
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
PictureBox[] picturebox = new PictureBox[100];
public Form1()
{
InitializeComponent();
}
private void router_Click(object sender, EventArgs e)
{
++a;
picturebox[a] = new PictureBox();
picturebox[a].Name = "picturebox" + a;
picturebox[a].Location = new Point(0 + (a-1) *100,100);
picturebox[a].Size = new Size(70, 70);
picturebox[a].BorderStyle = BorderStyle.None;
picturebox[a].SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(picturebox[a]);
picturebox[a].Image = Image.FromFile(#"D:\\router.jpg");
picturebox[a].Refresh();
picturebox[a].MouseDown += new MouseEventHandler(picMouseDown);
picturebox[a].MouseMove += new MouseEventHandler(picMouseMove);
picturebox[a].MouseUp += new MouseEventHandler(picMouseUp);
}
private void Form1_Load(object sender, EventArgs e)
{
}
int x = 0;
int y = 0;
bool drag = false;
private void picMouseDown(object sender, MouseEventArgs e)
{
// Get original position of cursor on mousedown
x = e.X;
y = e.Y;
drag = true;
}
private void picMouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
PictureBox pb = (PictureBox)sender;
// Get new position of picture
pb.Top += e.Y - y;
pb.Left += e.X - x;
pb.BringToFront();
}
}
private void picMouseUp(object sender, MouseEventArgs e)
{
drag = false;
}
private void switch1_Click(object sender, EventArgs e)
{
++b;
picturebox[b] = new PictureBox();
picturebox[b].Name = "picturebox" + b;
picturebox[b].Location = new Point(0 + (b - 1) * 100, 180);
picturebox[b].Size = new Size(70, 70);
picturebox[b].BorderStyle = BorderStyle.None;
picturebox[b].SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(picturebox[b]);
picturebox[b].Image = Image.FromFile(#"D:\HP ProBook 450\Desktop\Grafika\switch1.png");
picturebox[b].Refresh();
picturebox[b].MouseDown += new MouseEventHandler(picMouseDown);
picturebox[b].MouseMove += new MouseEventHandler(picMouseMove);
picturebox[b].MouseUp += new MouseEventHandler(picMouseUp);
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void pc_Click(object sender, EventArgs e)
{
++c;
picturebox[c] = new PictureBox();
picturebox[c].Name = "picturebox" + c;
picturebox[c].Location = new Point(0 + (c - 1) * 100, 260);
picturebox[c].Size = new Size(70, 70);
picturebox[c].BorderStyle = BorderStyle.None;
picturebox[c].SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(picturebox[c]);
picturebox[c].Image = Image.FromFile(#"D:\HP ProBook 450\Desktop\pc.jpg");
picturebox[c].Refresh();
picturebox[c].MouseDown += new MouseEventHandler(picMouseDown);
picturebox[c].MouseMove += new MouseEventHandler(picMouseMove);
picturebox[c].MouseUp += new MouseEventHandler(picMouseUp);
}
private void server_Click(object sender, EventArgs e)
{
++d;
picturebox[d] = new PictureBox();
picturebox[d].Name = "picturebox" + d;
picturebox[d].Location = new Point(0 + (d - 1) * 100, 340);
picturebox[d].Size = new Size(70, 70);
picturebox[d].BorderStyle = BorderStyle.None;
picturebox[d].SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(picturebox[d]);
picturebox[d].Image = Image.FromFile(#"D:\HP ProBook 450\Desktop\server.png");
picturebox[d].Refresh();
picturebox[d].MouseDown += new MouseEventHandler(picMouseDown);
picturebox[d].MouseMove += new MouseEventHandler(picMouseMove);
picturebox[d].MouseUp += new MouseEventHandler(picMouseUp);
}
}
}
THank you for your help.

You need to invalidate the parent when you add a picturebox or when you move a picturebox:
(picMouseMove and 4 times in the click handlers, it would be better to use 1 function)
Invalidate();
This is an example OnPaint, drawing lines between the pictureboxes as they are located in the Controls collection: (your picturebox array seems very weird, you always add controls at index 1, always overwriting the previous entry?! i'd suggest using a List if you need to keep a reference to them)
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var pictureBoxes = Controls.OfType<PictureBox>().ToArray();
if (pictureBoxes.Length > 1)
{
for (int i = 1; i < pictureBoxes.Length; i++)
{
DrawLineBetween(e.Graphics, pictureBoxes[i - 1], pictureBoxes[i]);
}
}
}
This function can be used to draw a line between 2 of your boxes:
private void DrawLineBetween(Graphics g, PictureBox from, PictureBox to)
{
g.DrawLine(Pens.Black,
new Point(from.Left + from.Width / 2, from.Top + from.Height / 2),
new Point(to.Left + to.Width / 2, to.Top + to.Height / 2));
}
----- full sample below -----
I refactored your full example, and added the code above to start you off with a working example:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
List<PictureBox> pictureboxes = new List<PictureBox>();
public Form1()
{
InitializeComponent();
}
private void AddPictureBox(string imagePath)
{
var pb = new PictureBox();
pb.Name = "picturebox" + pictureboxes.Count;
pb.Location = new Point(pictureboxes.Count * 100, 100);
pb.Size = new Size(70, 70);
pb.BorderStyle = BorderStyle.None;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(pb);
pb.Image = Image.FromFile(imagePath);
pb.Refresh();
pb.MouseDown += new MouseEventHandler(picMouseDown);
pb.MouseMove += new MouseEventHandler(picMouseMove);
pb.MouseUp += new MouseEventHandler(picMouseUp);
pictureboxes.Add(pb);
Invalidate();
}
private void router_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\\router.jpg");
}
private void Form1_Load(object sender, EventArgs e)
{
}
int x = 0;
int y = 0;
bool drag = false;
private void picMouseDown(object sender, MouseEventArgs e)
{
// Get original position of cursor on mousedown
x = e.X;
y = e.Y;
drag = true;
}
private void picMouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
PictureBox pb = (PictureBox)sender;
// Get new position of picture
pb.Top += e.Y - y;
pb.Left += e.X - x;
pb.BringToFront();
Invalidate();
}
}
private void picMouseUp(object sender, MouseEventArgs e)
{
drag = false;
}
private void switch1_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\Grafika\switch1.png");
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void pc_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\pc.jpg");
}
private void server_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\server.png");
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (pictureboxes.Count > 1)
{
var arr = pictureboxes.ToArray();
for (int i = 1; i < arr.Length; i++)
{
DrawLineBetween(e.Graphics, arr[i - 1], arr[i]);
}
}
}
private void DrawLineBetween(Graphics g, PictureBox from, PictureBox to)
{
g.DrawLine(Pens.Black,
new Point(from.Left + from.Width / 2, from.Top + from.Height / 2),
new Point(to.Left + to.Width / 2, to.Top + to.Height / 2));
}
}
}

Related

Collision detection with duplicated picturebox

For my school I have to do a little project.
The aim of the project is to do a game which spawns different rectangles and you have to click them.
If you click them you recive points and the rectangle gets replaced with a new one.
And every timer tick the box gets bigger.
We have to use pictureboxes.
Now my question is:
How can I make a detection to indicate a picturebox which colides with the panel-border or with a other picture box.
The problem is, that the picboxes are getting duplicated.
So how can I solve this problem?
This is my code:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BoxClicker
{
public partial class Form1 : Form
{
private Random rndColor = new Random();
private Random rndCreation = new Random();
public Form1()
{
InitializeComponent();
}
private void CreateBox()
{
PictureBox gamebox = new PictureBox();
gamebox.Size = new Size(20, 20);
gamebox.Location = new Point(rndCreation.Next(0, pnlSpiel.Width - 30), rndCreation.Next(0, pnlSpiel.Height - 30));
gamebox.BackColor = Color.FromArgb(rndCreation.Next(0, 255), rndCreation.Next(0, 255), rndCreation.Next(0, 255));
pnlSpiel.Controls.Add(gamebox);
gamebox.Click += pictureBox1_Click;
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < numValues.Value; i++)
{
CreateBox();
}
tmrResize.Start();
txtNotification.Text = "Klicke auf die erscheinenden Boxen um Punkte zu sammeln!";
btnStart.Visible = false;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void pictureBox1_Click(object sender, EventArgs e)
{
CreateBox();
PictureBox gamebox = sender as PictureBox;
int addPoints = gamebox.Width;
txtPoints.Text = (Convert.ToInt32(txtPoints.Text) + addPoints).ToString();
if ((Convert.ToInt32(txtBiggestBox.Text) < addPoints))
{
txtBiggestBox.Text = (Convert.ToString(addPoints));
}
pnlSpiel.Controls.Remove(sender as PictureBox);
}
private void button1_Click_1(object sender, EventArgs e)
{
if (tmrEasterEgg.Enabled)
{
tmrEasterEgg.Stop();
BackColor = Color.LightGray;
}
else
{
tmrEasterEgg.Start();
}
}
private void tmrEasterEgg_Tick(object sender, EventArgs e)
{
Color randomColor = Color.FromArgb(rndColor.Next(256), rndColor.Next(256), rndColor.Next(256));
BackColor = randomColor;
}
private void tmrResize_Tick(object sender, EventArgs e)
{
for (int i = 0; i < pnlSpiel.Controls.Count; i++)
{
PictureBox gamebox = pnlSpiel.Controls[i] as PictureBox;
gamebox.Size = new Size(gamebox.Size.Width + 1, gamebox.Size.Height + 1);
}
}
private void btnReset_Click(object sender, EventArgs e)
{
pnlSpiel.Controls.Clear();
txtNotification.Text = "Das Spiel wurde zurückgesetzt";
txtPoints.Text = "0";
btnStart.Visible = true;
}
}
}
You can have the collision detection in your CreateBox method. And decide whether to add the object or not in there.
Like this:
private void CreateBox()
{
Rectangle bounds = new Rectangle(rndCreation.Next(0, pnlSpiel.Width - 30),
rndCreation.Next(0, pnlSpiel.Height - 30),
20, 20);
bool pBDoIntersect = false;
foreach (Control picturebox in pnlSpiel.Controls)
{
if (bounds.IntersectsWith(picturebox.Bounds))
{
pBDoIntersect = true;
}
}
if (!pBDoIntersect)
{
PictureBox gamebox = new PictureBox();
gamebox.Size = new Size(bounds.Width, bounds.Height);
gamebox.Location = new Point(bounds.X, bounds.Y);
gamebox.BackColor = Color.FromArgb(rndCreation.Next(0, 255), rndCreation.Next(0, 255), rndCreation.Next(0, 255));
pnlSpiel.Controls.Add(PB);
gamebox.Click += pictureBox1_Click;
}
else
{
// spawn in another place?
}
}

Referencing multiple instantiated pictureboxes

I'm very new to C# but trying to learn so bear with me if my syntax isn't accurate. I am able to create a picturebox with a button and it appears on screen. I can then move it around the screen just fine with a mouse down / mouse move function. I then hit the button to instantiate another picturebox to be created and can move that one around as well, but when I try to move the first picturebox the second one moves instead and goes insane. Is there a way to reference or tag the boxes on instantiation so that when I click on any of them I can move them around the screen?
public partial class Form1 : Form
{
Point MP;
private static Control PB;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int picSizeX = Properties.Resources.police.Width / 3;
int picSizeY = Properties.Resources.police.Height / 3;
PictureBox pb = new PictureBox();
pb.Location = new Point(100, 100);
pb.Size = new Size(picSizeX, picSizeY);
pb.Image = new Bitmap(Properties.Resources.police);
pb.SizeMode = PictureBoxSizeMode.StretchImage;
Controls.Add(pb);
pb.Tag = "veh";
PB = pb;
pb.MouseDown += Pb_MouseDown;
pb.MouseMove += Pb_MouseMove;
pb.MouseHover += Pb_MouseHover;
}
private void Pb_MouseHover(object sender, EventArgs e)
{
PB.MouseHover += PB_MouseHover;
}
private void PB_MouseHover(object sender, EventArgs e)
{
}
private void Pb_MouseDown(object sender, MouseEventArgs e)
{
MP = e.Location;
}
private void Pb_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
PB.Left = e.X + PB.Left - MP.X;
PB.Top = e.Y + PB.Top - MP.Y;
}
}
}
Actually there is no need to have Control at class level.
In the event method there is a parameter called object sender that contains a reference to the control/object that raised the event.
Point MP;
//private Control PB; //commented out as it is not required
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int picSizeX = Properties.Resources.police.Width / 3;
int picSizeY = Properties.Resources.police.Height / 3;
PictureBox pb = new PictureBox();
pb.Location = new Point(100, 100);
pb.Size = new Size(picSizeX, picSizeY);
pb.Image = new Bitmap(Properties.Resources.police);
pb.SizeMode = PictureBoxSizeMode.StretchImage;
Controls.Add(pb);
pb.Tag = "veh";
//PB = pb;
pb.MouseDown += Pb_MouseDown;
pb.MouseMove += Pb_MouseMove;
pb.MouseHover += Pb_MouseHover;
}
private void Pb_MouseHover(object sender, EventArgs e)
{
Control pbObj = sender as PictureBox; //sender refers to control that raised the event
pbObj.MouseHover += PB_MouseHover;
}
private void PB_MouseHover(object sender, EventArgs e)
{
}
private void Pb_MouseDown(object sender, MouseEventArgs e)
{
MP = e.Location;
}
private void Pb_MouseMove(object sender, MouseEventArgs e)
{
Control pbObj = sender as PictureBox; //sender refers to control that raised the event
if (e.Button == MouseButtons.Left)
{
pbObj.Left = e.X + pbObj.Left - MP.X;
pbObj.Top = e.Y + pbObj.Top - MP.Y;
}
}

C# Drawing Lines with TextBox

I have an application where I can add a textBox on the screen and move it.
When I add more than two textBox, I double-click on top of two textbox and a line connects both.
My question is: How to make the line move along with the textBox?
code below:
public partial class principal : Form
{
int posMouseFormX, posMouseFormY;
int posMouseTXT_X, posMouseTXT_Y;
int posActTXT_X, posActTXT_Y;
bool txtPressionado = false;
int qntClick;
Pen myPen = new Pen(System.Drawing.Color.DarkGreen, 1);
Graphics Tela;
List<TextBox> listaNós = new List<TextBox>();
List<Point> origem = new List<Point>();
List<Point> destino = new List<Point>();
Point ponto1, ponto2;
ContextMenuStrip menu;
public principal()
{
InitializeComponent();
menu = new ContextMenuStrip();
menu.Items.Add("Remover");
menu.ItemClicked += new ToolStripItemClickedEventHandler(contextMenuStrip1_ItemClicked);
}
//TextBox event when the mouse moves over the TXT
private void txtMover_MouseMove(object sender, MouseEventArgs e)
{
TextBox textBox = sender as TextBox;
posMouseFormX = textBox.Location.X + e.Location.X;
posMouseFormY = textBox.Location.Y + e.Location.Y;
if (txtPressionado == true) moverTxt(textBox);
}
//Retrieve the X and Y coordinates where clicked within the component.
private void txtMover_MouseDown(object sender, MouseEventArgs e)
{
posMouseTXT_X = e.Location.X;
posMouseTXT_Y = e.Location.Y;
txtPressionado = true;
}
private void txtMover_MouseUp(object sender, MouseEventArgs e)
{
txtPressionado = false;
}
private void moverTxt(TextBox a)
{
a.Location = new System.Drawing.Point(posMouseFormX - posMouseTXT_X, posMouseFormY - posMouseTXT_Y);
posActTXT_X = a.Location.X;
posActTXT_Y = a.Location.Y;
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
}
//insert new TextBox
private void sb_Inserir_No_Click(object sender, EventArgs e)
{
TextBox noFilho = new TextBox();
noFilho = new System.Windows.Forms.TextBox();
noFilho.Location = new System.Drawing.Point(379, 284);
noFilho.Size = new System.Drawing.Size(100, 30);
noFilho.TabIndex = 20;
noFilho.Text = "";
noFilho.BackColor = Color.White;
posActTXT_X = noFilho.Location.X;
posActTXT_Y = noFilho.Location.Y;
this.Controls.Add(noFilho);
noFilho.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
noFilho.DoubleClick += new System.EventHandler(this.textBox1_Click);
noFilho.MouseUp += new System.Windows.Forms.MouseEventHandler(txtMover_MouseUp);
noFilho.MouseDown += new System.Windows.Forms.MouseEventHandler(txtMover_MouseDown);
noFilho.MouseMove += new System.Windows.Forms.MouseEventHandler(txtMover_MouseMove);
noFilho.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
noFilho.ContextMenuStrip = menu;
}
//event to resize the txt on the screen as the content.
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
Size size = TextRenderer.MeasureText(textBox1.Text, textBox1.Font);
textBox1.Width = size.Width + 10;
textBox1.Height = size.Height;
}
//Event to control the connection between two give us when double click on the textbox
private void textBox1_Click(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
int meio = textBox1.Size.Width / 2;
Tela = CreateGraphics();
qntClick = qntClick + 1;
if (this.qntClick == 1)
{
origem.Add(ponto1);
ponto1 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
}
if (this.qntClick == 2)
{
qntClick = 0;
destino.Add(ponto2);
ponto2 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
DesenhaSeta(Tela, ponto1, ponto2);
}
}
//draw arrow between two TXT
void DesenhaSeta(Graphics Tela, Point x, Point y)
{
myPen.StartCap = LineCap.Triangle;
myPen.EndCap = LineCap.ArrowAnchor;
Tela.DrawLine(myPen, x, y);
}
private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
//recuperando o controle associado com o contextmenu
Control sourceControl = menu.SourceControl;
DialogResult result = MessageBox.Show("Tem Certeza que deseja remover o nó selecionado?", "Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(result == DialogResult.Yes)
{
sourceControl.Dispose();
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Determine whether the key entered is the F1 key. Display help if it is.
if (e.KeyCode == Keys.Space)
{
TextBox textBox1 = sender as TextBox;
novoNó tela = new novoNó(textBox1.Text);
tela.Show();
}
}
}
Each control, TextBox included has a Move, event. Put an Invalidate() call there!
The lines should be drawn in the Paint event of the container that holds the TextBoxes, probably the Form; if it is the Form indeed call this.Invalidate().
Please move the line drawing code out of the DoubleClick event into the Paint event or else the lines will not persist, say minimize/maximize events or other situation, when the system has to redraw the application!
You probably will need to create a data structure to maintain information about which TextBox-pairs need to be connected, maybe a List<Tuple> or a List<someStructure>. This would get filled/modified in the DoubleClick event, then call this.Invalidate() and in the Form.Paint you have a foreach loop over the list of TextBox-pairs..
If you are drawing on the Form do make sure to turn DoubleBuffered on!
Update: To compare the reults here is a minimal example the expects two TextBoxes on a Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.DoubleBuffered = true;
pairs.Add(new Tuple<Control, Control>(textBox1, textBox2));
}
List<Tuple<Control, Control>> pairs = new List<Tuple<Control, Control>>();
Point mDown = Point.Empty;
private void Form2_Paint(object sender, PaintEventArgs e)
{
foreach (Tuple<Control, Control> cc in pairs)
drawConnection(e.Graphics, cc.Item1, cc.Item2);
}
void drawConnection(Graphics G, Control c1, Control c2)
{
using (Pen pen = new Pen(Color.DeepSkyBlue, 3f) )
{
Point p1 = new Point(c1.Left + c1.Width / 2, c1.Top + c1.Height / 4);
Point p2 = new Point(c2.Left + c2.Width / 2, c2.Top + c2.Height / 4);
G.DrawLine(pen, p1, p2);
}
}
void DragBox_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
void DragBox_MouseMove(object sender, MouseEventArgs e)
{
TextBox tb = sender as TextBox;
if (e.Button == MouseButtons.Left)
{
tb.Location = new Point(e.X + tb.Left - mDown.X, e.Y + tb.Top - mDown.Y);
}
}
void DragBox_MouseUp(object sender, MouseEventArgs e)
{
mDown = Point.Empty;
}
private void DragBox_Move(object sender, EventArgs e)
{
this.Invalidate();
}
}

I have two pictureBoxes in other sizes how can i make that when i click on one pictureBox it will draw a point on the smaller pictureBox?

This is my code but its not working not drawing points at all on pictureBox2.
public partial class Form1 : Form
{
private int counter;
private int pb1mouse_x;
private int pb1mouse_y;
private int pbsize_x;
private int pbsize_y;
public Form1()
{
InitializeComponent();
pbsize_x = pictureBox2.Width / pictureBox1.Width;
pbsize_y = pictureBox2.Height / pictureBox1.Height;
label4.Visible = false;
label5.Visible = false;
label6.Visible = false;
counter = 0;
pictureBox1.Load(#"d:\radar000075.png");
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
label4.Visible = true;
label4.Text = String.Format("X: {0}; Y: {1}", e.X, e.Y);
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
label5.Visible = true;
label5.Text = String.Format("X: {0}; Y: {1}", e.X, e.Y);
counter += 1;
label6.Visible = true;
label6.Text = counter.ToString();
pb1mouse_x = e.X;
pb1mouse_y = e.Y;
pb1mouse_x = pb1mouse_x * pbsize_x;
pb1mouse_y = pb1mouse_y * pbsize_y;
pictureBox2.Invalidate();
}
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
Pen p = new Pen(Color.Red);
var g = e.Graphics;
g.Clear(pictureBox1.BackColor);
g.DrawEllipse(p, new Rectangle(pb1mouse_x, pb1mouse_y, 10, 10));
}
}
You should be able to simply multiply by factors, i.e. smallBox.Width/largeBox.Width and smallBox.Height/largeBox.Height. Multiply the coordinates for the larger box by those factors and it will give you coordinates for the smaller box.
Edit:
This is what my code looks like:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace PBoxes
{
public partial class Form1 : Form
{
private float xFactor, yFactor;
List<PointF> points = new List<PointF>();
public Form1()
{
InitializeComponent();
xFactor = (float)pictureBox2.Width / pictureBox1.Width;
yFactor = (float)pictureBox2.Height / pictureBox1.Height;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
points.Add(new PointF(e.X * xFactor, e.Y * yFactor));
pictureBox2.Invalidate();
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
foreach (PointF pt in points)
{
e.Graphics.FillEllipse(Brushes.Red, pt.X, pt.Y, 3f, 3f);
}
}
private void pictureBox_SizeChanged(object sender, EventArgs e)
{
xFactor = (float)pictureBox2.Width / pictureBox1.Width;
yFactor = (float)pictureBox2.Height / pictureBox1.Height;
}
}
}

Draw lines on a picturebox using mouse clicks in C#

I'm trying to make a program that will draw lines over a picturebox using mouse clicks for the locations of where the line is to be drawn from and to. This is my current code:
public partial class Form1 : Form
{
int Drawshape;
private Point p1, p2;
List<Point> p1List = new List<Point>();
List<Point> p2List = new List<Point>();
public Form1()
{
InitializeComponent();
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
}
private void button1_Click(object sender, EventArgs e)
{
Drawshape = 1;
}
private void button2_Click(object sender, EventArgs e)
{
Drawshape = 2;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (Drawshape == 1)
{
if (p1.X == 0)
{
p1.X = e.X;
p1.Y = e.Y;
}
else
{
p2.X = e.X;
p2.Y = e.Y;
p1List.Add(p1);
p2List.Add(p2);
Invalidate();
p1.X = 0;
}
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics G = Graphics.FromImage(pictureBox1.Image);
if (Drawshape == 1)
{
using (var p = new Pen(Color.Blue, 4))
{
for (int x = 0; x < p1List.Count; x++)
{
G.DrawLine(p, p1List[x], p2List[x]);
}
}
}
}
At the moment it doesn't allow me to draw on the picturebox at all. How would that be possible?
Change Invalidate(); to pictureBox1.Invalidate();
You need to draw each line on the Image object (using Graphics.FromImage) after creating the line.
You also need to dispose the Graphics object in a using block.

Categories