So i am having a project where i need to drag and drop different pictureboxes and make an existing copy of them to the form when i drag drop them. My problem is that i cannot move the selected "picture box" after it is created on the form. I would like to have an option where i can move any picturebox that is dragged not like dragging at a position and keeping it at that position.
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
p = (PictureBox)sender;
p.Tag = p.Location;
downPoint = e.Location;
p.Parent = this;
p.BringToFront();
}
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
p = (PictureBox)sender;
if (e.Button == MouseButtons.Left)
{
p.Left += e.X - downPoint.X ;
p.Top += e.Y - downPoint.Y ;
}
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
p = (PictureBox)sender;
PictureBox PB = new PictureBox();
Control c = GetChildAtPoint(new Point(p.Left -1, p.Top));
if (c == null) c = this;
Point newLoc = c.PointToClient(p.Parent.PointToScreen(p.Location));
PB.Parent = c;
PB.Location = newLoc;
;
p.Parent.Controls.Add(PB); // <-- add new PB to the form!
p.Location = (Point)p.Tag;
// put the original back where it started:
}
Put the events to the new picturebox
PB.MouseMove += new MouseEventHandler(pictureBox_MouseMove);
PB.MouseDown += new MouseEventHandler(picturebOX_MouseDown);
PB.MouseUp += new MouseEventHandler(picturebOX_MouseUp);
Related
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;
}
}
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 am trying to make an application in which i have 7 Pictureboxes and i want to drag drop one each time i click then move the mouse on the form. I did make it to some extend by moving the picture-box on the form but i cannot keep the original image. When i drag drop a picture box i want to drag drop just a copy not the whole picture box on the form. Any help will be greatly appreciated. Kind regards.
public Form1()
{
controller = Controller.getController();
InitializeComponent();
this.AllowDrop = true;
this.pbOR.MouseDown += pbOR_MouseUp;
}
private void pbOR_MouseDown(object sender, MouseEventArgs e)
{
downPoint = e.Location;
pbOR.Parent = this;
pbOR.BringToFront();
}
private void pbOR_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pbOR.Left += e.X - downPoint.X;
pbOR.Top += e.Y - downPoint.Y;
}
}
private void pbOR_MouseUp(object sender, MouseEventArgs e)
{
Control c = GetChildAtPoint(new Point(pbOR.Left - 1, pbOR.Top));
if (c == null) c = this;
Point newLoc = c.PointToClient(pbOR.Parent.PointToScreen(pbOR.Location));
pbOR.Parent = c;
pbOR.Location = newLoc;
}
I'm dragging and dropping the pictureBox in FlowlayoutPanel but the event return the position in form...I need this position in FlowLayoutPanel(the pictureBoxes are in FlowLayoutPanel and are dragging and drop there)
public Form1()
{
InitializeComponent();
flowLayoutPanel1.AllowDrop = true;
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
picBox = (PictureBox)sender;
if (picBox.Image != null)
{
var dragImage = new Bitmap((Bitmap)picBox.Image, picBox.Size);
IntPtr icon = dragImage.GetHicon();
Cursor.Current = new Cursor(icon);
DoDragDrop(picBox.Image, DragDropEffects.Copy);
}
}
}
void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Bitmap)))
e.Effect = DragDropEffects.Copy;
}
// Occurs when the user releases the mouse over the drop target
void Form1_DragDrop(object sender, DragEventArgs e)
{
MessageBox.Show("Posicao x " + e.Y + "Posicao Y " + e.Y);//reutrn the position in form, not in flowLayoutPanel
}
You have to use this method:
var point = flowLayoutPanel1.PointToClient(new Point(e.X, e.Y));
This translates screen position coordinates into control one, more info here.
I have a problem with DragDrop.
private void Form0_Load(object sender, EventArgs e)
{
PictureBox panel1 = new PictureBox();
PictureBox panel2 = new PictureBox();
mainPanel.Dock = DockStyle.Fill;
this.Controls.Add(mainPanel);
panel1.Location = new Point(10, 10);
panel1.Size = new System.Drawing.Size(500, 300);
panel1.BorderStyle = BorderStyle.FixedSingle;
Button b2 = new Button();
b2.Location = new Point(10, 10);
panel2.Controls.Add(b2);
panel2.Location = new Point(10, 10);
panel2.Size = new System.Drawing.Size(200, 100);
panel2.BorderStyle = BorderStyle.FixedSingle;
foreach (Control c in panel1.Controls)
{
c.MouseDown += new MouseEventHandler(control_MouseDown);
c.MouseMove += new MouseEventHandler(control_MouseMove);
c.MouseUp += new MouseEventHandler(control_MouseUp);
c.AllowDrop = true;
}
panel1.AllowDrop = true;
panel1.DragEnter += new DragEventHandler(container_DragEnter);
panel1.DragDrop += new DragEventHandler(container_DragDrop);
panel1.DragOver += new DragEventHandler(container_DragOver);
foreach (Control c in panel2.Controls)
{
c.MouseDown += new MouseEventHandler(control_MouseDown);
c.MouseMove += new MouseEventHandler(control_MouseMove);
c.MouseUp += new MouseEventHandler(control_MouseUp);
c.AllowDrop = true;
}
panel2.AllowDrop = true;
panel2.DragEnter += new DragEventHandler(container_DragEnter);
panel2.DragDrop += new DragEventHandler(container_DragDrop);
panel2.DragOver += new DragEventHandler(container_DragOver);
mainPanel.Controls.Add(panel1);
mainPanel.Controls.Add(panel2);
mainPanel.Controls.Add(pb);
}
private void control_MouseDown(object sender, MouseEventArgs e)
{
Control c = sender as Control;
isDragging = true;
clickOffsetX = e.X;
clickOffsetY = e.Y;
}
private void control_MouseMove(object sender, MouseEventArgs e)
{
Control c = sender as Control;
if (isDragging == true)
{
c.Left = e.X + c.Left - clickOffsetX;
c.Top = e.Y + c.Top - clickOffsetY;
if (c.Location.X + clickOffsetX > c.Parent.Width ||
c.Location.Y + clickOffsetY > c.Parent.Height ||
c.Location.X + clickOffsetX < 0 ||
c.Location.Y + clickOffsetY < 0)
c.DoDragDrop(c, DragDropEffects.Move);
}
}
private void control_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
void container_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void container_DragEnter(object sender, DragEventArgs e)
{
//e.Effect = DragDropEffects.Move;
//if (e.Data.GetDataPresent(typeof(Bitmap)))
//{
// e.Effect = DragDropEffects.Copy;
//}
//else
//{
// e.Effect = DragDropEffects.None;
//}
}
private void container_DragDrop(object sender, DragEventArgs e)
{
Control c = e.Data.GetData(e.Data.GetFormats()[0]) as Control;
PictureBox p = sender as PictureBox;
mycontrol = c;
isDragging = false;
if (c != null)
{
c.Location = p.PointToClient(new Point(e.X, e.Y));
p.Controls.Add(c);
}
}
This is a working example. But I can't do drop Controls from parent to child control. What is a magic? How to drop control to another control (from panel1 to panel2 in my example).
There are some answers here in SO, which may help you:
See this Move controls when Drag and drop on panel in C#
this is a complete example on how to host the Form Designer:
Tailor Your Application by Building a Custom Forms Designer with .NET
Check this one also for simple lable drag drop:
Basic drag and drop in WinForms