Autoclicker calculation - c#

I'm making autoclicker program and I already have an issue. I want my program to be able to change the clicks per second field just how the user wants it. So I made this.
private void textBoxCps_TextChanged(object sender, EventArgs e)
{
try
{
time = Convert.ToDouble(textBoxCps.Text);
time = 1000 / time;
Math.Round(time);
}
catch (Exception)
{
}
}
The math is right(I think...)
while (IsRunning)
{
if ((Control.ModifierKeys & Keys.Alt) != 0)
{
DoMouseClicks();
Thread.Sleep(Convert.ToInt32(time));
}
else
{
}
}
When I try to put 1 CPS into the textbox it does 1 click per second, the same for 2 and 3 but when it's 4 and higher I'm getting 3.80 and lower CPS.

So the operator types some text that should represent a period of time (TimeSpan), and after running is started, you want to call method DoMouseClicks every TimeSpan, until running is stopped.
One of the problems is, that while you are doing this procedure you want your user input to be responsive.
Instead of Sleep, you should use one of the windows timers. There are several of them, and each have their advantages and disadvantages. In your case, the timer that you use depends on the accuracy that you need. See this article for a comparison between the various timers
Is it a problem if the clicks are a bit delayed if the user thread is busy? If not, the easiest is a System.Timers.Timer
System.Timers.Timer timer = new System.Timers.Timer()
timer.Elapsed += TimerElapsed;
private void TimerElapsed(object sender, ...)
{
DoMouseClicks();
}
To change the interval:
TimeSpan TimerInterval
{
get => TimeSpan.FromMilliseconds(this.timer.Interval);
set => this.Timer.Interval = value.TotalMilliseconds;
}
I decided to use a TimeSpan as interval time. This way you code changes are minimal if in future versions you decide to let the operator type his interval times in seconds, or in time format ("01:00")
To start and stop the timer:
private bool IsTimerStarted
{
get => this.timer.Enable;
set => this.timer.Enabled = value;
}
Now we are ready to react on operator input. You decided to act on TextBoxChanged. Are you sure you want this? What happens if an operator wants to type "1000", to indicate one second time interval. He starts by typing "1", you immediately start the mouse clicks with a frequency of 1 msec. Is this what you want?
Another problem: if the operator makes a typing error: "10)0", instead of "1000"?
A proper user interface would let the operator indicate that he finished typing the interval by pressing a button. When the button is pressed you read the text. If there is an error, you notify the operator, if not, you start the timer.
An alternative is to disable the button as long as the text box contains invalid text. Although this seems nice, the disadvantage is that the operator does not know why his button is not enabled.
private void OnButtonStart_Clicked(object sender, ...)
{
TimeSpan intervalTime = this.ReadTextBoxInterval();
this.TimerInterval = intervalTime;
this.IsTimerStarted = true;
// if desired: show the operator that the action is running
}
private void OnButtonStop_Clicked(object sender, ...)
{
this.IsTimerStarted = false;
// if the timer was handling event Elapsed, it is finished neatly.
// if desired show the operator that the action is stopped.
}
I decided to separate the action from the interpretation of the operator input. This way, code changes are minimal if you decide to change the operator input from msec to seconds, or even time format ("00:01"). Or if you decide to use a ComboBox instead of an edit box.
TimeSpan ReadTextBoxInterval()
{
string textBoxText = this.TextBoxInterval.Text;
return IntervalFromMsecText(textBoxText);
}
TimeSpan IntervalFromMsecText(string intervalText)
{
if (Double.TryParse(intervalText, NumberStyles.Any, CultureInfo.CurrentCulture,
out double msecInterval))
{
// input is a proper double
return TimeSpan.FromMilliseconds(msecInterval);
}
else
{
// invalid input. Notify the operator?
}
}

Related

Padleft on numericupdown

