c# Dynamic panel on mouse - c#

I am making a N*M size SUDOKU game. Every number are on a button.
When the program start all button is empty and I would like if I click to a button it is make a little panel on it with buttons for each number to choose one.
private void adatB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
Panel szamok = new Panel
{
Location = MousePosition,
Size = new Size(100, 100)
};
Controls.Add(szamok);
TableLayoutPanel minitabla = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = szorzat,
RowCount = szorzat,
};
for (int i = 0; i < szorzat; i++)
{
minitabla.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
minitabla.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
}
szamok.Controls.Add(minitabla);
Button[,] szamokB = new Button[meret[0], meret[1]];
int d = 1;
for (int i = 0; i < meret[0]; i++)
{
for (int j = 0; j < meret[1]; j++)
{
szamokB[i, j] = new Button();
szamokB[i, j].Tag= hely[0]+","+hely[1];
szamokB[i, j].Text = d.ToString();
szamokB[i, j].Dock = DockStyle.Fill;
szamokB[i, j].Click += szamokB_Click;
minitabla.Controls.Add(szamokB[i, j], i, j);
d++;
}
}
}
private void szamokB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
adatB[hely[0], hely[1]].Text = button.Text;
}
The problem with it when I click a button the pane isn't created.
meret[0] variable is the N, meret[1] is M, adatB is the arry of buttons with the positons in tag.
And If I choosed the number how can I close that panel?

First of all, you should calculate the mouseposition correctly.
From MSDN:
Gets the position of the mouse cursor in screen coordinates.
You should use something like this:
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y)
You will probably need this, to bring your panel to the front:
Controls.Add(szamok);
szamok.BringToFront();
To close the panel you can store the chooser panel and you can remove it from the controls later, use something like this:
public partial class Form1 : Form
{
private Panel myPanel = null;
private void adatB_Click(object sender, EventArgs e)
{
...
Panel szamok = new Panel
{
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y),
Size = new Size(100, 100)
};
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
}
this.myPanel = szamok;
Controls.Add(szamok);
szamok.BringToFront();
...
}
private void szamokB_Click(object sender, EventArgs e)
{
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
this.myPanel = null;
}
...
}
}

Related

How to access to a specific PictureBox.EventHandler that was created programmatically?

