Need help on my alarm program - c#

I want to make an alarm program where the user is asked to choose the time and the day of the week. If the user choose the day, the text in the label will be in bold. I am having trouble to pass the list from button2_click to Timer_Elapsed. The program worked well except when i pressed the button, the functions in Timer_Elapsed wont work.
List<string> list = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime currentTime = DateTime.Now;
DateTime userTime = dateTimePicker1.Value;
foreach(string _list in list)
{
if(currentTime.DayOfWeek.Equals(_list) && currentTime.Hour==userTime.Hour && currentTime.Minute==userTime.Minute && currentTime.Second == userTime.Second)
{
SoundPlayer player = new SoundPlayer();
player.SoundLocation = #"C:\Users\Andrew\Music\test1.wav";
player.PlayLooping();
if(MessageBox.Show("","It's Time!", MessageBoxButtons.OK)==DialogResult.OK)
{
player.Stop();
}
}
}
}
private void button2_Click(object sender, EventArgs e)
{
timer.Start();
if (label3.Font.Bold)
{
list.Add("Monday");
}
if (label4.Font.Bold)
{
list.Add("Tuesday");
}
if (label5.Font.Bold)
{
list.Add("Wednesday");
}
if (label6.Font.Bold)
{
list.Add("Thursday");
}
if (label7.Font.Bold)
{
list.Add("Friday");
}
if (label8.Font.Bold)
{
list.Add("Saturday");
}
if (label9.Font.Bold)
{
list.Add("Sunday");
}
foreach (string _list in list)
{
label10.Text = label10.Text + _list + " ";
}
label10.Visible = true;
}
private void label3_Click(object sender, EventArgs e)
{
label3.Font = new Font(label3.Font, FontStyle.Bold);
}
private void label4_Click(object sender, EventArgs e)
{
label4.Font = new Font(label4.Font, FontStyle.Bold);
}
private void label5_Click(object sender, EventArgs e)
{
label5.Font = new Font(label5.Font, FontStyle.Bold);
}
private void label6_Click(object sender, EventArgs e)
{
label6.Font = new Font(label6.Font, FontStyle.Bold);
}
private void label7_Click(object sender, EventArgs e)
{
label7.Font = new Font(label7.Font, FontStyle.Bold);
}
private void label8_Click(object sender, EventArgs e)
{
label8.Font = new Font(label8.Font, FontStyle.Bold);
}
private void label9_Click(object sender, EventArgs e)
{
label9.Font = new Font(label9.Font, FontStyle.Bold);
}
private void button1_Click(object sender, EventArgs e)
{
label3.Font = new Font(label3.Font, FontStyle.Regular);
label4.Font = new Font(label4.Font, FontStyle.Regular);
label5.Font = new Font(label5.Font, FontStyle.Regular);
label6.Font = new Font(label6.Font, FontStyle.Regular);
label7.Font = new Font(label7.Font, FontStyle.Regular);
label8.Font = new Font(label8.Font, FontStyle.Regular);
label9.Font = new Font(label9.Font, FontStyle.Regular);
}

In if statement, You are comparing DayOfWeek Enum value to string: currentTime.DayOfWeek.Equals(_list) this will be always false. Change with this:
currentTime.DayOfWeek.ToString().Equals(_list)