I would like to use a numericupdown control on my application. I'm well aware that I could use a plain textbox instead, but I rather like the way this particular control's UI fits with what I'm doing in my application.
It also needs to have 0's at the left, per desired text output. If I'm not mistaken, this is not supported by standard numericupdown controls. It should never exceed 4 digits in length. However, if I input more, it must show favor to new keystrokes and drop left-most digits instead. The up and down arrows should increment/decrement the value per usual behavior. Even after keying in values.
It should never be allowed to run negative. It should only accept whole integers. This is easily handled by the stock functionality though.
Partly posting an answer for others who may follow. Partly looking for assurance that I'm not being an idiot.
Note that this hack depends on firing Sync() before extracting the final value. The timer will fire pretty quickly, but does not guarantee that things will happen in the correct order. It may not hurt to manually trigger Sync() immediately before extracting values.
public class UpDownWith0 : System.Windows.Forms.NumericUpDown
{
private System.Windows.Forms.Timer addzeros = new System.Windows.Forms.Timer();
public UpDownWith0()
{
this.addzeros.Interval = 500; //Set delay to allow multiple keystrokes before we start doing things
this.addzeros.Stop();
this.addzeros.Tick += new System.EventHandler(this.Sync);
}
protected override void OnTextBoxTextChanged(object source, System.EventArgs e)
{
this.addzeros.Stop(); //reset the elapsed time every time the event fires, handles multiple quick proximity changes as if they were one
this.addzeros.Start();
}
public void Sync(object sender, System.EventArgs e)
{
int val;
this.addzeros.Stop();
if (this.Text.Length > 4)
{
//I never want to allow input over 4 digits in length. Chop off leftmost values accordingly
this.Text = this.Text.Remove(0, this.Text.Length - 4);
}
int.TryParse(this.Text, out val); //could use Value = int.Parse() here if you preferred to catch the exceptions. I don't.
if (val > this.Maximum) { val = (int)this.Maximum; }
else if (val < this.Minimum) { val = (int)this.Minimum; }
this.Value = val; //Now we can update the value so that up/down buttons work right if we go back to using those instead of keying in input
this.Text = val.ToString().PadLeft(4, '0'); //IE: display will show 0014 instead of 14
this.Select(4, 0); //put cursor at end of string, otherwise it moves to the front. Typing more values after the timer fires causes them to insert at the wrong place
}
}

How to properly implement a timer in C# [duplicate]

This question already has answers here:
How do you add a timer to a C# console application
(12 answers)
Closed 2 years ago.
This is an old question that I have come back to fix/edit, the essence of the question was how to implement a timer properly which has been answerd many times, so i have marked this as a duplicate
Link to a good answer for implementing a timer:
How do you add a timer to a C# console application
Use a Timer. In your catch, do not do the error message, instead, create a Timer object. Add to that timer's elapsed event a handler that will display the message only if the value is still invalid.
catch (FormatException fEX)
{
if (MyFormatExcTimer == null) {
MyFormatExcTimer = new Timer(1000);
MyFormatExcTimer.elapsed += async ( sender, e ) => await HandleTimer();
MyFormatExcTimer.start();
}
}
private static Task HandleTimer()
{
if (... format is still bad ...)
{
Message.Box("Value must be a divisisable by 1 exactly");
} else {
MyFormatExcTimer.Stop();
}
MyFormatExcTimer.Dispose();
MyFormatExcTimer = null;
}
This is not very complete. You may need to create or dispose or start or stop the timer at different events, but without seeing more of your code it is hard to tell. I might actually not have the program fire off an exception on bad input, but accept any input and have my own code that tests it. My code would get fired off on any text changed event and could set off the timer if the input is bad or stop it if the input is ok.
Also, you might consider not even firing off any messages during input, but rather firing verifying the data when the user tries to save it... but that assumes you have a "save" button or something like that, which you may not.
I agree with the #CodeCaster's comment that message box is not the best way to communicate invalid input to the user, but here is how it can be done:
//declare DateTime lastErrMsg = DateTime.MinValue; at your class level
catch (FormatException fEX)
{
if (DateTime.Now - lastErrMsg > TimeSpan.FromSeconds(30)) //or whatever TimeSpan value
{
Message.Box("Value must be a divisisable by 1 exactly")
lastErrMsg = DateTime.Now;
}
}

Best way to measure (and control) the refresh time of some itens of the user interface