I am making a Scorebar from 1-10 where every number is one picture of a small grey cube.
Like this:
🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛ (This would be a score of 5)
Now I want to change the cube images to green ones, when the MouseDown Event is triggered, but I don't know who to tell the program.
Pic of Scorebar
private void BtnDebug_Click(object sender, EventArgs e)
{
int xPos = 200;
int yPos = 100;
PictureBox[] ScoreGameplay = new PictureBox[100];
for (int i = 0; i < 10; i++)
{
ScoreGameplay[i] = new PictureBox();
ScoreGameplay[i].Name = "ScoreGameplay" + i;
ScoreGameplay[i].Size = new Size(18, 18);
ScoreGameplay[i].Location = new Point(xPos, yPos);
ScoreGameplay[i].Image = Image.FromFile(#"img\icons\score_empty.png");
ScoreGameplay[i].MouseEnter += new EventHandler(Score_MouseEnter);
ScoreGameplay[i].MouseLeave += new EventHandler(Score_MouseLeave);
ScoreGameplay[i].MouseDown += new MouseEventHandler(Score_MouseDown);
this.Controls.Add(ScoreGameplay[i]);
xPos += 18;
}
This part works without an issue, but here we go:
private void Score_MouseDown(object sender, EventArgs e)
{
if (sender is PictureBox pBox)
{
// ???
}
}
How do I tell know which Index of the Array in BtnDebug_Click has triggered the MouseDown?
For example:
The 7th PictureBox has been clicked; now I want to change the images from PictureBoxes 1-7 to the green ones.
Anyone has a smart solution for this?
Simply you can do that
private void BtnDebug_Click(object sender, EventArgs e)
{
int xPos = 200;
int yPos = 100;
PictureBox[] ScoreGameplay = new PictureBox[100];
for (int i = 0; i < 10; i++)
{
ScoreGameplay[i] = new PictureBox();
ScoreGameplay[i].Name = $"ScoreGameplay{i}";
ScoreGameplay[i].Size = new Size(18, 18);
ScoreGameplay[i].Location = new Point(xPos, yPos);
ScoreGameplay[i].Image = Image.FromFile(#"img\icons\score_empty.png");
ScoreGameplay[i].MouseEnter += new EventHandler(Score_MouseEnter);
ScoreGameplay[i].MouseLeave += new EventHandler(Score_MouseLeave);
ScoreGameplay[i].MouseDown += new MouseEventHandler(Score_MouseDown);
this.Controls.Add(ScoreGameplay[i]);
xPos += 18;
}
}
and in Score_MouseDown
private void Score_MouseDown(object sender, EventArgs e)
{
string imageName = ((PictureBox)sender).Name; // get the name of the clicked image
string imageIndex = imageName.Substring(13); // get the text after 13 chars
}

Add label under button in a flowLayoutPanel

I need to dynamically create buttons with labels under them in a flowLayoutPanel when i drop a file onto the form. But how do I set the label position to be under the button since the FLP is arranging the controls by itself.. ?
What I've tried:
void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach (string s in fileList)
{
Button button = new Button();
button.Click += new EventHandler(this.button_Click);
fl_panel.Controls.Add(button);
Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
Bitmap bmp = icon.ToBitmap();
button.BackgroundImage = bmp;
button.Width = 60;
button.Height = 75;
button.FlatStyle = FlatStyle.Flat;
button.BackgroundImageLayout = ImageLayout.Stretch;
int space = 5;
int Yy = button.Location.Y;
int Xx = button.Location.X;
Label label = new Label();
label.Location = new Point(Yy + space, Xx);
//label.Margin.Top = button.Margin.Bottom;
fl_panel.Controls.Add(label);
}
}
The best idea I know of is to implement a custom control that contains both a button and a label that are arranged correctly. Then add the custom control to the FlowLayoutPanel.
public class CustomControl:Control
{
private Button _button;
private Label _label;
public CustomControl(Button button, Label label)
{
_button = button;
_label = label;
Height = button.Height + label.Height;
Width = Math.Max(button.Width, label.Width);
Controls.Add(_button);
_button.Location = new Point(0,0);
Controls.Add(_label);
_label.Location = new Point(0, button.Height);
}
}
You can then add to it like this:
for (int i = 0; i < 10; i++)
{
CustomControl c = new CustomControl(new Button {Text = "Button!"}, new Label {Text = "Label!"});
fl_panel.Controls.Add(c);
}
EDIT:
If you want to listen to button events, try this:
for (int i = 0; i < 10; i++)
{
var button = new Button {Text = "Button " + i};
CustomControl c = new CustomControl(button, new Label {Text = "Label!"});
button.Click += buttonClicked;
fl_panel.Controls.Add(c);
}
...
private void buttonClicked(object sender, EventArgs e)
{
MessageBox.Show(((Button) sender).Text);
}

Get text from dynamically created TextBox

I have a button when clicked creates textboxes dynamically:
for (int i = 0; i < length; i++)
{
Name.Add(new TextBox());
System.Drawing.Point locate = new System.Drawing.Point(137, 158 + i * 25);
(Name[i] as TextBox).Location = locate;
(Name[i] as TextBox).Size = new System.Drawing.Size(156, 20);
StartTab.Controls.Add(Name[i] as TextBox);
}
I want to get the text entered in Name[i] convert to a string then set it to labels
You can use Control.ControlCollection.Find.
UPDATED:
TextBox txtName = (TextBox)this.Controls.Find("txtNameOfTextbox", true)[0];
if (txtName != null)
{
return txtName.Text;
}
You don't say what type that Name is, it looks like a list of some sort. Try using a List<TextBox> that way you can just access the TextBox properties directly. Something like this. I am also not sure what Control that StartTab is, so I just used a Panel for this test code. (you should also be aware that Name masks the Form's Name property that is why I changed your list to name)
public partial class Form1 : Form
{
List<TextBox> name = new List<TextBox>();
int length = 5;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < length; i++)
{
name.Add(new TextBox() { Location = new System.Drawing.Point(137, 158 + i * 25),
Size = new System.Drawing.Size(156, 20) });
StartTab.Controls.Add(name[i]);
}
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < length; i++)
{
StartTab.Controls.Add(new Label() {Location = new System.Drawing.Point(name[i].Location.X + name[i].Width + 20,
name[i].Location.Y),
Text = name[i].Text,
AutoSize = true });
}
}
}

how to place my button?

