DragDrop button text in C# (WinForm) - c#

My goal is to have multiple buttons whose text can be switched on the screen through dragging the text from one button to another (it's not necessary that the buttons themselves be switched, only the text on them, although if it's easier to switch the buttons themselves, that's fine). I have tried to follow this MSDN article but as soon as I actually begin to drag, I get a "no" symbol (an O with a / through it). Am I missing something? (Code below)
Thanks in advance!
public partial class Form1 : Form
{
Button button1 = new Button();
Button button2 = new Button();
public Form1()
{
InitializeComponent();
button1.Text = "Button 1";
button2.Text = "Button 2";
button2.Location = new Point(100, 0);
this.Controls.Add(button1);
this.Controls.Add(button2);
button1.MouseDown += new MouseEventHandler(button_MouseDown);
button2.MouseDown += new MouseEventHandler(button_MouseDown);
button1.DragEnter += new DragEventHandler(button_DragEnter);
button2.DragEnter += new DragEventHandler(button_DragEnter);
button1.DragDrop += new DragEventHandler(button_DragDrop);
}
private void button_MouseDown(object sender, MouseEventArgs e)
{
((Button)sender).DoDragDrop(((Button)sender).Text, DragDropEffects.Move);
}
private void button_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void button_DragDrop(object sender, DragEventArgs e)
{
//I'm not sure what goes here, but I can figure that out through experimentation
}
}

So it turns out I just had to do some more research. Adding button.AllowDrop = true for both buttons solved the issue

Related

C# Forms Mouse Hover Not firing in controls?

I am trying to write a code on Mouse_Hover for Button
private void Button_MouseHover(object sender, EventArgs e){
Button b = (Button)sender;
toolTip1.Show("Click ME!!", b);
}
But toolTip1 is not showing!!
after this I try to use MouseHover In another controls and it did not work and I try To use
MessageBox , but it did not work even , and I double check Events for Button (and other controls)
in properties tab.
You don't have to wire up controls to use the mouse hover event in order to use a tooltip. MSDN has some useful guidance, the essence of which is "add a tooltip to your form, assign the tooltip to the button"
This is a way to solve your problem:
public partial class Form1 : Form
{
private System.Windows.Forms.ToolTip toolTip1;
public Form1()
{
InitializeComponent();
this.components = new System.ComponentModel.Container();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
Button myBtn = new Button();
this.Controls.Add(myBtn);
myBtn.Location = new Point(10, 10);
myBtn.MouseEnter += new EventHandler(myBtn_MouseEnter);
myBtn.MouseLeave += new EventHandler(myBtn_MouseLeave);
}
void myBtn_MouseEnter(object sender, EventArgs e)
{
Button btn = (sender as Button);
if (btn != null)
{
this.toolTip1.Show("Hello!!!", btn);
}
}
void myBtn_MouseLeave(object sender, EventArgs e)
{
Button btn = (sender as Button);
if (btn != null)
{
this.toolTip1.Hide(btn);
}
}

C# - How to find out which dynamic button was clicked?

I am writing a program where I dynamically add buttons, I do that by storing them in a Dictionary to get a certain value from them later on (the color of the background).
I need to set a Click event on every one of them, but every Click event has to be a little different, as by clicking the button, a ColorDialog pops up and changes the background of the button.
Is there a way to know which button I clicked? In the following code, the button1 click event adds the other buttons and sets the EventHandler for each of them, what should be the code for the EventHandler? Thank you so much in advance guys.
int i = 0;
Dictionary<int, Button> buttonDictionary = new Dictionary<int, Button>();
Dictionary<int, ColorDialog> colorsDictionary = new Dictionary<int ColorDialog>();
public void button1_Click(object sender, EventArgs e)
{
i++;
buttonDictionary.Add(i, new Button());
buttonDictionary[i].Click += new EventHandler(Click);
this.Controls.Add(buttonDictionary[i]);
}
public void Click(object sender, EventArgs e)
{
//Somehow get the int key of the button that was clicked???? (in this case: int j)
int j;
if (!colorsDictionary.ContainsKey(j))
{
colorsDictionary.Add(j, new ColorDialog());
}
if (colorsDictionary[j].ShowDialog() == DialogResult.OK)
{
buttonDictionary[j].BackColor = colorsDictionary[j].Color;
}
}
The code is made just for adding the buttons, I will be glad for any kind of help, thank you guys!
Well, a direct answer to your question is: cast the sender to a Button
Button pressedButton = (Button) sender;
and then check to which button of the dictionary it matches:
foreach (var entry in buttonDictionary)
{
if (entry.Value == pressedButton)
{
j = entry.Key;
break;
}
}
However, that's overly complex for what you want to achieve. It would be much easier if you had a direct relationship between the button and the color picker:
Dictionary<Button, ColorDialog> buttonDictionary = new Dictionary<Button, ColorDialog>();
Then fill it like this:
public void button1_Click(object sender, EventArgs e)
{
i++;
var button = new Button();
this.Controls.Add(button);
button.Click += new EventHandler(Click);
buttonDictionary.Add(button, null);
}
And later access it with
public void Click(object sender, EventArgs e)
{
Button pressedButton = (Button) sender;
ColorDialog dialog = buttonDictionary[pressedButton];
if (dialog == null)
{
dialog = new ColorDialog();
buttonDictionary[pressedButton] = dialog;
}
if (dialog.ShowDialog() == DialogResult.OK)
{
pressedButton.BackColor = dialog.Color;
}
}
Even more, the question is why you would need so many ColorDialgos, since it should be possible with one dialog only. You can get rid of i, j, all dictionaries and most handling as well. IMHO, the following should be sufficient:
public void button1_Click(object sender, EventArgs e)
{
var button = new Button();
Controls.Add(button);
button.Click += Click;
}
public void Click(object sender, EventArgs e)
{
Button pressedButton = (Button) sender;
ColorDialog dialog = new ColorDialog {Color = pressedButton.BackColor};
if (dialog.ShowDialog() == DialogResult.OK)
{
pressedButton.BackColor = dialog.Color;
}
}
Bonus info:
I don't exactly know what you want to achieve. But your buttons will all be in the same place, overlapping each other. To avoid this, drag a flow layout panel onto the form and then add the buttons to the flow layout:
flowLayoutPanel1.Controls.Add(button);
This will ensure that your buttons are nicely arranged.

Adding multiple non url Hyperlinks in RichTextBox C# to throw an event for each

Starting with the context... I am making a game Text Adventure game using C# Windows Form because I am a beginner and it is what I understand. (I do not want to use something like Inform, this is a project so I can learn.)
That being said, I would like to avoid using buttons and most of the content will be displayed in a richtextbox. I have looked around and I can't find anything that suits my needs. (Yes I have looked here: http://www.codeproject.com/Articles/9196/Links-with-arbitrary-text-in-a-RichTextBox but it doesn't handle multiple links well and it has other issues. )
My aim would basically be to use the links in the richtextbox as a navigation menu and for contextual purpose. I would like to be able to have text before and after the link, like if it was incorporated in the text itself.
Here is my code:
public partial class Form1 : Form
{
Room1 Room1 = new Room1();
public Form1()
{
InitializeComponent();
PlayArea.Text = "Welcome to the Game! Would you like to start?";
Game();
}
private void Game()
{
PlayArea.Text = "Welcome Back!";
button1.Text = "Start?";
button1.Click += Button1_Beginning;
void Button1_Beginning(object sender, EventArgs e)
{
button1.Click -= Button1_Beginning;
FirstRoom();
}
}
private void FirstRoom()
{
PlayArea.Text = Room1.Description;
button1.Text = "ClickMe!";
button1.Click += Button1_FirstRoom;
void Button1_FirstRoom(object sender, EventArgs e)
{
PlayArea.Text = String.Empty;
}
button2.Text = "Return";
button2.Click += Button2_FirstRoom;
void Button2_FirstRoom(object sender, EventArgs e)
{
button1.Click -= Button1_FirstRoom;
button2.Click -= Button2_FirstRoom;
ClearButtonText();
Game();
}
}
private void ClearButtonText()
{
foreach (var button in Controls.OfType<Button>())
{
button.Text = string.Empty;
}
}
For now, some things are activated by buttons, my goal is to remove that and have most things activated by hyperlinks.
Any idea how to achieve this?

How can I move a button with mousehover?

I've made a TextBox that retains what you type, and when you click the button associated it gives you a messagebox. When people want to click no, I want the button to change location so people cannot click it so they are forced to click yes,Well the problem is mousehover works just 1 time and does not go back to initial position after i leave my pointer out. Can you help me? Here is the code:
{
MsgBox = new CustomMsgBox();
MsgBox.label1.Text = Text;
MsgBox.button1.Text = btnOK;
MsgBox.button2.Text = btnCancel;
MsgBox.Text = Caption;
result = DialogResult.No;
MsgBox.ShowDialog();
return result;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Location = new Point(25, 25);
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.Location = new Point(+50, +50);
}
private void button2_MouseLeave(object sender, EventArgs e)
{
button2.Location = new Point(+100, +100);
}
You should not use MouseLeave because when you move the button in the MouseHover, the button will move so the mouse will leave the button area. Meaning the No button will flip from the original position to the new position and back again all the time. What you could do is use the MouseMove to see if the user moved away from the area where the Button2 was originally and then move it back. Or include a non-visible control, like an empty label behind the button2. And set the MouseLeave on the label instead.
Oh and don't forget to set button2.TabStop = false, otherwise the user can use tab to get to the button.
Made a quick and dirty proof of concept for this, hope that helps ;)
public partial class Form1 : Form
{
private Rectangle buttonRectangle;
private bool checkRectangle = false;
public Form1()
{
InitializeComponent();
button2.TabStop = false;
buttonRectangle = button2.ClientRectangle;
buttonRectangle.Location = button2.Location;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Location = new Point(25, 25);
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.Location = new Point(50, 50);
checkRectangle = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (!checkRectangle)
{
return;
}
if (!buttonRectangle.Contains(e.X, e.Y))
{
checkRectangle = false;
button2.Location = buttonRectangle.Location;
}
}
}
The buttonRectangle is set based on where the button is found during construction of the form. It has a contains method that can be used to check if a certain point (mouse move) is contained in it.
I also set the button2.TabStop to false so it will no longer be active during tab cycles.
When your hover (can change this to mouse enter, but just used your code) event fires, I set checkRectangle to true. I use this in the mouse move event handler to see if anything should be checked (prevents from doing anything when the mouse is not "over" the button).
If the buttonRectangle and the mouse location are not intersected this means we left the area where the button was, so we can move the button back.

How can i take dynamically created buttons' name when they are clicked?

I'm making a mahjong game and I'm totally new at C#, I wonder how i can take a button's name when it's clicked. All the buttons are created dynamically in the form.
public Button createButton(node x)
{
Button nButton;
nButton = new Button();
nButton.Name = x.info.ToString();
nButton.Text = x.info.ToString();
nButton.Width = 55;
nButton.Height = 75;
nButton.Visible = true;
if (x.isValid())
nButton.Enabled = true;
else
nButton.Enabled = false;
nButton.Click += new System.EventHandler(n1_click);
return nButton;
}
in the form i take buttons with this code
myButton = createButton(tp);
myButton.Location = new System.Drawing.Point(25 , 25);
this.Controls.Add(myButton);
The first argument to the event handler is the sender, you can cast that to a Button and then access the Name property.
Here is a small example of the event handler.
private void Button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (button != null)
{
// Do something with button.Name
}
}
Edit: As Hans mentioned in the comments, using as could hide a potential bug. Using the as operator as in the example above will ensure that if you inadvertently wire this handler to an event of another control the code will handle it graciously and not throw an InvalidCastException, but there-in lies a problem as well, because this now silently fails you might not pickup a bug in your code. If the exception was thrown you would have realized there is a problem and been able to track it down. So the updated code would be something like this.
private void Button_Click(object sender, EventArgs e)
{
// If sender is not a Button this will raise an exception
Button button = (Button)sender;
// Do something with button.Name
}
With the following code you can get the button that was clicked
protected void Button1_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
}
on the function which handles the click "n1_click"
private void n1_click(object sender, EventArgs e)
{
Button temp = (Button)sender;
string neededText = temp.Text;
}

Categories