My idea is to add a button/custom marker to the coordinate i click on the form but i have no idea how to implement it.
private void AddLogo_Click_1(object sender, EventArgs e)
{
}
private void MapBrowser_MouseUp(object sender, MouseEventArgs e)
{
textBox1.Text = "X-" + e.X + "Y- " + e.Y;
var button1 = new Button { Location = new Point(e.X, e.Y) };
Controls.Add(button1);
}
This allow me to get a button everytime i click on the form, but my idea is to click on the form and then press the addlogo button to add a button to the form.
you need a variables in the form
bool _placeButton = false;
int _xButton;
int _yButton;
then
private void MapBrowser_MouseUp(object sender, MouseEventArgs e)
{
textBox1.Text = "X-" + e.X + "Y- " + e.Y;
_xButton = e.X;
_yButton = e.Y;
_placeButton = true;
}
and finally
private void AddLogo_Click_1(object sender, EventArgs e)
{
if(_placeButton)
{
_placeButton = false;
var button1 = new Button { Location = new Point(_xButton, _yButton) };
Controls.Add(button1);
}
}
Related
I haven't found a similar question but maybe I haven't found the good keys word, my apologies if there is one.
It's my first question on this website so please tell me if I should ask my question differently! :)
I'm trying to create some pictureblock in a panel thanks to a button and drag and drop them but I don't know how to call the pictureBlock by clicking on it
I tried this, I'm able to create the block by clicking on a button and I'm able the move the last block created but I can't move other blocks.
I tried many solutions but I don't understand how to call the pictureblock i clicked on instead of calling "structures[i]"
Thank you for your help!
form 1 :
private void button1_Click(object sender, EventArgs e)
{
//ajout_panel1();
ajout_panelI();
}
private void pictureBox_Click(object sender, MouseEventArgs e)
{
pictureBox_MouseDown(this.structures[i], e);
pictureBox_MouseMove(this.structures[i], e);
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.structures[i-1].Left = e.X + this.structures[i-1].Left - MouseDownLocation.X;
this.structures[i-1].Top = e.Y + this.structures[i-1].Top - MouseDownLocation.Y; }
}
}
Form 1 designer:
private void ajout_panelI()
{
System.Windows.Forms.PictureBox newbox = new System.Windows.Forms.PictureBox();
this.structures.Add(newbox);
panel1.SuspendLayout();
SuspendLayout();
panel1.Controls.Add(this.structures[i]);
this.structures[i].BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.structures[i].Location = new System.Drawing.Point(pos_x, pos_y);
this.structures[i].Name = pic_name();
this.structures[i].Size = new System.Drawing.Size(200, 100);
this.structures[i].TabIndex = 0;
this.structures[i].MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox_MouseDown);
this.structures[i].MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox_MouseMove);
this.structures[i].Paint += new System.Windows.Forms.PaintEventHandler(this.panel2_Paint_1);
panel1.ResumeLayout(false);
ResumeLayout(false);
pos_y = pos_y + 150;
i++;
}
public System.Windows.Forms.Panel panel1;
private System.Windows.Forms.PictureBox panel2;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Button button1;
public int i = 0;
private int pos_x =30;
private int pos_y =30;
private List<System.Windows.Forms.PictureBox> structures { get; set; } = new List<System.Windows.Forms.PictureBox>();
private System.Windows.Forms.PictureBox structure;
private string name;
I have a user control with 10 small buttons (20 x 20). I am using the following code to allow the user to drag each button along the x axis only.
I then want to save its X location to a list which can be saved as part of an XML file and then be loaded with the same button locations the next time the app runs. For some reason, I can't save button location. Even the message box doesn't show. What am I doing wrong?
private Point p;
private void button2_mousedown(object sender, MouseEventArgs e)
{
string buttonName = ((Button)sender).Name;
Button b1 = ((Button)sender);
if (e.Button == MouseButtons.Left)
{
p = e.Location;
}
}
private void button2_mousemove(object sender, MouseEventArgs e)
{
string buttonName = ((Button)sender).Name;
Button b1 = ((Button)sender);
if (e.Button == MouseButtons.Left)
{
b1.Left = e.X + b1.Left - p.X;
}
int idx = int.Parse(buttonName) - 1;
scriptIconLocation[idx] = b1.Left;
//MessageBox.Show(scriptIconLocation[idx].ToString(), "saved location");
savedSettings.ScriptIconLocation = scriptIconLocation;
saveSettingsXML(savedSettings);
}
To move buttons use the following code. Subscribe each button on this event handler.
private void Button_MouseMove(object sender, MouseEventArgs e)
{
var button = (Button)sender;
if (e.Button == MouseButtons.Left)
{
button.Left = PointToClient(Cursor.Position).X;
}
}
The MouseDown event is not necessary.
Do not save data in xml with every mouse movement, because it's very inefficient.
Do this, for example, when the form is closed. And read the data when the form is loaded.
private void Form1_Load(object sender, EventArgs e)
{
// Array of your buttons.
var buttons = userControl.Controls.OfType<Button>().ToArray();
var xml = XElement.Load("buttons.xml").Elements("X").ToArray();
for (int i = 0; i < buttons.Length; i++)
{
buttons[i].Left = (int)xml[i];
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
var buttons = userControl.Controls.OfType<Button>();
var xml = new XElement("Buttons",
buttons.Select(b => new XElement("X", b.Left)));
xml.Save("buttons.xml");
}
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();
}
}
How I can get text of a control that was created at runtime?
private void button1_Click(object sender, EventArgs e)
{
Button btn = new Button();
btn.Top = 50;
btn.Left = 50;
btn.Name = "mybtn";
btn.Text = "My button";
this.Controls.Add(btn);
}
private void button2_Click(object sender, EventArgs e)
{
Console.WriteLine(mybtn.text); // error
}
var b = this.Controls.OfType<Button>().FirstOrDefault(b => b.Name == "mybtn");
if (b == null) { return; }
Console.WriteLine(b.Text);
private void button2_Click(object sender, EventArgs e)
{
// find mybtn
Button mybtn = this.Controls.FirstOrDefault(i => i.Name == "mybtn") as Button;
if (mybtn != null)
{
Console.WriteLine(mybtn.Text);
}
}
Either declare newly created control as a class member(property or field):
Button btn ;
private void button1_Click(object sender, EventArgs e)
{
btn = new Button();
btn.Top = 50;
btn.Left = 50;
btn.Name = "mybtn";
btn.Text = "My button";
this.Controls.Add(btn);
}
OR
search it through the form controls:
private void button2_Click(object sender, EventArgs e)
{
Console.WriteLine(this.Controls.Cast<Control>().Single(p=>p.Name == "mybtn").Text);
}
private void button2_Click(object sender, EventArgs e)
{
Console.WriteLine(this.Controls.Find("myBtn", false).FirstOrDefault().Text);
}