I have a problem with my C# WinForm project.
In my project I have a function to draw a square, and I have a function that makes buttons at run time. What I want to do is that the button will place on the square.
I try to use 2 arrays; one gets the x location of the square, and the other gets the y location.
The button is placed at the x and y location one by one in columns but its place them diagonal.
int[] locationx = new int[100];
int[] locationy = new int[100];
int monex = 0;
int money = 0;
private void DrawAllSquares()//z,k its many square its going to draw
{
int tempy = y;
for (int i = 0; i < z; i++)
{
DrawingSquares(x, y);
for (int j = 0; j < k - 1; j++)
{
locationy[money] = tempy;
money++;
tempy += 60;
DrawingSquares(x, tempy);
}
x += 120;
locationx[monex] = x;
monex++;
tempy = y;
}
}
private void button2_Click(object sender, EventArgs e)
{
Button myText = new Button();
myText.Tag = counter;
//changeplace();
myText.Location = new Point(locationx[monex2], locationy[money2]);
monex2++;
money2++;
buttonList.AddLast(myText);
myText.Text = Convert.ToString(textBox3.Text);
this.Controls.Add(myText);
buttons[counter] = myText;
myText.BringToFront();
counter++;
}
You need do add created button to Form Controls collection.
private void button2_Click(object sender, EventArgs e)
{
Button myText = new Button();
myText.Tag = counter;
myText.Location = new Point(locationx[monex2], locationy[money2]);
Controls.Add(myText); // Assuming that handler 'button2_Click' is in your Form class.
// rest of your code
}
EDIT:
Button myText = new Button();
myText.Click += button2_Click;

How to add buttons dynamically to my form?

I want to create 10 buttons on my form when I click on button1. No error with this code below but it doesnt work either.
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < buttons.Capacity; i++)
{
this.Controls.Add(buttons[i]);
}
}
You aren't creating any buttons, you just have an empty list.
You can forget the list and just create the buttons in the loop.
private void button1_Click(object sender, EventArgs e)
{
int top = 50;
int left = 100;
for (int i = 0; i < 10; i++)
{
Button button = new Button();
button.Left = left;
button.Top = top;
this.Controls.Add(button);
top += button.Height + 2;
}
}
It doesn't work because the list is empty. Try this:
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < 10; i++)
{
Button newButton = new Button();
buttons.Add(newButton);
this.Controls.Add(newButton);
}
}
You could do something like this:
Point newLoc = new Point(5,5); // Set whatever you want for initial location
for(int i=0; i < 10; ++i)
{
Button b = new Button();
b.Size = new Size(10, 50);
b.Location = newLoc;
newLoc.Offset(0, b.Height + 5);
Controls.Add(b);
}
If you want them to layout in any sort of reasonable fashion it would be better to add them to one of the layout panels (i.e. FlowLayoutPanel) or to align them yourself.
Two problems- List is empty. You need to add some buttons to the list first. Second problem: You can't add buttons to "this". "This" is not referencing what you think, I think. Change this to reference a Panel for instance.
//Assume you have on your .aspx page:
<asp:Panel ID="Panel_Controls" runat="server"></asp:Panel>
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < buttons.Capacity; i++)
{
Panel_Controls.Controls.Add(buttons[i]);
}
}
use button array like this.it will create 3 dynamic buttons bcoz h variable has value of 3
private void button1_Click(object sender, EventArgs e)
{
int h =3;
Button[] buttonArray = new Button[8];
for (int i = 0; i <= h-1; i++)
{
buttonArray[i] = new Button();
buttonArray[i].Size = new Size(20, 43);
buttonArray[i].Name= ""+i+"";
buttonArray[i].Click += button_Click;//function
buttonArray[i].Location = new Point(40, 20 + (i * 20));
panel1.Controls.Add(buttonArray[i]);
} }
I had the same doubt and came up with the following contribution:
int height = this.Size.Height;
int width = this.Size.Width;
int widthOffset = 10;
int heightOffset = 10;
int btnWidth = 100; // Button Widht
int btnHeight = 40; // Button Height
for (int i = 0; i < 50; ++i)
{
if ((widthOffset + btnWidth) >= width)
{
widthOffset = 10;
heightOffset = heightOffset + btnHeight
var button = new Button();
button.Size = new Size(btnWidth, btnHeight);
button.Name = "" + i + "";
button.Text = "" + i + "";
//button.Click += button_Click; // Button Click Event
button.Location = new Point(widthOffset, heightOffset);
Controls.Add(button);
widthOffset = widthOffset + (btnWidth);
}
else
{
var button = new Button();
button.Size = new Size(btnWidth, btnHeight);
button.Name = "" + i + "";
button.Text = "" + i + "";
//button.Click += button_Click; // Button Click Event
button.Location = new Point(widthOffset, heightOffset);
Controls.Add(button);
widthOffset = widthOffset + (btnWidth);
}
}
Expected Behaviour:
This will generate the buttons dinamically and using the current window size, "break a line" when the button exceeds the right margin of your window.
First, you aren't actually creating 10 buttons. Second, you need to set the location of each button, or they will appear on top of each other. This will do the trick:
for (int i = 0; i < 10; ++i)
{
var button = new Button();
button.Location = new Point(button.Width * i + 4, 0);
Controls.Add(button);
}
You can't add a Button to an empty list without creating a new instance of that Button.
You are missing the
Button newButton = new Button();
in your code plus get rid of the .Capacity

Categories