Just like Giorgi said, you are comparing the Enum to a string. You would need to ToString() it before.
As for the rest of your code, here are a couple pointers to make it better overall, since you seem to be beginning. If you don't understand one of the tips, try to read about it. Understanding why it is better is much more important than just blindly changing it. Most of the tips are extremely simplified pointers, and the level is pretty basic too.
Better functionality:
Make a label click either turn it bold or turn it back to normal, depending on it's current state. This will allow a user to remove one of them easily. This will make button1 irrelevant too.
label3.Font = new Font(label3.Font, label3.Font.Bold ? FontStyle.Regular : FontStyle.Bold);
Allow button2 to deactivate the alarm, by clicking it again.
Do not hard-code the path to your sound, instead include it as a ressource, or just put it in the folder with the executable and use a relative path
Nobody needs an alarm up to the second. Make the timer Interval about 30 seconds or so (to avoid millisecond errors), and compare up to the minute.
Don't start the alarm if it is already ringing
Safeguard your dangerous code, like finding the sound file, either by checking it exists beforehand (and reacting appropriately) or with a simple try catch, so that your program doesn't crash at critical moments.
Better code:
Add Enum values (from DayofWeek) to your list, then you will not need to convert anything to compare them
Name your form controls and variables better, so that their use is obvious from the name. "label3", "button2", "list" are horrible names for variables, especially global ones.
Considering the fact that you don't give any other option than "OK" when it rings, don't test the dialog response at all.
player.PlayLooping();
MessageBox.Show("", "It's time!");
player.Stop();
Use the same function for all label clicks, like this:
private void labelDay_Click(object sender, EventArgs e)
{
Label currentLbl = (label) sender;
currentLbl.Font = new Font(currentLbl.Font, currentLbl.Font.Bold ? FontStyle.Regular : FontStyle.Bold);
}
Hold all your labels in an array, so that you can loop through them in the button clicks
Compare the time using a difference, so that you don't have to compare days, then hours, then minutes, etc. A DateTime can easily be compared in one operation.
WinForms has a timer component that you can use from the editor
Dispose of your SoundPlayer when you're done with it, or re-use it. C# takes care of that for you behind the scenes, but that is a very good habit to learn in programming in general
That should be a good start to learning a few very useful things about C# and WinForms, and starting to use better code practices. This is in no way an exhaustive list of everything that could be improved, but since you probably don't plan on ever turning this program into a piece of software used by the whole world, this should be a good stepping stone for you.

Related

c# colour change loop

I am trying to make an 'automatic colour change loop' in other words when someone's mouse hovers over a label, it changes colour in fast repetition, say, 300 microseconds.
private void label1_MouseHover(object sender, EventArgs e)
{
while (true)
{
Random color = new Random();
Color randomColor = Color.FromArgb(color.Next(255), color.Next(255), color.Next(255)); label1.ForeColor = randomColor;
return;
}
}
The issue is in the loop, or should I say lack thereof, I was under the presumption that the while(true) was in itself a loop there for if I kept the mouse in same place, as long as it was over the label it would act, but it only acts once, in simpler terms, I have to hover over it, then leave the area, then hover again, to get it to change colour twice, the ideal is that I can have it always changing colour, so I don't have to hover, but I can't think of a way to do that, since I need the while loop. any ideas for that second part is appreciated but not necessary :)
Okay, so thanks to the guys that realised I am an idiot :3
For anyone else who may want / need the code.
at the beginning of the form:
public Form2()
{
InitializeComponent();
notifyIcon1.Visible = true;
timer2.Start();
}
private void timer2_Tick(object sender, EventArgs e)
{
timer2.Interval = 100;
timer2.Enabled = true;
timer2.Tick += changer;
}
void changer (object sender, EventArgs e)
{
Random color = new Random();
Color randomColor = Color.FromArgb(color.Next(255), color.Next(255), color.Next(255));
label1.ForeColor = randomColor;
}
Now add these, btw, I am aware that I am still issuing a new random every time, if you want to edit that, go ahead, but it works for me, quite nicely, so I am going to keep it that way.

System.FormatException occurred in mscorlib.dll when converting it int32

