I have this piece of code, where it runs a function (MouseTracker) after clicking on a label
this MouseTracker, should capture a mouse position x and y after pressing the OK in dialog result.
namespace AdvancedStashHelper
{
public partial class Settings : Form
{
public int xTemp;
public int yTemp;
public Settings()
{
InitializeComponent();
}
private void MouseTracker()
{
while (true)
{
var result = MessageBox.Show("Move your cursor to position and press ENTER");
if (result == DialogResult.OK)
{
xTemp = MousePosition.X;
yTemp = MousePosition.Y;
}
break;
}
}
private void orbTransLabel_Click(object sender, EventArgs e)
{
Thread thread = new(MouseTracker);
thread.Start();
orbTransXPos.Text = xTemp.ToString();
}
private void orbAltLabel_Click(object sender, EventArgs e)
{
Thread thread = new(MouseTracker);
thread.Start();
}
}
}
The problem here it's, first time when you click on the label, nothing happens, but after you click the second time, the value is updated with previous mouse position.
This should function like this:
click on label
run the dialog that says to press enter to capture mouse position
update the values on form after pressing ok
do this for all labels with different mouse position values
thanks all for your info the code was simply as it is
namespace AdvancedStashHelper
{
public partial class Settings : Form
{
public int xTemp;
public int yTemp;
public Settings()
{
InitializeComponent();
}
private void MouseTracker()
{
var result = MessageBox.Show("Move your cursor to position and press ENTER");
if (result == DialogResult.OK)
{
xTemp = MousePosition.X;
yTemp = MousePosition.Y;
}
}
private void orbTransLabel_Click(object sender, EventArgs e)
{
MouseTracker();
orbTransXPos.Text = xTemp.ToString();
orbTransYPos.Text = yTemp.ToString();
}
private void orbAltLabel_Click(object sender, EventArgs e)
{
MouseTracker();
orbAltXPos.Text = xTemp.ToString();
orbAltYPos.Text = yTemp.ToString();
}
}
}
Related
This question already has answers here:
WinForms how to call a Double-Click Event on a Button?
(4 answers)
Closed 7 months ago.
I have a child that contains four buttons, double click each button it clears data in the main form/parent form
below I have my code which counts the button click and perform the event task upon count. Some how its not working at all.
public enum CommandType
{
SetCycleCount,
ClearFaultCount,
ClearGUIControl,
ClearBackData
}
public partial class Child: Form
{
public delegate void OnDblClickedBtn(CommandType operationType, bool state);
public event OnDblClickedBtn BtnClickedEvent;
public CtrlTest()
{
InitializeComponent();
SetCommand();
}
public void SetCommand()
{
SetCycleCnt_btn.Tag = CommandType.SetCycleCount;
ClrFaultCnt_btn.Tag = CommandType.ClearFaultCount;
ClrGuiCtrl_btn.Tag = CommandType.ClearGUIControl;
ClrBackData_btn.Tag = CommandType.ClearBackData;
var btnList = Controls.OfType<Button>().ToList();
foreach (var btn in btnList)
{
btn.DoubleClick += CommandOnClicked;
}
}
private void CommandOnClicked(object sender, EventArgs e)
{
var status = (Button)sender;
BtnClickedEvent?.Invoke((CommandType)status.Tag, status.Enabled);
}
}
Parent Form (message-box is just to check whether its working or not)
child = new Child();
child.BtnClickedEvent += BtnClickedEvent;
child.MdiParent = this;
child.Show();
public int btnCount = 0;
private void BtnClickedEvent(CommandType commandType, bool state)
{
switch (commandType)
{
case CommandType.ClearBackData:
if (btnCount==0)
{
//TODO
MessageBox.Show("Double clicked");
btnCount += 2;
}
else
{
MessageBox.Show("Double click to perform the action");
}
break;
....
}
}
One way to do this is by overriding WndProc in a ButtonWithDoubleClick : Button class:
class ButtonWithDoubleClick : Button
{
const int WM_LBUTTONDBLCLK = 0x203;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_LBUTTONDBLCLK:
OnDoubleClick(EventArgs.Empty);
break;
}
}
}
Replace the Button instances in MainForm.Designer.cs
// private System.Windows.Forms.Button buttonTryDoubleClick;
private double_click.ButtonWithDoubleClick buttonTryDoubleClick;
private void InitializeComponent()
{
// this.buttonTryDoubleClick = new System.Windows.Forms.Button();
this.buttonTryDoubleClick = new double_click.ButtonWithDoubleClick();
...
}
Responding to one or two clicks
public MainForm()
{
InitializeComponent();
buttonTryDoubleClick.Click += ButtonTryDoubleClick_Click;
buttonTryDoubleClick.DoubleClick += ButtonTryDoubleClick_DoubleClick;
}
private async void ButtonTryDoubleClick_Click(object sender, EventArgs e)
{
_isDoubleClick = false;
// Allow some time to get the second click if it's coming.
await Task.Delay(100);
if(!_isDoubleClick)
{
MessageBox.Show("Clicked");
}
}
bool _isDoubleClick = false;
private void ButtonTryDoubleClick_DoubleClick(object sender, EventArgs e)
{
_isDoubleClick = true;
BeginInvoke((MethodInvoker)delegate
{
MessageBox.Show("Double Clicked");
});
}
I'm having two issues which I'm pretty sure are separate in WPF. First off boolean xs isn't getting passed into the Main Window which I've checked by testing where it is true and where it isn't. Also Cross 1 and Cross 2 do not draw if I add them to the Stack Panel in a button click event. Sorry about it being two pretty basic questions but I can't find anything that works. Also I tried to spare you guys as much reading as possible so if you need anything else to make it work for whatever reason don't hesitate to ask for it.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
Rectangle Rectangle = new Rectangle();
Rectangle.MouseLeftButtonDown += Rectangle8_MouseLeftButtonDown;
Rectangle Cross1 = new Rectangle();
Rectangle Cross2 = new Rectangle();
myStackPanel.Children.Add(Rectangle8);
bool xs = Menu.Xs;
bool os = Menu.Os;
bool RectangleClicked = false;
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
}
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
}
if (RectangleClicked == true)
{
myStackPanel.Children.Add(Cross2);
myStackPanel.Children.Add(Cross1);
}
if (xs == true)
{
MessageBox.Show("Xs is true");
}
}
}
Window Two Code
public partial class Menu : Window
{
public Menu()
{
InitializeComponent();
}
public static bool Xs { get; private set; }
public static bool Os { get; private set; }
public void Button_Click(object sender, RoutedEventArgs e)
{
Xs = true;
Os = false;
this.Close();
}
public void Button_Click_1(object sender, RoutedEventArgs e)
{
Xs = false;
Os = true;
MessageBox.Show("Xs is false");
this.Close();
}
}
}
The first issue with the Menu not returning the values:
You need an event to signal to main window that menu has closed and should retrieve the new values from menu.
In Menu, we add a delegate and event to signal that data has changed and the menu is closing:
public partial class Menu : Window
{
public delegate void DataChangeHandler(object sender, EventArgs e);
// an instance of the delegate
public DataChangeHandler DataChanged;
public Menu()
{
InitializeComponent();
}
public static bool Xs { get; private set; }
public static bool Os { get; private set; }
public void Button_Click(object sender, RoutedEventArgs e)
{
Xs = true;
Os = false;
DataChanged?.Invoke(this, new EventArgs());
this.Close();
}
public void Button_Click_1(object sender, RoutedEventArgs e)
{
Xs = false;
Os = true;
MessageBox.Show("Xs is false");
DataChanged?.Invoke(this, new EventArgs());//when menu closes announce change event if a handler is wired up to listen.
this.Close();
}
}
In MainWindow, we have two properties for x and o's being set from menu. These are outside the constructor.
public partial class MainWindow : Window
{
bool xs;
bool os;
public MainWindow()
{
//snip
Button Start = new Button();
Start.Height = 50;
Start.Width = 200;
Start.Margin = new Thickness(500, -100, 0, 0);
Start.Content = "Start";
myStackPanel.Children.Add(Start);
Start.Click += Start_Click;
xs = Menu.Xs;
os = Menu.Os;
}
private void Start_Click(object sender, RoutedEventArgs e)
{
Menu win2 = new Menu();
win2.DataChanged += MenuClosed; //handler
win2.Show();
}
public void MenuClosed(object sender, EventArgs e) //fires after closing menu
{
xs = Menu.Xs; //get new values from Menu for x and o
os = Menu.Os;
}
The second issue:Cross 1 and Cross 2 do not draw if I add them to the Stack Panel.
You need create new crosses and add them to the desired rectangle. First remove the handler to the rectangle clicked outside the constructor in Mainwindow.
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
HandleMove(); //draw a new cross either X or O to 'this' square
}
For each rectangle you add, add a handler to draw the right cross inside the clicked rectangle. The cross drawing handler would then check if x's or o's are set and draw the right cross and add the cross to the rectangle.
I have a List of Objects. What I want to do:
Build a Dialog Box which shows a Radio Button for each element in the given List and returning the selected element/value by clicking on OK-Button.
Thanks in Advance.
Here is a quick example of creating your own form and getting a value from it.
Form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
frmTest frmTest = new frmTest();
DialogResult dr = frmTest.ShowDialog();
if(dr == System.Windows.Forms.DialogResult.OK)
{
string value = frmTest.GetValue();
MessageBox.Show(value);
}
}
}
Form1 View:
public partial class frmTest : Form
{
private string _value { get; set; }
public frmTest()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton radioButton = (RadioButton)sender;
this._value = radioButton.Text; // Assign the radio button text as value Ex: AAA
}
public string GetValue()
{
return this._value;
}
}
You have to make sure that all radio buttons are using radioButton_CheckedChanged for the CheckedChanged event.
Form2 View:
Output:
build your own form and add a public variable "a string for example" called "Result"
public partial class YourDialog:Form
{
public string Result = "";
public YourDialog()
{// add all the controls you need with the necessary handlers
//add the OK button with an "On Click handler"
}
private void OK_Button_Click(object sender, EventArgs e)
{
//set the Result value according to your controls
this.hide();// will explain in the main form
}
}
// in your main form
private string GetUserResult()
{
YourDialog NewDialog = new YourDialog();
NewDialog.ShowDialog();//that's why you only have to hide it and not close it before getting the result
string Result = NewDialog.Result;
NewDialog.Close();
return Result;
}
OOps! I came back just to see there are already 2 answers! How ever, I want to post my version, which can build controls according to list of strings:
//dialog form
public partial class frmDialogcs : Form
{
public string selectedString;
//keep default constructor or not is fine
public frmDialogcs()
{
InitializeComponent();
}
public frmDialogcs(IList<string> lst)
{
InitializeComponent();
for (int i = 0; i < lst.Count; i++)
{
RadioButton rdb = new RadioButton();
rdb.Text = lst[i];
rdb.Size = new Size(100, 30);
this.Controls.Add(rdb);
rdb.Location = new Point(20, 20 + 35 * i);
rdb.CheckedChanged += (s, ee) =>
{
var r = s as RadioButton;
if (r.Checked)
this.selectedString = r.Text;
};
}
}
private void btnOK_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
}
}
//in main form
private void button1_Click(object sender, EventArgs e)
{
var lst = new List<string>() { "a", "b", "c" };
frmDialogcs dlg = new frmDialogcs(lst);
if (dlg.ShowDialog() == DialogResult.OK)
{
string selected = dlg.selectedString;
MessageBox.Show(selected);
}
}
I have a countdown and it outputs to a label on the main form, I want to popout the countdown from the main form to a child form because the child form will be able to stay on top of all other windows (for game) I can't get it to updated the countdown on the child's label. I only get the second when i hit the popout button.
This is on the main form
private void tmrMain_Tick(object sender, EventArgs e)
{
TimerSeconds = TimerSeconds - 1;
if (TimerSeconds == 0)
{
tmrMain.Stop();
if (chbxPlaySound.Checked)
{
System.Media.SystemSounds.Exclamation.Play();
}
if (chbxRepeat.Checked)
{
btnStartTimer.PerformClick();
}
}
string dis_seconds = Convert.ToString(TimerSeconds);
//
// lblTimer is the label that shows the countdown seconds
//
lblTimer.Text = dis_seconds;
}
This is my pop out button on the main form
private void btnPopOut_Click(object sender, EventArgs e)
{
PopTimer ShowTimer = new PopTimer(TimerSeconds);
ShowTimer.Show(this);
}
This is my child form
public partial class PopTimer : Form
{
public PopTimer(int countTimer)
{
InitializeComponent();
//string dis_seconds = Convert.ToString(TimerSeconds);
lblPopTimer.Text = Convert.ToString(countTimer); ;
}
}
Your PopTimer form needs an accessible method, something like this:
public void SetCountdown(int value) {
lblPopTimer.Text = value.ToString();
}
Then your PopTimer needs to be accessible, so move the declaration:
private PopTimer showTimer = null;
private void btnPopOut_Click(object sender, EventArgs e)
{
showTimer = new PopTimer(timerSeconds);
showTimer.Show(this);
}
Then in your tick event:
if (showTimer != null) {
showTimer.SetCountdown(timerSeconds);
}
so this code here dynamically adds buttons to my wpf windows application. I cant think of the way in which I can call buttons which actually runat server because they are randomly added.
namespace DynamicButtons
{
public partial class Window1
{
public Window1()
{
this.InitializeComponent();
populateButtons();
}
public void populateButtons()
{
int xPos;
int yPos;
Random ranNum = new Random();
for (int i = 0; i < 4; i++)
{
Button foo = new Button();
Style buttonStyle = Window.Resources["CurvedButton"] as Style;
int sizeValue = ranNum.Next(100);
foo.Width = sizeValue;
foo.Height = sizeValue;
xPos = ranNum.Next(200);
yPos = ranNum.Next(300);
foo.HorizontalAlignment = HorizontalAlignment.Left;
foo.VerticalAlignment = VerticalAlignment.Top;
foo.Margin = new Thickness(xPos, yPos, 0, 0);
foo.Style = buttonStyle;
foo.Name = "button" + i;
foo.Click += new RoutedEventHandler(buttonClick);
LayoutRoot.Children.Add(foo);
}
}
private void buttonClick(object sender, EventArgs e)
{
Button clicked = (Button) sender;
// something like certainWindowsButton((i)<-this has to be based on above code) = clicked.Name();
MessageBox.Show("Button's name is: " + clicked.Name);
}
}
}
Every time the application runs the buttons are randomly assigned, what I want is a way in which I can interact with them from the code behind.
So
foo.Name = "button" + i;
means when or whichever button is clicked a number is assigned to it but how can I interact with that button in the code?
private void buttonClick(object sender, EventArgs e)
{
Button clicked = (Button) sender;
// something like certainWindowsButton((i)<-this has to be based on above code) = clicked.Name();
MessageBox.Show("Button's name is: " + clicked.Name);
}
}
I hope that makes sense.
To give you a sense of whats happening at design level:
Each of these grey squares are buttons each button is randomly assigned its designated name and number and each time the application runs these buttons will be reassigned a different number.
I need a way inwhich when a number is assigned to it I can then fire an event for that button clicked.
So randomly a button has been assigned number 1, take this number 1 and then assign it to
private void buttonClick(object sender, EventArgs e)
if
{
button1_Click = clicked.Name(strip away "button" and make sure the (variableNumber leftover matches button(1)_Click);
}
else
button2
etc etc
Which then fires my button event:
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("yay each randomly assigned button now correlates with a real button event");
}
}
}
Is this more what you're looking for? This takes each buttonNClick handler and creates a button for it. This way you don't even need the "i".
partial class Window1 {
void button3Click(object sender, RoutedEventArgs e) {
//Whatever you want here
}
void button2Click(object sender, RoutedEventArgs e) {
//Whatever you want here
}
void button1Click(object sender, RoutedEventArgs e) {
//Whatever you want here
}
public Window1() {
this.InitializeComponent();
populateButtons();
}
public void populateButtons() {
int xPos;
int yPos;
Random ranNum = new Random();
foreach (var routedEventHandler in new RoutedEventHandler[] { button1Click, button2Click, button3Click }) {
Button foo = new Button();
int sizeValue = ranNum.Next(100);
foo.Width = sizeValue;
foo.Height = sizeValue;
xPos = ranNum.Next(200);
yPos = ranNum.Next(300);
foo.HorizontalAlignment = HorizontalAlignment.Left;
foo.VerticalAlignment = VerticalAlignment.Top;
foo.Margin = new Thickness(xPos, yPos, 0, 0);
foo.Click += routedEventHandler;
LayoutRoot.Children.Add(foo);
}
}
}
If you just want to choose an action based on the button name the below code may help. Obviously the doAction method calls will change as will your cases but hopefully the code gives you a good enough general idea.
private void buttonClick(object sender, EventArgs e)
{
Button clicked = (Button) sender;
ChooseAction(clicked.Name);
}
private void ChooseAction(string buttonName)
{
switch(buttonName)
{
case "button1": doAction1(); break;
case "button2": doAction2(); break;
case "button3": doAction3(); break;
case "button4": doAction4(); break;
case "button5": doAction5(); break;
default: doDefaultAction(); break;
}
}
private void doAction1()
{
Console.WriteLine("action 1");
}
private void doAction2()
{
Console.WriteLine("action 2");
}
private void doAction3()
{
Console.WriteLine("action 3");
}
private void doAction4()
{
Console.WriteLine("action 4");
}
private void doAction5()
{
Console.WriteLine("action 5");
}
private void doDefaultAction()
{
Console.WriteLine("button name not recognised, performing default action");
}
As lobsterism said, or you could have a list of commands, that you bind randomly to the buttons, instead of any of this. http://www.switchonthecode.com/tutorials/wpf-tutorial-command-bindings-and-custom-commands
here is a verbose sample:
public class CoolCommand : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
//do what you want :)
}
#endregion
}
var allCommands = new List<ICommand>();
allCommands.Add(new CoolCommand);
allCommands.Add(new OtherCoolCommand);
allCommands.Add(new ThirdCoolCommand);
private void assignButton(button)
{
var idx = new Random().nextInt(allCommands.Count-1);
var command = allComands[idx];
button.Command = command;
allCommands.remove(command);
}