Is the following possible when initiating an if pictureBox clicked event? - c#

I have been trying to make a matching game and I recently learned that the following is possible:
if (checkBox1.checked = true)
{
MessageBox.Show("For Example.")'
}
Then why is the following not possible?
private void pictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("Now Pick Another Hidden Picture!");
pictureBox1.Visible = false;
if (pictureBox13.Click = true)
{
MessageBox.Show("Great!");
pictureBox13.Visible = false;
double score = score + 1;
textBox1.Text = (score).ToString();
}
else
{
MessageBox.Show("Try Again!");
pictureBox13.Visible = true;
pictureBox1.Visible = true;
}
}
There is a error line under .Click , and the error is :
The event 'system.Windows.Forms.Control.Click' can only appear on the left hand side of += or -=.
What does this mean? And why does this work for checking checkboxes, but not for clicking pictureboxes? Thank in advance.

Checked is the state of a checkbox. At any given time, a checkbox is either checked or unchecked. Reading myCheckBox.Checked immediately returns the current state of the checkbox.
Click is an event. What do you expect if (pictureBox.Click == true) to do? Tell you if the pictureBox has been clicked within the last X seconds? Wait X seconds for the user to click (or not click) on the pictureBox?
In other words: If you check a checkbox, it stays checked until it is unchecked. Thus, it makes sense to check the current state of the checkbox. On the other hand, if you click a button, it is "clicked" for only an instant and then returns to being "unclicked". Thus, it just does not make sense to query the "clicked" state of a button.
PS: Comparisons are done with ==, not with =. The latter is an assigment. And, as Hugh correctly points out in the comments, if (boolean) is enough, if (boolean == true) is redundant.

Related

NumericUpDown error MessageBox

I would like to ask what code should I insert to to my "numGPA" to inform the user that they have exceeded the "maximum".
Right now if the try to "submit" a value above the maximum, my visual studio will only play a "ding" sound.
Instead of that I would like to have a message box that says something like "Only a value from 0 to 4 is allowed"
I found this code on Google and despite me changing the numericUpDown1 to numGPA it does not work.
if (numGPA.Value >= 4 || numGPA.Value <= 0)
{
MessageBox.Show("Error. Number must be between 0 and 4");
numGPA.Value = 1;
numGPA.ReadOnly = true;
}
Do take a look at this video to get a clear picture of what I am saying
https://www.youtube.com/watch?v=XVv-it6x044&feature=youtu.be
Instead of the "ding" sound effect played #0.06, I would like a MessageBox.
You can do that with the TextChange event. You can (and should) also set the minimum and maximum properties to limit the input with the arrows.
Private Sub NumericUpDown1_Changed(sender As Object, e As EventArgs) Handles NumericUpDown1.TextChanged
If IsNumeric(NumericUpDown1.Text) AndAlso _
CInt(NumericUpDown1.Text) > NumericUpDown1.Maximum Then MsgBox("Oops! Too big.")
End Sub
The best way is to let the user edit and only check when he has finished. This will trigger the ValueChanged event.
Here we can get at the entered value by grabbing the internal TextBox control.
I suggest using a helper function, maybe like this:
void nudCheck(NumericUpDown nud)
{
TextBox tb = (TextBox) nud.Controls[1];
if (Convert.ToInt32(tb.Text) > nud.Maximum)
{
string msg = tb.Text + " is too large! Setting value to maximum: " + nud.Maximum;
tb.Text = "" + nud.Maximum;
nud.Value = nud.Maximum;
// do what you want with the message string!
//MessageBox.Show(msg); // not recommended!
toolTip1.Show(msg, nud); // add a ToolTip component to your form for this!
}
}
Call it here:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
nudCheck(numericUpDown1);
}
We also want to suppress the error sound for the case when the user presses Enter, best in the KeyDown event..
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
nudCheck(numericUpDown1);
e.SuppressKeyPress = true;
}
}
Note that bringing up an actual MessageBox will bring back the bell sound and force the user to get rid of it. So I have used a ToolTip, but a Label would also work, if you have the space..
Obviously you may want to add similar code to check input lower than the Minimum..

Store two mouse click positions on canvas when checkbox enabled

