I am currently working on a C# application that runs on a Windows CE 5 device with MS Compact Framework 2.0.
In this application I call a singleton dialog from a keyboard-hook asynchronously via BeginInvoke:
this.BeginInvoke((ThreadStart)delegate()
{
DlgX.getInstance().display(TaskController.getInstance().getActiveTask().getValues(), true);
});
In the display method of the dialog I want to set the focus to a certain control. As the Win CE device is very slow, I have to use a timer to delay the Focus() execution:
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 600;
timer.Enabled = true;
timer.Tick += (EventHandler)delegate(object obj, EventArgs args)
{
button1.Focus();
timer.Dispose();
};
Unfortunately this does not work. The timer gets executed as soon as I close the dialog.
What am I doing wrong?
Thank you in advance for any help!
edit:
This is the whole display() method of the dialog:
public void display(List<InputRow> fvList, bool validate)
{
this.fvList = fvList;
ctlCount = (fvList.Count > 5 ? 5 : fvList.Count);
for (int i = 0; i < ctlCount; i++)
{
//some 100% irrelevant stuff
}
button1.KeyDown += new KeyEventHandler(btnOK_KeyDown);
button1.Click += new EventHandler(btnOK_Click);
if (!this.Visible)
{
ShowDialog();
}
if (validate)
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 600;
timer.Enabled = true;
timer.Tick += (EventHandler)delegate(object obj, EventArgs args)
{
button1.Focus();
timer.Dispose();
};
}
}
The timer instantiation and enabling is evaluated when you close your form, because ShowDialog is synchronous. You should put your timer before your ShowDialog
Related
I am new to coding and are having trouble.
I want to use a timer that will start upon pressing ScatterMode tab, it will start counting 4sec before running "Dosomething" function. This cycle will repeat itself until i decide to stop the program. But the problem i get is, this code only run correctly for like 2loop, after that the timer sort of go crazy LOL.
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
//ScatterMode Tab
private void Scatter_modeToolStripMenuItem_Click(object sender, EventArgs e)
{
timer.Interval = 4000;
timer.Enabled = true;
timer.Tick += new EventHandler(Dosomething);
timer.Start();
}
private void Dosomething (object sender, EventArgs e)
{
timer.Stop();
timer.Enabled = false;
Grab.buffer(out buffer, out status, 6000);
Scatter_mode(buffer);
pictureBox1.Refresh();
int done_grab = 1;
if (doneGrab == 1)
{
timer.Interval = 4000;
timer.Enabled = true;
timer.Tick += new EventHandler(Scatter_modeToolStripMenuItem_Click);
timer.Start();
done_grab = 0;
}
}
Adding a new event handler to a timer, to handle its tick event, inside the handler for the tick event will indeed cause the timer to go "crazy". Every time the timer raises its event, another event handler (that responds to events raised) will be added. This means the next time the timer ticks, the event code will run twice. Two new event handlers will be added. Next time the timer ticks, the code will run 4 times. 4 event handlers will be added ... and so on
Remove this line from your code:
timer.Tick += new EventHandler(Scatter_modeToolStripMenuItem_Click);
And move this line into your form's constructor:
timer.Tick += new EventHandler(Dosomething);
You only want to wire this event handler up once. Every time the timer's interval elapses, the code will run, once :)
I'll also do a bit of a peer review of your code, see the comments:
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
//ScatterMode Tab
private void Scatter_modeToolStripMenuItem_Click(object sender, EventArgs e)
{
timer.Interval = 4000; //can go in the constructor also; don't need to set repeatedly
timer.Enabled = true;
timer.Tick += new EventHandler(Dosomething); //move to constructor
timer.Start(); //this isn't needed - you already Enabled the timer, which started it
}
private void Dosomething (object sender, EventArgs e)
{
timer.Stop(); //use this
timer.Enabled = false; //or this. It's not required to do both
Grab.buffer(out buffer, out status, 6000); //if these lines crash then your timer will
Scatter_mode(buffer); //only restart if the toolstripmenuitemclick
pictureBox1.Refresh(); //above runs.. is it what you wanted?
int done_grab = 1; //not needed
if (doneGrab == 1) //this will always evaluate to true, it is not needed
{
timer.Interval = 4000; //the interval is already 4000, not needed
timer.Enabled = true; //careful; your timer may stop forever if the code above crashes
timer.Tick += new EventHandler(Scatter_modeToolStripMenuItem_Click); //remove
timer.Start(); //not needed
done_grab = 0; //not needed
}
}
I am using
for (int i = 0; i < 10; i++)
{
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -10, 0);
System.Threading.Thread.Sleep(1000);
}
to scroll down a bit then wait a second the scroll and so on. However, it seems to wait 10 seconds then scroll down -100.
I am not sure if this is relevant but I am trying to get it to scroll down a page in a web browser as part of a windows form (once you scroll to the bottom the page loads more and you can scroll again).
the problem is that your GUI freezes and is not updated for the duration of the for loop, because it is running on the same thread. To See the changes every second you need to run it on a background thread.
You can also use a System.Timers.Timer to do that job. Set it up as
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.AutoReset = true;
and hook up the Elapsed event in which you handle the scrolling
timer.Elapsed += Timer_Elapsed;
timer.Start();
you would also need a counter like in your for-loop. Count down until 0 with it in the event handler
int counter = 10;
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if(counter > 0)
{
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -10, 0);
counter--;
}
else
{
System.Timers.Timer t = sender as System.Timers.Timer;
t.Stop();
}
}
This way you can stop the timer after 10 iterations
As suggested by Jakub DÄ…bek you can also use System.Windows.Forms.Timer. This would look like this:
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += Timer_Tick;
timer.Start();
private void Timer_Tick(object sender, EventArgs e)
{
// here the same code as above
}
Situation: I wrote a WinForms application which users access via an RDP. The nature of the application is such that two users cannot run the application at the same time. The problem we're having is that folks will forget to close out of the app, essentially locking other users out.
What I'd like to do is add functionality to automatically close the app after x minutes. I realize that I need to use threading for this since marking time in the main thread would freeze up the app. I don't have a critical need to detect activity/inactivity, but if that's trivial to do, I'd definitely like to know.
Thanks in advance for any assistance!
Assuming you're talking about closing the app from inside the WinForms app itself...use a Timer as suggested by SLaks:
public partial class Form1 : Form
{
private System.Windows.Forms.Timer tmr;
public Form1()
{
InitializeComponent();
tmr = new System.Windows.Forms.Timer();
tmr.Tick += delegate {
this.Close();
};
tmr.Interval = (int)TimeSpan.FromMinutes(10).TotalMilliseconds;
tmr.Start();
}
}
If you wan't to get fancier and close after X minutes of inactivity, then write your own IMessageFilter() that resets a Timer whenever mouse/keyboard activity occurs (WM_LBUTTONDOWN, WM_KEYDOWN, WM_SYSKEYDOWN, etc.). You register your filter with Application.AddMessageFilter() in the Load() event of your Form.
This may help, just put this together, it will close the form 1.5 seconds after the button1 is pressed. you could change this to any time after form load.
public void testc()
{
Timer t = new Timer();
t.Interval = 1500;
t.Tick += new EventHandler(timer_Tick);
t.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Tick");
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
testc();
}
I wrote a class starting from the Idle_Mind's reply, that create a message with another feature : Opacity
Add a Form to your project and call it VanishingMessage.
Add a text label to the Form, i called it : testo
Add the event PAINT to the form.
Copy and paste this code
When you call the class set the the message and seconds as parameters, like required.
I personally suggest to set the FormBorderStyle to NONE.
public partial class VanishingMessage : Form
{
private System.Windows.Forms.Timer tmr;
private System.Windows.Forms.Timer tmr2;
/// <summary>
/// Shows a message windows. 3 sec is the suggested time
/// </summary>
/// <param name="messageText">Message</param>
/// <param name="vanishingSeconds">Showing time</param>
public VanishingMessage(string messageText, int vanishingSeconds=3)
{
InitializeComponent();
double elapsedTime = 0;
testo.Text = messageText;
double vanishingMilliSeconds = vanishingSeconds * 1000;
// message dimensions
this.Width = testo.Width + 50;
this.Height = testo.Height + 50;
//text position
testo.Location = new Point((this.Width / 2) - (testo.Width / 2), (this.Height/2)-(testo.Height/2));
//first timer
tmr = new System.Windows.Forms.Timer();
tmr.Tick += delegate {
tmr.Stop();
tmr2.Stop();
tmr.Dispose();
tmr2.Dispose();
this.Close();
};
tmr.Interval = (int)TimeSpan.FromSeconds(vanishingSeconds).TotalMilliseconds;
tmr.Start();
//second timer
tmr2 = new System.Windows.Forms.Timer();
tmr2.Tick += delegate {
elapsedTime += 50;
if (elapsedTime >= (vanishingMilliSeconds * 65)/100)
this.Opacity -= 0.05f;
};
tmr2.Interval = (int)TimeSpan.FromMilliseconds(50).TotalMilliseconds;
tmr2.Start();
}
private void VanishingMessage_Paint(object sender, PaintEventArgs e)
{
Graphics g = this.CreateGraphics();
Pen p = new Pen(Color.DarkRed);
SolidBrush sb = new SolidBrush(Color.DarkRed);
Rectangle r = this.DisplayRectangle;
r.Width -= 1;
r.Height -= 1;
g.DrawRectangle(p,r);
}
}
Here how to call the class :
VanishingMessage vm = new VanishingMessage("your message",3);
vm.Show();
I have a program that is continuously running.
When I start the program, I have a BackgroundWorker (InitialStart.cs):
BackgroundWorker recordingSyncWorker = new BackgroundWorker();
recordingSyncWorker.DoWork += new DoWorkEventHandler(RecordingSyncCheck);
recordingSyncWorker.WorkerSupportsCancellation = false;
recordingSyncWorker.WorkerReportsProgress = false;
recordingSyncWorker.RunWorkerAsync();
void RecordingSyncCheck(object sender, DoWorkEventArgs e)
{
cHandler ch = new cHandler();
Timer theTimer;
int seconds = 1;
if (taskSeconds != null && taskSeconds != "")
seconds = Convert.ToInt32(taskSeconds);
int milliseconds = seconds * 1000;
theTimer = new Timer(10000);
theTimer.Elapsed += new ElapsedEventHandler(ch.SyncMethod);
theTimer.Interval = milliseconds;
theTimer.Enabled = true;
}
And I have two methods in another class (cHandler.cs):
SyncMethod(object source, System.Timers.ElapsedEventArgs e)
{
// random code
}
private string SDCardCheck(object whatever)
{
//more code
}
SDCardCheck gets called thru WCF, so it's like there is another instance of cHandler.cs running. Is there a way for me to pause the BackgroundWorker when I call SDCardCheck?
Don't use a BackgroundWorker just to start a timer. Starting a timer is not a long running operation; it can be done directly from the UI thread.
Your other method can disable the timer to stop it from firing, and then enable it again to allow it to continue firing, in order to effectively pause its execution.
I have a timer event setup and I would like to change how often the timer event happens by reading a number from a text box. If the box is '10' and you click the update button the event would trigger every 10ms then if you changed to '100' and clicked it would happen every 100ms and so on.
When I run the program however, i can speed up the event frequency (e.g. 100ms to 10ms) but I cannot slow it down (e.g. 10ms to 100ms). Here is the piece of my code that changes the timer when I click:
private void TimerButton_Click(object sender, EventArgs e)
{
getTime = ImgTimeInterval.Text;
bool isNumeric = int.TryParse(ImgTimeInterval.Text, out timerMS); //if number place number in timerMS
label2.Text = isNumeric.ToString();
if (isNumeric)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Enabled = false;
timer.Interval = timerMS;
timer.Elapsed += new ElapsedEventHandler(timerEvent);
timer.AutoReset = true;
timer.Enabled = true;
}
}
public void timerEvent(object source, System.Timers.ElapsedEventArgs e)
{
label1.Text = counter.ToString();
counter = (counter + 1) % 100;
}
If anyone knows what I may be doing wrong it would be greatly appreciated.
The problem with this code is, that you create a new Timer each time you click the button. Try to create the timer outside the method. You think it's only goes faster, but instead multiple timers trigger the timerEvent
private System.Timers.Timer _timer;
private void CreateTimer()
{
_timer = new System.Timers.Timer();
_timer.Enabled = false;
_timer.Interval = 100; // default
_timer.Elapsed += new ElapsedEventHandler(timerEvent);
_timer.AutoReset = true;
_timer.Enabled = true;
}
private void TimerButton_Click(object sender, EventArgs e)
{
bool isNumeric = int.TryParse(ImgTimeInterval.Text, out timerMS); //if number place number in timerMS
label2.Text = isNumeric.ToString();
if (isNumeric)
{
_timer.Interval = timerMS;
}
}
public void timerEvent(object source, System.Timers.ElapsedEventArgs e)
{
label1.Text = counter.ToString();
counter = (counter + 1) % 100;
}
Make sure that the CreateTimer is called in the constructor/formload. Also you can now stop the timer within another button event. With _timer.Enabled = false;
You're always creating a new timer and never stopping the old timer. When you "change" it from 100 to 10 your 100ms timer is still firing every 100 ms, so every 100ms two timers are firing at around the same time.
You need to "remember" the old timer so that you can stop it. Or, better yet, just have only one timer that you change the interval on.
private System.Timers.Timer timer = new System.Timers.Timer();
public Form1()
{
timer.Enabled = false;
timer.AutoReset = true;
timer.Elapsed += timerEvent;
}
private void TimerButton_Click(object sender, EventArgs e)
{
getTime = ImgTimeInterval.Text;
bool isNumeric = int.TryParse(ImgTimeInterval.Text, out timerMS); //if number place number in timerMS
label2.Text = isNumeric.ToString();
if (isNumeric)
{
timer.Interval = timerMS;
timer.Enabled = true;
}
}
Well the basic problem is that you're building a new one every time. Make a private timer:
private System.Timers.Timer _timer = new System.Timers.Timer();
and then fix it up when the button is clicked:
if (isNumeric)
{
_timer.Stop();
_timer.Interval = timerMS;
_timer.Start();
}
and then in the .ctor, do this:
_timer.Elapsed += new ElapsedEventHandler(timerEvent);
Now you have a single timer that you are just modifying as the user changes the value in the text box.