My app needs to display the process time of some operations. One of the process times is the time spent to refresh the proces times at the UI ( got it? :D ).
The frequency of the operations can vary from 0 to about 100 Hz (10 ms).
The process times are display in some labels. To set it values I use this static method:
public Class UserInteface
{
//Static action to SafeSetControlText
private static Action<Control, string> actionSetControlText = delegate(Control c, string txt) { c.Text = txt; };
//Control
//Set Text
public static void SafeSetControlText(Control control, string text, bool useInvoke = false)
{
//Should I use actionSetControlText or it is ok to create the delegate every time?
Action<Control, string> action = delegate(Control c, string txt) { c.Text = txt; };
if (control.InvokeRequired)
{
if (useInvoke)
control.Invoke(action, new object[] { control, text });
else
control.BeginInvoke(action, new object[] { control, text });
}
else
action(control, text);
}
}
Questions:
I dont want to freeze all my UI tryng to update the process times, so how should I control when is it ok to refresh? Now Im doing something like: only update if last update time was 100 ms before now.
If I use BegingInvoke, is it possible to overflow the queues with too much calls?
How can I measure the UI refresh time using BeginInvoke? The best way is to use Invoke?
Pretty acceptable solution, by me, cause if you do not control it, it can result on data blinking on UI side.
No, I don't think you can overflow, especially on 10 ms, speed.
If you want to be sure on time measuring (as much as it possible) the solution is definitely is using of Invokde. The same ou an use also in production.
But this is something you gonna to measure against your specific application requirements.

How to handle the TextChanged event only when the user stops typing?

I have a TextBox with a TextChanged event wired up. In the end it is making a query to a SQL database, so I want to limit the number of queries.
I only want to make the query if the user hasn't pressed a key in say .. 300 milliseconds or so. If for some reason the previous query is still executing, I would need to cancel that, and then issue a new query.
Create a System.Windows.Forms.Timer and reset it (e.g. stop then start it) after every keypress. If the timer event is triggered, disable the timer.
Use the Reactive Framework to trigger on a sequence of events. I'm not sure exactly how this would work, but you can read up on it here (Reactive Extensions for .NET) and see if it will fulfill your needs. There are a bunch of examples here too: Examples. The "Throttling" example may be what you're looking for.
1) Create a timer.
2) Create a handler for the Tick event of your timer. On each tick, check to see if enough idle time has elapsed, and if it has, STOP the timer and execute the query.
3) Whenever a keypress occurs on that textbox, RESTART the timer.
Add a second actionlistener that gets called whenever the user presses any key and when it gets called save the current time to a global variable. Then whenver your TextChanged event gets called it checks to see the time difference between the global variable and the current time.
If the difference is less than 300 milliseconds then start a timer to execute the query after 300 milliseconds. Then if the user presses another key it resets the timer first.
Thanks to #Brian's idea and this answer , I came up with my own version of using a timer to handle this issue. This worked fine for me. I hope it helps the others as well:
private Timer _tmrDelaySearch;
private const int DelayedTextChangedTimeout = 500;
private void txtSearch_TextChanged(object sender, EventArgs e)
{
if (_tmrDelaySearch != null)
_tmrDelaySearch.Stop();
if (_tmrDelaySearch == null)
{
_tmrDelaySearch = new Timer();
_tmrDelaySearch.Tick += _tmrDelaySearch_Tick;
_tmrDelaySearch.Interval = DelayedTextChangedTimeout;
}
_tmrDelaySearch.Start();
}
void _tmrDelaySearch_Tick(object sender, EventArgs e)
{
if (stcList.SelectedTab == stiTabSearch) return;
string word = string.IsNullOrEmpty(txtSearch.Text.Trim()) ? null : txtSearch.Text.Trim();
if (stcList.SelectedTab == stiTabNote)
FillDataGridNote(word);
else
{
DataGridView dgvGridView = stcList.SelectedTab == stiTabWord ? dgvWord : dgvEvent;
int idType = stcList.SelectedTab == stiTabWord ? 1 : 2;
FillDataGrid(idType, word, dgvGridView);
}
if (_tmrDelaySearch != null)
_tmrDelaySearch.Stop();
}

C# WinForms: Waiting for a button press inside an infinite loop