I have a checkbox at the moment where, when I click it, it should allow the user to click two places on a canvas, and then a messagebox with the coordinates of both clicks appear, and then the checkbox should uncheck itself. I've tried various things and keep running into a few problems.
Checking the box is a RoutedEventArgs where as clicking on the canvas is a MouseButtonEventArgs.
I'm unable to store the second mouse click (the first click appears twice); I've tried various for loops, while loops, etc.
I'm unable to get the box to uncheck itself after the message box appears, regardless of where I put the .Checked == false. I get an error that says system.windows.etcetc.checked can only appaer on the left hand side of += or -=.
I'd like to handle the whole thing in a function related to the checkbox aka the routedeventargs and not a canvas click method.
I can figure out #2 but 1 and 3 have me stumped.
This is a sample of the method which is subscribed to from a canvas mousedown in the xaml:
public void get_Scaling(object sender, MouseButtonEventArgs e)
{
Point startPoint;
Point endPoint;
while (Scale_btn.IsChecked == true)
{
startPoint = e.GetPosition(canvas1);
endPoint = e.GetPosition(canvas1);
System.Windows.MessageBox.Show("Start point is" + startPoint + "and end point is" + endPoint, "test", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
There are a couple of issues I see.
1) The way to programmatically uncheck a CheckBox is to use the IsChecked property.
Scale_btn.IsChecked = false;
2) Remember that your while loop is running inside of a single MouseDown event handler. You won't be able to capture two different MouseDown events within that while loop. In order to achieve your goal, you need to bring the Point objects outside of the event handler and use another variable to keep track of which click you are capturing.
bool firstPointCaptured = false;
Point startPoint;
Point endPoint;
private void get_Scaling(object sender, MouseButtonEventArgs e)
{
if (Scale_btn.IsChecked == true)
{
if (!firstPointCaptured)
{
startPoint = Mouse.GetPosition(canvas1);
firstPointCaptured = true;
}
else
{
endPoint = Mouse.GetPosition(canvas1);
System.Windows.MessageBox.Show("Start point is" + startPoint + "and end point is" + endPoint, "test", MessageBoxButton.OK, MessageBoxImage.Information);
Scale_btn.IsChecked = false;
firstPointCaptured = false;
}
}
}
This is how you get mouse coords (you do not need e, so your question 1 is invalid).
Currently your starPoint == endPoint. Do you understand you have to get 2 mouse click events (while remembering points) before you are able show MessageBox?
You have to use IsChecked property, instead of Checked event to change checked state of CheckBox.

ListView Checkbox Behavior

I have a Winform application I'm modifying for a friend. It has a listview and wants me to add a checkbox to each row and make them mutually exclusive. So in my testing of how to make it work I found a strange behavior and as hopping someone could tell me what I'm missing.
If I display the List view with no checkbox checked. When I click right on the checkbox I cannot get it to check, but the row dose get selected. If I click on the item (the name in this case) in the column it does get checked and selected.
No matter where I click on a row, any checkboxes in rows not selected will be uncheck. Here is my little test program. I’m using .NET 4
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
TestListView.Items.Add("Bob");
TestListView.Items.Add("Ann");
TestListView.Items.Add("Frank");
}
void TestListView_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) {
ListViewItem currentItem = TestListView.GetItemAt(e.X, e.Y);
if (currentItem != null) {
foreach (ListViewItem item in TestListView.Items) {
if (item.Text == currentItem.Text) {
item.Checked = true;
item.Selected = !currentItem.Selected;
}
else
item.Checked = false;
}
}
}
}
Seems that WinForms is checking the checkbox when you click on the checkbox directly, and then your code immediately undoes the checking, so you never see it.
Perhaps instead of MouseClick you should use the ItemCheck or ItemChecked event. The first is fired before the Checked property changes, the second after.
I'm currently having a very similar issue as well, however in response to Timwi it's not the code doing the unchecking. I've been stepping through it very slowly and as the code fires when clicking on a checkbox, it states that it has checked it. But when the form resumes, it is unchecked again. After reading Timwi post, he lead me onto the answer. It's not the code doing the unchecked, but the winforms event firing afterwards that unchecks the box. This fixes it:
My code is:
private bool allowCheck = false;
private bool preventOverflow = true;
private void lstvwRaiseLimitStore_MouseClick(object sender, MouseEventArgs e)
{
preventOverflow = false;
ListViewItem item = lstvwRaiseLimitStore.HitTest(e.X, e.Y).Item;
if (item.Checked)
{
allowCheck = true;
item.Checked = false;
}
else
{
allowCheck = true;
item.Checked = true;
}
}
private void lstvwRaiseLimitStore_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (!preventOverflow)
{
if (!allowCheck)
{
preventOverflow = true;
e.Item.Checked = !e.Item.Checked;
}
else
allowCheck = false;
}
}
So what it is doing, first I have to set a flag to prevent overflow, otherwise when the form is built or when you uncheck windows checking the box, it keeps looping the code and will eventually stack overflow. Next flag is the actual allow checking of the checkbox via your code and not via another method.
Clicking on them item, it locates where the click was and then sets the flag to allow a check to be done. The code then checks the box and the item checked section kicks off, becuase it was done by our code, it does nothing but reset the allowcheck flag.
If you clicked on a line, it does nothing else, however if it was a checkbox, at the end of our code, the Windows function kicks off and tries to check the box, becuase the allowcheck flag is false, the code first sets a flag to say I'm already preventing a check and then resets the check back to it's intial status. Becuase this is done, the itemchecked event kicks off again, but the code has set the flag to prevent it from doing anything. Then the code finishes and it has prevented windows from checking the check box and only allowed our code.
Hope it helps!

