I want to make it work this way: when I write to NumericUpDown 1k the value should be 1000, when I write 4M the value should be 4000000. How can I make it?
I tried this:
private void NumericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyValue == (char)Keys.K)
{
NumericUpDown1.Value = NumericUpDown1.Value * 1000;
}
}
But it works with the original value that I wrote.
I want to make it work as a macroses. For example, If I want to get NUD1.Value 1000, I write 1 and then, when I press K the NUD1.Value becomes 1000.
Let's assume we have a NumericUpDown named numericUpDown1. Whenever the user presses k, we want to multiply the current value of the NUP by 1,000, and if the user presses m, the current value should be multiplied by 1,000,000. We also don't want the original value to trigger the ValueChanged event. So, we need to have a bool variable to indicate that the value is being updated.
Here's a complete example:
private bool updatingValue;
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData != Keys.K && e.KeyData != Keys.M) return;
int multiplier = (e.KeyData == Keys.K ? 1000 : 1000000);
decimal newValue = 0;
bool overflow = false;
try
{
updatingValue = true;
newValue = numericUpDown1.Value * multiplier;
}
catch (OverflowException)
{
overflow = true;
}
updatingValue = false;
if (overflow || newValue > numericUpDown1.Maximum)
{
// The new value is greater than the NUP maximum or decimal.MaxValue.
// So, we need to abort.
// TODO: you might want to warn the user (or just rely on the beep sound).
return;
}
numericUpDown1.Value = newValue;
numericUpDown1.Select(numericUpDown1.Value.ToString().Length, 0);
e.SuppressKeyPress = true;
}
And the ValueChanged event handler should be something like this:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (updatingValue) return;
// Simulating some work being done with the value.
Console.WriteLine(numericUpDown1.Value);
}
Related
I have a textbox, a button, and a progressbar. I would like the keydown event of the textbox therefore the entry, is found using a button in the progressbar, in fact I would like the number entered in the textbox to become the value of the progressbar and that in this case the progressbar value increases. If you could put me a sample code, that would be nice, thank you.
public void button1_Click(object
sender,EventArgs e)
{
//I don't know.
}
public void textbox2_KeyDown(object
sender,KeyEventArgs e)
{
if(e.KeyCode <= Keys.NumPad0 ||
e.KeyCode >= Keys.NumPad9)
{
// I don't know !
}
As I understood, you want to change the progress bar value based on the textBox input and detect that change.
Well, to get the input from the textBox on change, there is an event for that which called:
TextChanged
so with every change in the input, you'll be able to capture the input.
For the progressbar, you can change the value by the property: Value.
Read more:
ProgressBar.Value
so if your progressBar control named: progressBar1, change it by:
progressBar1.Value = 5; // here the value is 5.
Now, you can use textChanged event to set the progress bar value like:
public void textbox2_TextChanged(object sender,KeyEventArgs e)
{
progressBar1.Value = int.Parse(textBox2.Text); // parse the input to int value. Consider using int.TryParse
}
On KeyDown capture the keyValue
int keyValue { get; set; }
private void textbox2_KeyDown(object sender, KeyEventArgs e)
{
int keyVal = (int)e.KeyValue; keyValue = -1;
if ((keyVal >= (int)Keys.D0 && keyVal <= (int)Keys.D9))
{
keyValue = (int)e.KeyValue - (int)Keys.D0;
}
else if (keyVal >= (int)Keys.NumPad0 && keyVal <= (int)Keys.NumPad9)
{
keyValue = (int)e.KeyValue - (int)Keys.NumPad0;
}
}
On Button Click Increase the ProgessBar value
public void button1_Click(object sender,EventArgs e)
{
//Here Increment the progress bar by keyValue
progressBar1.Value += keyValue;
}
KeyValues and KeyCodes
I have a setting in my application that requires any value between 24 and 65520 that must be evenly divisible by 24. I decided to implement this with a horizontal scrollbar and a textbox that shows the current value of the scrollbar, and can have a value manually typed into it (which then sets the scrollbar value). The scrollbar has minimum = 24, maximum = 65520, small & large increments = 1. The default value at app launch is 960. I ended up having to use a couple of event handlers for both the textbox and the scrollbar, and even still it didn't work perfectly. My first mostly-working attempt was this:
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
int NewValue = e.NewValue;
if (e.Type != ScrollEventType.EndScroll)
{
if (e.NewValue < e.OldValue)
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.NewValue > e.OldValue)
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
txtTicksPerQuarter.Text = NewValue.ToString();
}
else
{
hScrollBar_TicksPerQuarter.Value = NewValue;
}
}
private void hScrollBar_TicksPerQuarter_ValueChanged(object sender, EventArgs e)
{
if (hScrollBar_TicksPerQuarter.Value.ToString() != txtTicksPerQuarter.Text)
{
hScrollBar_TicksPerQuarter.Value = Convert.ToInt32(txtTicksPerQuarter.Text);
}
}
private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
{
TrySetTicksPerQuarter();
}
private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
TrySetTicksPerQuarter();
}
private void TrySetTicksPerQuarter()
{
bool useOldValue = false;
int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
int TicksPerQuarter = 0;
if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
{
if (TicksPerQuarter % 24 == 0)
{
hScrollBar_TicksPerQuarter.Value = TicksPerQuarter;
}
else
{
useOldValue = true;
MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
useOldValue = true;
}
if (useOldValue)
txtTicksPerQuarter.Text = TicksPerQuarter_OldValue.ToString();
}
This works fairly well, if I enter a value in the textbox and leave the box or press Enter, it will update the scrollbar accordingly, and if the value is not a proper multiple of 24 it will just reset itself to the last valid value and display a message to the user indicating the issue. Scrolling the scrollbar updates the textbox in real time as you scroll, and everything basically works. The problem is that when you click and drag the scrollbar, the moment you let results in a jump in the value (usually of a couple hundred or so, in either direction). Not sure why it was happening, I started experimenting with changes the "Scroll" event on the scrollbar to see if I could fix it, so releasing the scrollbar after dragging it would result in the value staying what it displayed at the time you release it. It took a lot of experimentation, including some drastic overhauls to everything that didn't even work as well as the code I put above, but ultimately the best I could get was to keep all the code above the same in the other events, and just change the Scroll event to this:
ScrollEventType[] IncrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeIncrement, ScrollEventType.SmallIncrement, ScrollEventType.Last };
ScrollEventType[] DecrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeDecrement, ScrollEventType.SmallDecrement, ScrollEventType.First };
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
int NewValue = e.NewValue;
if (IncrementScrollEvents.Contains(e.Type))
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
else if (DecrementScrollEvents.Contains(e.Type))
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.Type == ScrollEventType.ThumbTrack)
{
if (e.NewValue < e.OldValue)
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.NewValue > e.OldValue)
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
}
else if (e.Type == ScrollEventType.EndScroll)
{
hScrollBar_TicksPerQuarter.Value = NewValue;
}
else
{
return;
}
txtTicksPerQuarter.Text = NewValue.ToString();
}
This definitely works better, and if I had to estimate it, I'd say maybe 4 out of 5 times you release the scrollbar, the value remains where it was at the last moment before you let go of the mouse button. But it still isn't perfect.
I was hoping there is a better way to do this, both in terms of functionality being just that little bit more perfect than it is now, and perhaps even in terms of the overall complexity of the code. I didn't expect to have to write code in 4 different events across 2 controls to do this, but perhaps there isn't a better way after all?
EDIT 1:
I had an idea to use increments of 1 and min/max 1-2730 instead of 24-65520 and then instead of doing math and verification and manually setting the value of the scrollbar to ensure it's a multiple of 24, I will instead just multiply its real value by 24 to get the usable value and the display value for the textbox. This code is now identical in functionality to what I had above, with a lot less complexity. I also moved the warning messagebox for invalid entry in the textbox so that it displays a message even when the user types something that can't even be converted to an integer:
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
txtTicksPerQuarter.Text = (e.NewValue * 24).ToString();
}
private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
{
TrySetTicksPerQuarter();
}
private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
TrySetTicksPerQuarter();
}
private void TrySetTicksPerQuarter()
{
bool useOldValue = false;
int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
int TicksPerQuarter = 0;
if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
{
if (TicksPerQuarter % 24 == 0)
{
hScrollBar_TicksPerQuarter.Value = (TicksPerQuarter / 24);
}
else
{
useOldValue = true;
}
}
else
{
useOldValue = true;
}
if (useOldValue)
{
MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtTicksPerQuarter.Text = (TicksPerQuarter_OldValue * 24).ToString();
}
}
The scrollbar still jumps occasionally when you let go of the mouse button when you're dragging it left and right. I still don't have a solution for that particular problem, unless it's really not something that I can fix due to the way the mouse and scroll bar play with each other?
I just made a small WinForms demo app using just a single scrollbar (hScrollbar1) and a label (Label1).
Created the form's Load event handler and added the following code:
hScrollBar1.Minimum = 1;
hScrollBar1.Maximum = 65520 / 24;
hScrollBar1.Value = 960 / 24;
hScrollBar1.LargeChange = 1;
Created hScrollBar1's ValueChanged event handler and added the following code:
label1.Text = (hScrollBar1.Value * 24).ToString();
Seems to work fine for me this way. Not sure if I could get it to work when using stepping values of 24 in the scrollbar property settings... Sorry for that...
Edit: Just saw your own comment. I agree. :)
I know the title was little unclear but i will explain.
My Example:
when i press 'D' my object will move to right,
same for 'A' just move to left,
but when i press 'Space' while holding 'A'/'D',the object will just o the function of the 'Space'.
if (e.KeyCode == Keys.A)
{
ply.Left -= 3;
}
if (e.KeyCode == Keys.D)
{
ply.Left += 3;
}
if (e.KeyCode == Keys.Space) {
ply.Top -= 100;
}
You can track the state of multiple keys through the use of both KeyUp and KeyDown by use of a HashSet<Keys>:
private HashSet<Keys> _keys = new HashSet<Keys>();
public void Control_KeyDown(object sender, KeyEventArgs e)
{
_keys.Add(e.KeyCode);
}
public void Control_KeyUp(object sender, KeyEventArgs e)
{
_keys.Remove(e.KeyCode);
}
public bool IsKeyDown(Keys keyCode)
{
return _keys.Contains(keyCode);
}
Now, whenever you want to check to see if a key is down, just do:
if(IsKeyDown(Keys.A))
{
ply.Left -= 3;
}
Keep in mind that if you just check key states in one of the key events, you will probably have issues with not detecting repeats properly. If you really want to handle this properly, you should use a Timer with a fairly small Interval that periodically polls with IsKeyDown and handles all your input.
With a Timer named timer1 that has an interval of 100, you can handle all your input like this, and have fairly responsive input to the full range of keys supported by your hardware.
private void timer1_Tick(object sender, EventArgs e)
{
if (IsKeyDown(Keys.A))
{
ply.Left -= 3;
}
if (IsKeyDown(Keys.S))
{
ply.Top += 3;
}
if (IsKeyDown(Keys.D))
{
ply.Left += 3;
}
if (IsKeyDown(Keys.W))
{
ply.Top -= 3;
}
}
As Bradley said, you could save all key events to a keystate cache.
This could look something like this pseudo code:
Event KeyDown(e) -> keystate[e.KeyCode] = true
Event KeyUp(e) -> keystate[e.KeyCode] = false
That way, you should always know every state.
is there a way i can set a condition that after pressing key and if 5seconds already passed then a certain method will be executed .
e.g i have keyup event in gridview:
private void Grid_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
}
else
{
if (atimehasalreadypassed == 5seconds)
{
//execute
}
}
}
problem with this was count might start after passing keyDown so it would be only 1sec.
so i need some count outside U.I thread / within background thread ...
Note: i dont need delay, i just need to know if 5seconds already passed after keyEvent ...
This might be what you need:
private void Grid_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
}
else
{
if (SecondsPassed(5))
{
//execute
}
}
}
private DateTime _lastCallTime = new DateTime();
private bool SecondsPassed(double seconds)
{
// calculate time difference
var timeSpan = new TimeSpan(DateTime.Now.Ticks - _lastCallTime.Ticks);
// reset timing
_lastCallTime = DateTime.Now;
if (timeSpan.TotalSeconds > seconds)
{
return true;
}
return false;
}
Note that you might want to initialize "_lastCallTime" manually, depending on your usage.
What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid. I need to run this calculation After the value in one of the dependent cells is changed, but only if the value was a Valid entry. The EditValueChanged, Validating, and Validated events of the editor/repository all occur before the data is posted back into the datasource. I am wondering if there is any event I can hook into that will allow me to fire this calculation after the data has been post back into the datasource, but before control is returned to the user.
Sample Code
//calculation functions
private void SetCalcROP(MyObjectt Row)
{
//rop = m/hr
TimeSpan ts = Row.ToTime - Row.FromTime;
double diffDepth = Row.EndDepth - Row.StartDepth;
if (ts.TotalHours > 0)//donot divide by 0
Row.ROP = diffDepth / ts.TotalHours;
else
Row.ROP = 0;
}
private void SetCalcDeltaP(MyObject Row)
{
Row.DeltaPress = Row.SPPOnBtm - Row.SPPOffBtm;
}
//events
private void repNumberInput_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colSPPOff) || vwDDJournal.FocusedColumn.Equals(colSPPOn))
SetCalcDeltaP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colStartDepth) || vwDDJournal.FocusedColumn.Equals(colEndDepth))
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repTimeEdit_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (string.IsNullOrEmpty(TE.Text))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column may not be blank");
return;
}
else
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repNumberInput_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (!string.IsNullOrEmpty(TE.Text))
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repTimeEdit_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (vwDDJournal.FocusedColumn.Equals(colToTime))
{//dont bother to check from time
//TIME TRAVEL CHECK!!!!
DateTime FromTime = Convert.ToDateTime(vwDDJournal.GetRowCellValue(vwDDJournal.FocusedRowHandle, colFromTime));
TimeEdit te = sender as TimeEdit;
DateTime ToTime = Convert.ToDateTime(te.EditValue);
if (ToTime < FromTime)
{//TIME TRAVEL
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "To Time must be greater than From Time");
return;
}
}
}
the problem is that everywhere I call this from, and whether I use vwDDJournal.GetRowCellValue(...) or vwDDJournal.GetFocusedRow() as MyObject, I still get the old edit value.
Requirements
I have to have the input validated before running the calculation.
I have to run the calculation immediately after making the change.
... What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid.
The best way to accomplish this task is using Unbound Columns feature.
The following example demonstrates how to implement this feature by handling the ColumnView.CustomUnboundColumnData event:
// Provides data for the Total column.
void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e) {
if (e.Column.FieldName == "Total" && e.IsGetData) e.Value =
getTotalValue(e.ListSourceRowIndex);
}
// Returns the total amount for a specific row.
decimal getTotalValue(int listSourceRowIndex) {
DataRow row = nwindDataSet.Tables["Order Details"].Rows[listSourceRowIndex];
decimal unitPrice = Convert.ToDecimal(row["UnitPrice"]);
decimal quantity = Convert.ToDecimal(row["Quantity"]);
decimal discount = Convert.ToDecimal(row["Discount"]);
return unitPrice * quantity * (1 - discount);
}
Original example: How to: Add an Unbound Column Storing Arbitrary Data
You can also implement calculated value for unbound column using expressions:
GridColumn columnTotal = new GridColumn();
columnTotal.FieldName = "Total";
columnTotal.Caption = "Total";
columnTotal.UnboundType = DevExpress.Data.UnboundColumnType.Decimal;
columnTotal.UnboundExpression = "[Quantity] * [UnitPrice] * (1 - [Discount])";
gridView1.Columns.Add(columnTotal);
How about CustomCellValue?
After posting back to the data source refresh the data.
It's called whenever data is updated or view is changed.