I know, i know there are lots and lots of questions asking on here about this error, each with their own response, but its easier to work off a response regarding your own code rather than someone else's
I have been working on this program for some time for a college assignment, and as soon as i started putting in the class to calculate the totals of things it now crashes,
I don't know where to look so i'll post my main code
enter code here
namespace Till
public partial class MainWindow : Window
{
Calculator calc = new Calculator();
public MainWindow()
{
InitializeComponent();
}
public bool User;
public bool tillopen = false;
private void button_Click(object sender, RoutedEventArgs e)
{
//button clone thingy
Button btn = (Button)sender;
label.Content = label.Content + btn.Content.ToString();
Console.Beep(); // makes the buttons beep
}
private void clear_Click(object sender, RoutedEventArgs e)
{
// Clear
label.Content = "";
}
private void Button_Submit_Click(object sender, RoutedEventArgs e)
{
// submit
listView.Items.Add(label.Content);
label.Content = "";
calc.setSoldItems(Convert.ToInt32(label.Content)); /// it breaks on this line///
}
private void button13_Click(object sender, RoutedEventArgs e)
{
//void sale
label.Content = "";
listView.Items.Clear();
}
private void button15_Click(object sender, RoutedEventArgs e)
{
//pound
label.Content = "1.00";
}
private void button12_Click(object sender, RoutedEventArgs e)
{
//till open close
tillopen = true;
}
private void button16_Click(object sender, RoutedEventArgs e)
{
Login m = new Login();
m.Show();
this.Close();
}
private void button14_Click(object sender, RoutedEventArgs e)
{
label.Content = "2.00"; // 2 pound
}
private void button17_Click(object sender, RoutedEventArgs e)
{
label.Content = calc.finish();
}
}
I have tried to re-create the error in another WPF (converting a to an int32) and it works fine, i know this is an issue with my code itself, i have tried using other machine and using different versions of visual studio itself, so we came to the assumption its this code itself and not a broken dll file
So before I sit down with my Teacher and spend all day going though my code step by step im asking around for help in order to save both of our time, This assignment is due in in 3 weeks, and it decides to break on me now.
thankies
To replicate this error, i press a number button on my Windows form, them hit the submit button i created (which starts the conversion) If a copy of my class which handles all of this is needed im happy to post it
In the method button_click, you have assigned value as
label.Content = label.Content + btn.Content.ToString();
which is a string value to the label and the values are concatenated instead of add.
and when you are reading it, you are converting it in Int32. which will give exception as it will not contain any integer value to it.
You can add the value like this:
label.Content = (Convert.ToInt32(label.Content) + Convert.ToInt32(btn.Content)).ToString();
and check before converting if the label has blank values in it, if it has do not convert them, and only convert the value if it has some values it will not give any error. Also do not assign any values other that numerical digits.
You are calculating:
Convert.ToInt32(label.Content)
but on the line before you set:
label.Content = "";
so this means you are calculating
Convert.ToInt32("")
which gives you a FormatException.
Perhaps you should use the value of label.Content before you overwrite it?

Refresh timer and warning boxes in c#