Cancelling ListBox SelectedIndexChange Event

Is it possible to cancel the SelectedIndexChange event for a listbox on a winforms application? This seems like such a logical thing to have that I must be overlooking some easy feature. Basically, I have been popping up a message box asking if the user really wants to move to another item, as this will change the UI and I don't want their changes to be lost. I'd like to be able to cancel the event in case the user has not saved what they are working on. Is there a better way of doing this?
You cannot cancel it.
What I did just a couple of days ago was to have a variable with the latest selected index. Then when the event fires, you ask the user if he wants to save, this is done in the eventhandler. If the user selected "Cancel" you change the id again.
The problem is that this will make the event fire once again. So what i've used is a bool just saying "Inhibit". And at the top of the eventhandler I have:
if(Inhibit)
return;
Then below this where you ask the question you do something like this:
DialogResult result = MessageBox.Show("yadadadad", yadada cancel etc);
if(result == DialogResult.Cancel){
Inhibit = true; //Make sure that the event does not fire again
list.SelectedIndex = LastSelectedIndex; //your variable
Inhibit = false; //Enable the event again
}
LastSelectedIndex = list.SelectedIndex; // Save latest index.
This is exactly #Oskar Kjellin 's method, but with a twist. That is, one variable less and with a selected index changed event that really behaves like a selected index changed event. I often wonder why is selected index changed event getting fired even if I click on the exact same selected item. Here it doesn't. Yes it's a deviation, so be doubly sure if you want this to be there.
int _selIndex = -1;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex == _selIndex)
return;
if (MessageBox.Show("") == DialogResult.Cancel)
{
listBox1.SelectedIndex = _selIndex;
return;
}
_selIndex = listBox1.SelectedIndex;
// and the remaining part of the code, what needs to happen when selected index changed happens
}
I just ran into this exact problem. What I did is when the user makes changes, I set ListBox.Enabled = false; This disallows them to select a different index. Once they either save or discard their changes, I set ListBox.Enabled = true; Probably not as slick as a prompt, but it gets the job done.
More elegant, use the Tag property:
if ((int)comboBox.Tag == comboBox.SelectedIndex)
{
// Do Nothing
}
else
{
if (MessageBox.Show("") == DialogResult.Cancel)
{
comboBox.SelectedIndex = (int)comboBox.Tag;
}
else
{
// Reset the Tag
comboBox.Tag = comboBox.SelectedIndex;
// Do what you have to
}
}
The SelectedIndexChanged cannot be cancelled. So you only have one real option:
private int? currentIndex;
public void ListBox_SelectedIndexChanged(sender, EventArgs args) {
if (currentIndex.HasValue && currentIndex.Value != listBox1.SelectedIndex) {
var res = MessageBox.Show("Do you want to cancel edits?", "Cancel Edits", MessageBoxButtons.YesNo);
if (res == DialogResult.Yes) {
currentIndex = (listBox1.SelectedIndex == -1 ? null : (int?) listBox1.SelectedIndex);
} else {
listBox1.SelectedIndex = currentIndex.Value;
}
}
}
This is my way to cancel SelectionChange for ComboBox. I think it could also fit to ListBox.
private bool comboBox_CancelSelection = false;
private int comboBox_LastSelectedIndex = -1;
private void comboBox_SelectedIndexChanged(object sender, EventArgs e) {
if (comboBox_CancelSelection) {
comboBox_CancelSelection = false;
return ;
}
// Handle Event
if (!comoBox_CancelSelection) {
comboBox_LastSelectedIndex = comboBox.SelectedIndex;
} else {
comboBox.SelectedIndex = comboBox_LastSelectedIndex;
}
}