I'm making a simple Guess-The-Number game with a GUI. I need to wait on a loop waiting for the user to input a number in a text box and press "OK". How do I wait for an event inside a loop?
Note: I don't want message boxes. This is done in the main window, hence the need to wait for input.
EDIT: I should have explained myself better. I know that there's a loop inside the GUI. What I want is another loop inside a method. Maybe there's a better way to do this. I could code stuff inside the button's event handler, now that I think about it. Although I'd need global variables. Whataver, I'll think about it, but I hope my question is clearer now.
EDIT 2: Sorry that my question wasn't clear and the edit didn't do much help. First of all, the code is too big to be posted here. I'd probably have to post a screenshot of the GUI, so it wouldn't be of much use. Basically, I have two fields, "Max number" and "Number of allowed guesses". The user enters these two and clicks "Play". A new panel becomes available, with a text box and a "Guess" button. The user enters a guess, and the program checks to see if it's correct.
The purpose of the second infinite loop is to avoid global variables. See, each time the user clicks "Play", the game has to generate a new random number as the correct guess. If everything is done inside a method, no problem. But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
I'd also have to keep track of the remaining number of guesses outside of the method. Again, it's no big deal. I just want to avoid globals if I can.
Again, I'm sorry that my question wasn't too clear. I'm kind of tired, and I didn't feel like writing too much. If this still isn't clear, then don't bother. I'll think of something.
C# automatically loops infinitely waiting for events until your form is closed. You just need to respond to the button click event.
Jason Down's suggestion is wise, create a new GuessingGame class and add it to your project. I know you're worried about "global variables" (which everyone is taught in school never to use unless you absolutely have to), but think about your design specifications for a minute.
But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
As an alternative, store an instance of your GuessingGame class in the form. This is not a global variable! You said so yourself, the point of the game is keep track of the guesses and generate new numbers to guess every time "Play" is clicked. If you store an instance of the game in the form then open another form (e.g. a Help or About box), then the game's instance would not be available (thus, not global).
The GuessingGame object is going to look something like:
public class GuessingGame
{
private static Random _RNG = new Random();
private bool _GameRunning;
private bool _GameWon;
private int _Number;
private int _GuessesRemaining;
public int GuessesRemaining
{
get { return _GuessesRemaining; }
}
public bool GameEnded
{
get { return !_GameRunning; }
}
public bool GameWon
{
get { return _GameWon; }
}
public GuessingGame()
{
_GameRunning = false;
_GameWon = false;
}
public void StartNewGame(int numberOfGuesses, int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException("max", "Must be > 0");
if (max == int.MaxValue)
_Number = _RNG.Next();
else
_Number = _RNG.Next(0, max + 1);
_GuessesRemaining = numberOfGuesses;
_GameRunning = true;
}
public bool MakeGuess(int guess)
{
if (_GameRunning)
{
_GuessesRemaining--;
if (_GuessesRemaining <= 0)
{
_GameRunning = false;
_GameWon = false;
return false;
}
if (guess == _Number)
{
_GameWon = true;
return true;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call StartNewGame() before making a guess.");
}
}
}
This way, all the data related to the game is encapsulated within the class. Hooking up the events is easy in the codebehind of the form:
GuessingGame game = new GuessingGame();
private void btnPlay_Click(object sender, EventArgs e)
{
int numberOfGuesses = Convert.ToInt32(txtNumberOfGuesses.Text);
int max = Convert.ToInt32(txtMax.Text);
game.StartNewGame(numberOfGuesses, max);
}
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = Convert.ToInt32(txtGuess.Text);
bool correct = game.MakeGuess(guess);
if (correct)
lblWin.Visible = true;
if (game.GameEnded)
{
// disable guess button, show loss label
}
}
You should probably look for a book to actually learn windows programming.
The very basics:
1) There is already an infinite loop deep down in the windows code somewhere. Any windows program is constantly looping and scanning for input.
2) Once input is found, this loop fires off an Event.
3) Your mission, should you choose to accept it, is to write event handlers to handle those events.
you are most likely doing it wrong as it has already been pointed out, but you can use this
Application.DoEvents();
to process events when you are on an actual loop
to do it the right way
- don't use a loop
- use an edit box for the input, then a button
- implement the button onclick event
Yes, and What if I am waiting for Speech events, it could happen anytime event when a function is running, I need to handle that without recursively call a function

Categories

Resources