Basically, I have a frequency that refreshes data on screen. When one of these data points goes over a set value, it sets off an error. Upon this error setting off, I want the background colour to change (like a flashing warning).
The problem I have is that I am already using a timer, and when I call a new timer (for the flash) it stops the other timer working, and I'm unaware of how to call in the previous method (being as it uses object sender)
Here is my code:
public void Freq_Change(object sender, SelectionChangedEventArgs e)
{
_timer.Stop();
_timer.Interval = TimeSpan.FromSeconds(Freq.SelectedIndex + 1);
_timer.Start();
_timer.Tick += timer_Tick;
}
and timer_Tick
void timer_Tick(object sender, EventArgs e)
{
//Data generator
//Value pushes to text boxes
if (value is over 100)
{
Warning_Blink
"Oh no, an error"
}
else
{
"All good"
}
Warning_Blink has the new timer in, which then calls warning_Tick
In warning_Tick
private bool _warning = false;
private void warning_Tick(object sender, EventArgs e)
{
if (_warning)
{
ErrorBox.Background = new SolidColorBrush(Colors.Red);
}
else
{
ErrorBox.Background = new SolidColorBrush(Colors.White);
}
_warning = !_warning;
Freq_Change();
}
Here where I call Freq_Change (which doesn't work) I want to be able to go back to the old timer (or better yet never switch between the two) so the data generation can continue.
Can anyone help me with this? I've been scratching my head for hours

Writing a method to serve slightly different scenarios C#

I struggled with what to title this as but hopefully I can explain a little better here. I am trying to write a program that will track an assembly through a 6 station assembly line. At each station, the operator will hit a button (such as station1start, station1stop, station2start, etc) and the button press event will send the timestamp to a database and also update the form visually by moving the traveling id number to the next station. I have this all working for the first couple of stations but I'm wondering if there is a way to use the same method for each station. For example have a method such as
void updateStart(int station_num)
where the station ID would be an argument but otherwise the method could be used for all of the stations. I know that variables in C# cannot be dynamically changed but am curious if there is another way to make this code cleaner. It seems like bad programming to have 6 methods almost identical. Especially if we were to add another 6 stations. See the screenshot of the form and my example code below of the button that the operator would hit when they started at station 2. Any help would be greatly appreciated!
http://i.stack.imgur.com/Ddxww.png
private void Station2Start_Click(object sender, EventArgs e)
{
Station2Label.Text = Station1Label.Text;
Station1Label.Text = "";
Station1Status.Text = "";
Station2Status.Text = "IN PROGRESS";
addTimeToDb(2);
}
The question is somewhat unclear but I believe it is:
I have the following code:
private void Station2Start_Click(object sender, EventArgs e)
{
Station2Label.Text = Station1Label.Text;
Station1Label.Text = "";
Station1Status.Text = "";
Station2Status.Text = "IN PROGRESS";
addTimeToDb(2);
}
private void Station3Start_Click(object sender, EventArgs e)
{
Station3Label.Text = Station2Label.Text;
Station2Label.Text = "";
Station2Status.Text = "";
Station3Status.Text = "IN PROGRESS";
addTimeToDb(2);
}
And so on, repeated many times with minor substitutions. How do I "DRY out" this code? (That is Don't Repeat Yourself.)
When you create the labels and status boxes put them in an array:
private Label[] stationLabels;
private Label[] statusLabels;
...
// in your form initialization after the creation of the labels:
stationLabels = new [] { Station1Label, Station2Label, Station3Label, ...
// and similarly for status labels.
Now write
private void StationClick(int station)
{
stationLabels[station-1].Text = stationLabels[station-2].Text;
... and so on
And then each method becomes
private void Station2Start_Click(object sender, EventArgs e)
{
StationClick(2);
}
private void Station3Start_Click(object sender, EventArgs e)
{
StationClick(3);
}
And so on.

Event being increasingly, repeatedly fired

I have an unusual thing happening with an RSS presenter I'm trying to make. It's meant to go to the next item after an 'Out' animation is played, then play the 'In' animation. http://oeis.org/A000217
void _timer_Tick(object sender, EventArgs e)
{
Storyboard sbOut = this.FindResource("sbAnimateOut") as Storyboard;
sbOut.Completed += new EventHandler(sbOut_Completed);
sbOut.Begin();
}
void sbOut_Completed(object sender, EventArgs e)
{
if (_selected < _total)
{
_selected++;
}
else
{
GetFeed(_feed);
_selected = 0;
}
lstbxItems.SelectedIndex = _selected;
counter.Text = _selected.ToString();
Storyboard sbIn = this.FindResource("sbAnimateIn") as Storyboard;
sbIn.Begin();
}
I noticed it seem to skip items though. When I step through it line by line, it seems to execute the void sbOut_Completed(object sender, EventArgs e) once the first time, three times the second time, six times the third time - and so on, sequentially.
Perhaps I'm going about this the wrong way and that's causing the issue? Any suggestions?
You are adding another event handler every timer tick!
Move this code:
sbOut.Completed += new EventHandler(sbOut_Completed);
into your initialization - only do it once.

Categories