Preventing double events in DataGridView

I have a problem that I am not sure how to solve. I have a DataGridView (EditMode = EditProgrammatically). This grid has one checkbox column and one or more textbox columns. The functionality is as following (or should be at least):
When you click on a checkbox, the checkbox should be toggled
When a row (or many rows) are selected, and you press space, the checkboxes should be toggled.
I have these two event handlers:
private void grid_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex == useColumn.Index)
{
if (ModifierKeys != Keys.Shift && ModifierKeys != Keys.Control)
{
ToggleRows(grid.SelectedRows);
}
}
}
private void RowSelectorForm_KeyDown(object sender, KeyEventArgs e)
{
if (grid.Focused && e.KeyCode == Keys.Space)
{
ToggleRows(grid.SelectedRows);
e.Handled = true; // Not sure if this is needed or even does anything
e.SuppressKeyPress = true; // Or this for that matter...
}
}
This almost works. The problem is when you press space and a checkbox cell is active. When a textbox cell is active, it works like it should. The problem is that when you press space and a checkbox cell is active, both events gets fired. Which means it first selects and then deselects (or the reverse). So the checkboxes end up being like they was. How can I prevent this?
I have thought about using a flag, but not sure where I can put it, since I can't really know if it was a double event or if it was just the user using space and then clicking with the mouse. So that can't really be used I think. Is there a different event I should use? Is there a way to see if the cell was clicked by mouse or by space? Is there a way to disable the automatic checkbox toggling when space is pressed? What can I do?
Note: Reason for RowSelectorForm_KeyDown and not just grid_KeyDown was that I was trying to use KeyPreview and then suppress the keypress if it was space and the grid was focused. But that SuppressKeyPress doesn't really seem to do anything at all =/ Maybe I've just misunderstood it...
Well, I didn't want to do it, but I have now fixed it with a timer... but if anyone knows how to do it properly, please let me know!!
Current solution:
private DateTime lastClick = DateTime.MinValue;
and in both events:
if (DateTime.Now - lastClick > TimeSpan.FromMilliseconds(400))
{
lastClick = DateTime.Now;
ToggleRows(grid.SelectedRows);
}
It has been a time since I worked with C#, but I assume that you can disconnect the grid_CellClick event handler before calling ToggleGrid in RowSelectorForm_KeyDown.
After the call, you can reconnect the event handler.
Also, there might be some way to supress the event from being fired in the first place. In some API's certain methods are specially provided that don't trigger any events.
The frustrating problems are:
.Handled doesn't prevent the check box from changing
.SuppressKeyPress doesn't prevent the checkbox from changing
If you DoubleClick on the checkbox, the first click fires the Click() event (toggling the checkbox) and the second click fires the DoubleClick() event (toggling the checkbox yet again).
However, the KeyDown event fires before any of the grid events. Perhaps setting a flag to indicate the spacebar was pressed or if the row was already selected, reset the value of the checkbox.
I used the following and it seemed to work well:
private Keys _ClickSource = 0;
private void dgv_CellClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
{
if (_ClickSource == 0 || _ClickSource != Keys.Space)
{
dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ! (System.Convert.ToBoolean(dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value));
}
_ClickSource = null;
}
private void dgv_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
_ClickSource = e.KeyCode;
}

Categories