What event is fired when the cancel button is clicked? - winforms

Is there a way I can cancel editing on my form without adding a cancel button?
I am looking for a way to call CancelButton.PerformClick() when I don't have a cancel button.
In the form code I have added the following - but need to know how to cancel the editing.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if(keyData == Keys.Escape) {
// What goes here?
}
return base.ProcessCmdKey(ref msg, keyData);
}
The form contains text controls , and a BindingNavigator
It turns out that I can accomplish what I need using
navigator.BindingSource.CancelEdit();
however I wondered it there way of calling something like
form.CancelButton.PerformClick() if the form.CancelButton is not set.

Is there a way I can cancel editing on my form without adding a cancel button?
I am looking for a way to call CancelButton.PerformClick() when I don't have a cancel button.
In a word, no. There is no cancel button unless you've created one. The Form.CancelButton property will not specify any object unless you've assigned an object to it.
However, there may be a way to achieve what you seek to accomplish. Think about this: what would happen if you did have a cancel button? What would that cancel button do?
It would close the form, discarding all of the user's changes, right? So why not just close the form? Something like:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if(keyData == Keys.Escape) {
this.Close();
}
return base.ProcessCmdKey(ref msg, keyData);
}
If you need to do more clean-up on cancellation (e.g., whatever you would normally put in the cancel button's Click event handler method), you could just define a form class-level method called something like CancelForm, and then call that. For example:
private void CancelForm() {
// do cleanup
this.Close();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if(keyData == Keys.Escape) {
this.CancelForm();
}
return base.ProcessCmdKey(ref msg, keyData);
}
Then again, I question your motivation for wanting to do this. If you want to support cancellation, why not just add a cancel button? Why does the user need to memorize keyboard commands? Keyboard commands are great for users who want to use them, but there's a reason that GUIs are so popular. If the user should be able to cancel the operation, give 'em a big ol' cancel button for them to click. Be sure to disable it when cancelling is not available, giving instant visual feedback.
As a bonus, when you set the Form.CancelButton property to a cancel button on your form, the Esc key automatically invokes the cancel button, freeing you from overriding ProcessCmdKey. You seem to be trying to solve the problem backwards. WinForms takes care of all this for you automagically when you follow the standard idioms. And there are some really good reasons for following the standard idioms.

Related

Is there a way to change the Button.addActionListener behaviour?

If I use the .addActionListener on a button the button fires action "onRelease". Is there a simple way to change that behaviour to "onPress"?
I found a workaround by overriding the pointerPressed method. That works for what I want to achieve, but is that a proper way to go?
Button button1 = new Button("LEFT"){
#Override
public void pointerPressed(int x, int y) {
super.pointerPress(x, y);
m.play();
showLeftForm();
}
};
There's a reason all frameworks fire on release and not on press.
If you do the latter the release event will trigger as you're transitioning to the new form and could cause problems. E.g. a repaint() during screen transition might cause artifacts in some OS/transition combinations etc.
Having said that you can use pointer pressed listener if you wish although I would recommend against it.

How do I do something when I press a key on the keyboard?

I want to make a basic game using Windows Forms.
I want to end the turn of a player when I press Space on the keyboard. I've tried using getch(), but it isn't a good solution because the character has to be entered in the debug window, as it isn't constantly polling for a key press.
A basic pseudocode example of what I need is something like this:
if(PlayerPressesSpace)
{
//end turn of player (I've got this bit figured out)
}
In a Windows Forms GUI app, each Form, and every child Control inside of it, has its own KeyDown, KeyUp, and KeyPress events that you can assign individual handlers to as needed.
Or, you can handle all key events within an entire Form instead of on a per-Control basis, by setting the Form's KeyPreview property to true and then using the Form's KeyDown event. See How to handle keyboard input messages in the form (Windows Forms .NET) for more details.
In a WinForms Form, you can override ProcessCmdKey of the Form container, to pre-process Key presses before they're dispatched to the destination. See also the Docs about this.
This allows to intercept keys that are used to activate default action, as the TAB Key, used to move the Focus to the next Control in the TabIndex hierarchy.
You can then perform any action required before the default action is performed, or suppress the Key, returning true when the conditions you have set are met.
It can also be used to generate special actions when combinations of Keys are pressed.
protected:
virtual bool ProcessCmdKey(Message %msg, Keys keyData) override {
if (keyData == Keys::Space) {
/* do something */
// Suppress the Key press, the message is not sent to the destination recipient
return true;
}
// Otherwise, let the message pass through
return Form::ProcessCmdKey(msg, keyData);
}
If you just need to intercept Keys that don't have special uses, as the aforementioned TAB Key, or some other Key that is processed by specific Controls for their internal use - so the Parent may or may not be notified - you can set the KeyPreview property of your Form container to true and handle the KeyDown event, as mentioned in Remy Lebeau answer.
When KeyPreview is set to true, the Form class sets a state, formState[FormStateKeyPreview]; its ProcessKeyPreview override checks this state and behaves as the ProcessCmdKey override in most cases.
I can only think of
if(Console::ReadKey(true).KeyChar == ' ') {
...
}
Console.ReadKey Method Documentation

Winform app; execute buttons on start

Maybe be a stupid question but say i have an Winform App with 2 clickable buttons (button_1 and button_2), each containing a piece of code. If I open the app, I want to click button_1 then button_2, and close the application. What i am wandering is there any way to insert a method that will call button_1 then button_2 on load (and possibly close the app?) that could be inserted into say Form1_Load?
Don't "click the buttons" automatically. Invoke the logical actions which the buttons invoke automatically. If that logic is currently in the buttons' click events in the code-behind, refactor it into a common location.
For example, your click event might end up with something like:
protected void Button1_Click()
{
SomeObject.DoSomething();
}
Then you can invoke the same action from the form's load event:
protected void Form_Load()
{
SomeObject.DoSomething();
}
Following that, still in the form load event, you can then close the application as well:
protected void Form_Load()
{
SomeObject.DoSomething();
Application.Exit();
}
Though it seems really unnecessary to load up an entire form just to do something without user interaction and then exit. A console application would be much simpler:
static void Main()
{
SomeObject.DoSomething();
}
Then you don't have a UI to worry about, you don't have to attach code to events, you don't even have to forcibly close the application. It'll just execute the code and exit.

disable validation of errorprovider when click cancel button

is there a way to disable the validation of errorprovider elegantly when click cancel button to dismiss a winform?
The validation always happens when the textbox lose focus, and i don't wanna it to validate when the user click cancel button, it is just a little bit silly to validate when the user clicking cancel.
after googling, found the answer, just set CauseValidation property of the cancel button to false. that's it.
I just ran into this myself and setting CauseValidation = false is only a partial solution.
When you set the Form.CancelButton to the cancel button, the Escape key is supposed to invoke that button. It does, however, validation still runs in response to the Escape key, even though we set CauseValidation = false.
To fix it, add the following hack:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Although we set CausesValidation = false for the Cancel button,
// the Escape key fails to cancel due to validation failure. The
// Form.CancelButton property should invoke the validation-free
// cancel button, but doesn't. Force the issue here.
if (keyData == Keys.Escape)
{
DialogResult = DialogResult.Cancel;
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}

Prevent Multiple Form Instances

How do I prevent Multiple forms from opening?
I do .show on the form but the user can click the main form and the button again and another instance of form opens.
Two options, depending on what you need:
Use ShowDialog instead of Show, which will open a modal window. This is the obvious solution if you don't need your main form to be active while the child form is open.
Or keep track of the window you opened already in the main form and do nothing if it's already open. This will be needed if you want the user to be able to use the main form while the child form is already open, maybe to open other forms.
do something like:
SingleForm myform = null;
void ShowMyForm_Click(object sender, EventArgs e)
{ if (myform == null)
{
myform = new SingleForm();
}
myform.Show();
myform.BringToFront();
}
Force your form object to adhere to the singleton pattern
I prefer to use Generics and lazy loading to handle my forms. Since all of my forms inherit from a base class, I can use the same method to bring forms to the front, send them to the back, destroy them, start them, etc.
If you keep a form manager class that's responsible for managing any loaded forms, you can bring whatever form to the front that you want, or prevent specific forms from being able to come back unless certain criteria are met.
public void LoadForm<T>() where T : MyNameSpace.MyBaseForm
{
// Load all your code in this joint and just call it when you
// need a form. In here, you can determine if a copy of the form
// already exists and then bring it forward or not
}
Disable the main form until the child form goes away, or disable the button.
button_onClick(object Sender, EventArgs e)
{
Button btn = sender as Button;
btn.Enabled = false;
Form myform = new MyForm();
myform.Show();
}
Of course, you really should be using form.ShowDialog() rather than form.Show() if you want modal behavior.

Resources