I have a form in my application where users can enter a list of serial numbers, each to be subjected to a quick check and then added to a list (this is for a stock take module). So the users typically use barcode scanners to scan the serial numbers from a pile of stock items.
I'm handling the KeyPress event of the TextBox that has focus while the users are scanning items and look for e.KeyChar == 13 (the enter key). Whenever enter is pressed, I know that I have a complete serial number which I can then validate before adding it to the list.
Here's where my problem occurs; Under certain conditions, I have to prompt the user at this point on whether he really wants the stock item added to the list or not. I'm using a MessageBox for that, like so:
if (MessageBox.Show("This is a special stock item.\r\nDo you want to add it to the list?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
// Add item to list
else
// Do not add item to list
But because this is something that only happens occasionally, the users often don't even see the MessageBox and simply scans the next serial number, which gets lost of course but which ends with an enter key, which fires the default button on the MessageBox and without having intended to do so, and sometimes not even aware that it's happened, the user adds an item to the list and misses a subsequent item.
Is there a way I can prevent the MessageBox from firing any buttons if enter is pressed? I don't mind if the user goes on scanning barcode after barcode and losing them all, as long as the MessageBox remains on screen until he realises his attention is required and deliberately select one of the two options.
Is there a way I can prevent the MessageBox from firing any buttons if
enter is pressed?
No.
I don't mind if the user goes on scanning barcode after barcode and
losing them all, as long as the MessageBox remains on screen until he
realises his attention is required and deliberately select one of the
two options.
Use the YesNoCancel option, and set the default to Button3, which will be the Cancel button. Now keep looping while the result is Cancel. When the loop drops out, the user will have selected either Yes or No:
DialogResult result;
do
{
result = MessageBox.Show("This is a special stock item.\r\nDo you want to add it to the list?", "Confirmation", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3);
} while (result == DialogResult.Cancel);
if (result == DialogResult.Yes)
{
// yes
}
else
{
// no
}
---------- Edit ----------
I'm not overly fond of the idea of having a button on the dialog that
means nothing other than for some obscure application logic (from the
user's perspective).
Agreed...having a "noop" button isn't optimal. The solution above is a quick and dirty "fix".
When you get around to implementing your own custom MessageBox Form, here's an easy way to make it ignore the Enter key whenever a Button is currently focused:
public partial class frmVerify : Form
{
public frmVerify()
{
InitializeComponent();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter && this.ActiveControl is Button)
{
return true; // suppress the keystroke
}
return base.ProcessCmdKey(ref msg, keyData);
}
// ... more code ...
}
Related
It is hard to describe the issue. Let me illustrate it with a very simple example.
Start from a new solution of winform(.net framework 4.8).
Add a menustrip with a textbox, then a datagridview.
And let's handle KeyDown event of datagridview.
if (e.KeyCode == Keys.F3)
toolStripTextBox1.Focus();
Ok, now we start the program.
Click the datagridview to focus on it.
Click the textbox to change focus.
Press Esc on your keyboard.
You can see that the datagridview gets the focus as expected.
But if you make a little change in step two, the result will be confusing. Press F3 instead of clicking the textbox. When you press Esc this time, the focus is just lost. I tried to print the name and the handle of focused control. It turned out to be the textbox itself. Can somebody explain it?
Now I'm quite sure it is some kind of bug. After Jimi's mention of hwndThatLostFocus, I had traced this variable for several hours. Although I failed to locate the exact position where hwndThatLostFocus was changed, something unreasonable was found: when Focus() was called in different cases, the result lost consistency.
Under most circumstances, if Focus() of ToolStripTextBox is called, hwndThatLostFocus of ToolStripTextBox will be set to 0, just like the example in my question. But if you click the datagridview and click the ToolStripTextBox and then click the datagridview agian, this time you call Focus(), hwndThatLostFocus will remain a pointer to the datagridview. In addition, this could be reproduced in .net 6.
Later I will report this to Microsoft. For now, there are three ways to avoid this.
Simulate a mouse click by SetCursorPos and mouse_event in user32.dll.
Use reflection like Jimi's advice.
Override ProcessCmdKey in Form, and take care of Keys.Escape yourself:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Escape && msg.HWnd == toolStripTextBox1.TextBox.Handle)
{
dataGridView1.Focus();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
As I avoid using unnecessary reflect, and Dllimport is also some kind of ugly to me, I prefer the third one.
Okay so I have a DataGridView which is bound with my Data.
I have coded it to be in "edit" mode or "non-edit" mode with some buttons and
DGVSomeGrid.ReadOnly = true; //Or false when applicable.
The user is also allowed to delete rows, but I have to write this to my DataBase. There are foreign keys affected and thus I would like to invoke a warning | confirmation dialog with:
DialogResult = MessageBox.Show();
if (DialogResult == DialogResult.Yes)
{}
else if (DialogResult == DialogResult.No)
{}
This I am fine with aswell.
My problem is I'm not really catching the right event (I think), and I'm not really sure how to cancel the delete procedure. Any help will be greatly appreciated.
I have experimented with:
keydown
and
keypress
events.
I dont have much experience with Winforms but I think the DataGridView.UserDeletingRow Event is just what you are looking for.
Is there a way to show an MessageBox in C# without a focus on a button in the message box? For example the following code snippet (which is not working as wished):
MessageBox.Show("I should not have a button on focus",
"Test",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button3);
What i want is that the MessageBox is shown without a focus on [Yes] or [No]. Background is that the customer scans several barcodes which have an carriage return at the and. So when the messagebox pops up and they scan further barcodes without noticing the message box they "press" a button.
Well you can do it certainly with some trick.
[DllImport("user32.dll")]
static extern IntPtr SetFocus(IntPtr hWnd);
private void button1_Click(object sender, EventArgs e)
{
//Post a message to the message queue.
// On arrival remove the focus of any focused window.
//In our case it will be default button.
this.BeginInvoke(new MethodInvoker(() =>
{
SetFocus(IntPtr.Zero);//Remove the focus
}));
MessageBox.Show("I should not have a button on focus",
"Test",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button3);
}
Note that the above code assumes that when BeginInvoke is called MessageBox is shown and it got the button focused. It will be the case usually upto my knowledge. If you want to make sure message box has shown already you can use this code to find it and then you can remove the focus.
This isn't possible with the standard MessageBox - you'll need to implement your own if you want this functionality.
See here to get you started.
add a new form to your project name it msg
add a label to this form, write your message in this label's text
add a button1 with its text property set to OK
add a textBox1 with the Visible property set to false
add this code in msg_FormLoad():
txtBox1.Focus();
add this code to buton1_Click:
this.Close();
whenever you want to show your message you can just:
msg msgBox = new msg();
msgBox.ShowDialog();
done!
P.S: not tested because the lack of IDE for the moment but I guess it can be adjusted to work with little effort
I'm coding a windows form application running on a barcode scanner.
The plantform is .Net2.0CF/C#.
What i want is whenever user input wrong, the app will pop a messagebox and block the next input(actually,a scan action) until user click the OK on the screen.
But normally the user will continuously scan the next stuff as they didn't find anything went wrong, this will insert a Enter keydown so the messagebox will be closed, in one word, the messagebox does not stop the user.
How can i code this? Below is a very simple code snippet
private void tb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode.ToString() == "Return")
{
if(!ValidateInput(tb.Text))
MessageBox.Show("Error");
}
}
You can create your own window (Form) that displays the error message, but does not react on the enter key.
It should contain a button which the user can click (as you wrote), however you need to make sure the button does not have focus when the window is displayed. (Because if it had focus, pressing the return key will "click" the button.)
A simple way for doing this is adding another control which has TabStop set to true (e.g. a textbox, another button) and which has a lower TabIndex property than the button.
Additionally, maybe you might want to do a
System.Media.SystemSounds.Beep.Play();
when showing the window to draw the user's attention to the window.
I have a confirmation message box for the user in one of my apps. Below is the code for that,
MessageBoxResult res= System.Windows.MessageBox.Show("Could not find the folder, so the D: Drive will be opened instead.");
if (res == MessageBoxResult.OK)
{
MessageBox.Show("OK");
}
else
{
MessageBox.Show("Do Nothing");
}
Now, when the user clicks on the OK button, I want certain code to execute but when they click on the red cross at the upper right corner, I just want the messagebox to close without doing anything. In my case I get 'OK' displayed even when I click on the red cross icon at the upper right corner. Is there a way I can have 'Do Nothing' displayed when I click on the cross. I not want to add any more buttons.
Yes there is a very simple way, just add the "MessageBoxButtons.OKCancel" param to your MessageBox.Show method. this way you will have two buttons (OK and Cancel). this way if the user clicks the cancel button or the red cross the DialogResult.Cancel message will be returned. the following code described the solution:
System.Windows.Forms.DialogResult result = System.Windows.Forms.MessageBox.Show("Could not find the folder, so the D: Drive will be opened instead.",
"", System.Windows.Forms.MessageBoxButtons.OKCancel);
if (result == System.Windows.Forms.DialogResult.OK)
MessageBox.Show("OK");
else
MessageBox.Show("Do nothing.");
No, there isn't.
You could make your own custom dialog form.