Background Info:
For school, I need to make a crossword puzzle project in Windows Forms using OOP and the project needs to have a list build in it.
Problem:
For the functions in Form1.cs, I need to pass parameters (Object sender, Eventargs e) coming from the classes for the Form. The Project is OOP based.
Question:
error: There is no argument given that corresponds to the required formal parameter 'sender'
The errors are coming from:
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
boardCells.Board_CellPainting();
boardCells.Board_CellValueChanged();
boardCells.formatCell();
My question is what do I need to do to solve the error?
Form1.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO;
namespace CrossWordPuzzle
{
public partial class Form1 : Form
{
//Object instances from classes
Clues clue_window = new Clues();
Cell boardCells = new Cell();
Menu menuOptions = new Menu();
Board board = new Board();
public Form1()
{
InitializeComponent();
//Board functions
board.buildWordList();
board.InitializeBoard();
//Menu functions
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
menuOptions.InitializeComponent();
//Cell functions
boardCells.Board_CellPainting();
boardCells.Board_CellValueChanged();
boardCells.formatCell();
boardCells.InitializeComponent();
}
//Function loads form with window properties
public void Form1_Load(object sender, EventArgs e)
{
board.InitializeBoard();
clue_window.SetDesktopLocation(this.Location.X + this.Width + 1, this.Location.Y);
clue_window.StartPosition = FormStartPosition.Manual;
clue_window.Show();
clue_window.clueTable.AutoResizeColumns();
}
//Function location form window
public void Form1_LocationChanged(object sender, EventArgs e)
{
clue_window.SetDesktopLocation(this.Location.X + this.Width + 1, this.Location.Y);
}
}
}
(menuOptions) Menu Class
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace CrossWordPuzzle
{
class Menu : Form
{
//Object instances from classes
public DataGridView datagridview = new DataGridView();
public Form1 form = new Form1();
public string puzzle_file = Application.StartupPath + "\\Puzzles\\Puzzle1.pzl";
Clues clue_window = new Clues();
public List<id_cells> idc = new List<id_cells>();
Board board = new Board();
//Opens puzzle selector
public void openPuzzleToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Puzzle Files|*.pzl";
if (ofd.ShowDialog().Equals(DialogResult.OK))
{
puzzle_file = ofd.FileName;
datagridview.Rows.Clear();
clue_window.clueTable.Rows.Clear();
idc.Clear();
board.buildWordList();
board.InitializeBoard();
}
}
//Exit application function
public void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
//About menu function
public void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("CrossWordPuzzle made in C# Windows Forms", "CrossWordPuzzle");
return;
}
//Initialize Menu component
public void InitializeComponent()
{
this.SuspendLayout();
//
// Menu
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "Menu";
this.Load += new System.EventHandler(this.Menu_Load);
this.ResumeLayout(false);
}
//Load Menu
private void Menu_Load(object sender, EventArgs e)
{
}
}
}
(boardCells) Cell class
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace CrossWordPuzzle
{
class Cell : Form
{
//Object instances from classes
public DataGridView datagridview = new DataGridView();
public List<id_cells> idc = new List<id_cells>();
public Form1 form = new Form1();
//Cell painting
public void Board_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
//Every time a cell gets drawn on the board, it comes with a rectangle that has the number of the word.
String number = "";
if (idc.Any(c => (number = c.number) != "" && c.X == e.ColumnIndex && c.Y == e.RowIndex))
{
Rectangle r = new Rectangle(e.CellBounds.X, e.CellBounds.Y, e.CellBounds.Width, e.CellBounds.Height);
e.Graphics.FillRectangle(Brushes.White, r);
Font f = new Font(e.CellStyle.Font.FontFamily, 7);
e.Graphics.DrawString(number, f, Brushes.Black, r);
e.PaintContent(e.ClipBounds);
e.Handled = true;
}
}
//Function for BoardCell design
public void Board_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
//make letter uppercase
try
{
form.Board[e.ColumnIndex, e.RowIndex].Value = form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().ToUpper();
}
catch (Exception)
{
}
//Only 1 letter per cell
try
{
if (form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().Length > 1)
{
form.Board[e.ColumnIndex, e.RowIndex].Value = form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().Substring(0, 1);
}
}
catch (Exception)
{
}
//Change color if correct
try
{
if (form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().ToUpper().Equals(form.Board[e.ColumnIndex, e.RowIndex].Tag.ToString().ToUpper()))
{
form.Board[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.DarkGreen;
}
else
{
form.Board[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.Red;
}
}
catch (Exception)
{
}
}
//Function for formatting Cell design on Board
public void formatCell(int row, int col, String letter)
{
DataGridViewCell c = form.Board[col, row];
c.Style.BackColor = Color.White;
c.ReadOnly = false;
c.Style.SelectionBackColor = Color.Cyan;
c.Tag = letter;
}
//Initialize Cell component
public void InitializeComponent()
{
this.SuspendLayout();
//
// Cell
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "Cell";
this.Load += new System.EventHandler(this.Cell_Load);
this.ResumeLayout(false);
}
//Load Cell
private void Cell_Load(object sender, EventArgs e)
{
}
}
//Class for Cell id's
public class id_cells
{
public int X;
public int Y;
public String direction;
public String number;
public String word;
public String clue;
public id_cells(int x, int y, String d, String n, String w, String c)
{
this.X = x;
this.Y = y;
this.direction = d;
this.number = n;
this.word = w;
this.clue = c;
}
} //end of class
}
You are trying to call menuOptions.aboutToolStripMenuItem_Click(); but the function requires 2 parameters (object sender, EventArgs e);
You need to supply those parameters.
This is done automatically by the framework when you wire up events:
this.Load += new System.EventHandler(this.Cell_Load);
private void Cell_Load(object sender, EventArgs e)
{
}
When the Load event is triggered by the framework when a form is loaded, it will automatically pass in the sender and event args.
If you are trying to call those functions manually (i.e. in YOUR code), then you must supply those parameters.
You can fake it by using:
CellLoad(this, EventArgs.Empty);
What is confusing is why you have decided to call these functions during initialisation.
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
Why do you want to press the exit button during startup?
Related
In Microsoft Visual Studio, I have Form1.cs, which contains several buttons such as btnHome, etc. When one of them is clicked (in this case btnHome), it opens the child form FormHome.cs. When the Start button is clicked in FormHome.cs, a process starts that runs every 10 seconds and does not stop until the stop or pause button is clicked. However, if I click on the btnStatus or btnSettings button from the menu bar and return to the btnHome button, the process already stopped. What should I do to prevent it from stopping? I know that the data needs to be saved in a database, I'll handle that later, but how can I make the process not stop if navigating between other child forms?
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test
{
public partial class panel : Form
{
private Button currentButton;
private Random random;
private int tempIndex;
private Form activateForm;
public panel()
{
InitializeComponent();
random = new Random();
}
private Color SelectThemeColor()
{
int index = random.Next(ThemeColor.ColorList.Count);
while (tempIndex == index)
{
index = random.Next(ThemeColor.ColorList.Count);
}
tempIndex = index;
string color = ThemeColor.ColorList[index];
return ColorTranslator.FromHtml(color);
}
private void ActivateButton(object btnSender)
{
if (btnSender != null)
{
if (currentButton != (Button)btnSender)
{
DisableButton();
Color color = SelectThemeColor();
currentButton = (Button)btnSender;
currentButton.BackColor = color;
currentButton.ForeColor = Color.White;
currentButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 12.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
panelTitleBar.BackColor = color;
}
}
}
private void DisableButton()
{
foreach (Control previousBtn in panelMenu.Controls)
{
if (previousBtn.GetType() == typeof(Button))
{
previousBtn.BackColor = panelMenu.BackColor;
previousBtn.ForeColor = Color.Gainsboro;
previousBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
}
}
}
private void OpenChildForm(Form childForm, object btnSender)
{
ActivateButton(btnSender);
if (activateForm != null)
{
activateForm.Close();
}
activateForm = childForm;
childForm.TopLevel = false;
childForm.FormBorderStyle = FormBorderStyle.None;
childForm.Dock = DockStyle.Fill;
this.panelDesktopPane.Controls.Add(childForm);
this.panelDesktopPane.Tag = childForm;
childForm.BringToFront();
childForm.Show();
lblTitle.Text = childForm.Text;
}
private void btnHome_Click(object sender, EventArgs e)
{
OpenChildForm(new Forms.FormHome(), sender);
}
private void btnStatus_Click(object sender, EventArgs e)
{
OpenChildForm(new Forms.FormStatus(), sender);
}
private void btnSettings_Click(object sender, EventArgs e)
{
OpenChildForm(new Forms.FormSettings(), sender);
}
}
}
FormHome.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
namespace test.Forms
{
public partial class FormHome : Form
{
private static readonly string IPv4Pattern = #"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
private System.Windows.Forms.Timer _timer;
public FormHome()
{
InitializeComponent();
homePanel2ListView1CurlResults.View = View.Details;
homePanel2ListView1CurlResults.Columns.Add("Time");
homePanel2ListView1CurlResults.Columns.Add("Result");
}
private void homePanel1Button2Start_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(homePanel1TextBox1PublicIP.Text))
{
MessageBox.Show("Please enter a IPv4 address.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!System.Text.RegularExpressions.Regex.IsMatch(homePanel1TextBox1PublicIP.Text, IPv4Pattern))
{
MessageBox.Show("Please enter a valid IPv4 address.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string selectedTime = homePanel1ComboBox1Time.SelectedItem?.ToString();
if (selectedTime == null)
{
MessageBox.Show("Please select a time.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
int interval = 10000;
_timer = new System.Windows.Forms.Timer
{
Interval = interval
};
_timer.Tick += new EventHandler(TimerTick);
_timer.Start();
}
private void homePanel1Button3Pause_Click(object sender, EventArgs e)
{
_timer.Stop();
}
private void homePanel1Button4Stop_Click(object sender, EventArgs e)
{
_timer.Stop();
homePanel2ListView1CurlResults.Items.Clear();
}
private void TimerTick(object sender, EventArgs e)
{
var result = GetPublicIP();
homePanel2ListView1CurlResults.Items.Add(new ListViewItem(new[] { DateTime.Now.ToString("HH:mm:ss"), result }));
}
private string GetPublicIP()
{
try
{
using (WebClient client = new WebClient())
{
string response = client.DownloadString("http://ifconfig.me");
return response;
}
}
catch (Exception ex)
{
MessageBox.Show("Error retrieving IP address: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return string.Empty;
}
}
}
}
The problem here is scope.
This isn't working because your timer is defined on FormHome and is destroyed when you navigate out of scope.
You could try passing your timer object as a parameter to other form when you navigate or try using an async task.
I would try something like this.
Form1.cs
private bool timerIsRunning;
...
private void btnHome_Click(object sender, EventArgs e)
{
OpenChildForm(new Forms.FormHome(timerIsRunning), sender);
}
FormHome.cs
bool timerIsRunning;
public FormHome(bool _timerIsRunning)
{
...
timerisRunning = _timerIsRunning;
}
private void homePanel1Button2Start_Click(object sender, EventArgs e)
{
timerIsRunning = true;
StartTimer();
}
private void homePanel1Button4Stop_Click(object sender, EventArgs e)
{
timerIsRunning = false;
}
async void StartTimer ()
{
while (timerIsRunning)
{
await Task.Delay(10000);
TimerTick();
}
}
private void TimerTick()
{
// Event code here
}
I have an onLoad event and it contains the variable which takes data from the database and now I need to pass that string to an onclick event of a button so that whenever it is pressed I can perform operations. I need to access word variable from load to onclick.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public string word, alphabets;
public int chances, score;
public Form2()
{
InitializeComponent();
}
public void Form2_Load(object sender, EventArgs e)
{
chances = 8;
score = 0;
alphabets = "abcdefghijklmnopqrstuvwxyz";
Random rnd = new Random();
int wordid = rnd.Next(1, 127);
label12.Text = chances.ToString();
label13.Text = score.ToString();
try
{
string myConnection1 = "datasource=localhost;port=3306;username=root;password=amit;";
MySqlConnection myConn1 = new MySqlConnection(myConnection1);
myConn1.Open();
int count = 0;
var cmd = new MySqlCommand(" select words from gamers.gamewords where id='" + wordid + "';", myConn1);
string word = (string)cmd.ExecuteScalar();
int length = word.Length;
label4.Text = length.ToString();
label7.Text = alphabets;
label14.Text = word;
myConn1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void button1_Click(object sender, EventArgs e)
{
//Code for Game Begins
int i = 0, j = 0;
int lengthcount = 0;
string choice = textBox1.Text;
string guess;
label14.Text = word + "**";
// for (i = 0; i<word.Length; i++)
/* {
if (word[i] == choice[0])
{
label14.Text = "Good Guess! You Scored a point";
lengthcount++;
score += 5;
guess = choice;
label9.Text= guess;
}
else
{
chances--;
guess = "______";
if (chances == 0)
{
label14.Text = "You Lost the Game! Turns Over";
button1.Enabled = false;
}
else
{
label14.Text = "Sorry! Try Again";
}
}
}*/
}
}
}
You can call the button1_Click like a method, but you can't pass a value to it directly, because the Click event are handled by the default EventHandler, so you have just the two parameters: object sender and EventArgs e:
button1_Click(sender, e);
But you can use a property (or a field / variable) in the Form2 class, to hold an value from the Form2_Load method, and after read then in the button1_Click method:
public partial class Form2 : Form
{
// ...
private string ValueToHold { get; set; }
// ...
public void Form2_Load(object sender, EventArgs e)
{
// ...
ValueToHold = "something";
// ...
}
public void button1_Click(object sender, EventArgs e)
{
// ...
// Use the ValueToHold here!
// ...
}
}
This question already has answers here:
How do you pass an object from form1 to form2 and back to form1?
(4 answers)
Closed 5 years ago.
I'm supposed to make a math practice program for kids. They should be able to choose 1 operation and the amount of digits (1, 2 or 3 digit) the numbers will have. It then has to out put 10 random questions according to the selection made by the kid, then once they have completed the quiz, it should display their results and which questions they got wrong.
I have two selections being made on form1, operations and # of digits, which are assigned numbers (1. (*) 2. (/) 3. (+) 4. (-)). All i need to do is communicate the operation number and # of digits to form2, where the questions will be generated and displayed.
Here's my code for form1 so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FinalProject
{
public partial class Form1 : Form
{
public static int operation = 0;
public static int digits = 0;
public Form1()
{
InitializeComponent();
}
// this is to make sure only one box is checked for both selections. Starts here
private void label1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void MulCB_CheckedChanged(object sender, EventArgs e)
{
if ( MulCB.Checked == true)
{
operation = 1;
DivCB.Checked = false;
AddCB.Checked = false;
SubCB.Checked = false;
}
}
private void DivCB_CheckedChanged(object sender, EventArgs e)
{
if (DivCB.Checked == true)
{
operation = 2;
MulCB.Checked = false;
AddCB.Checked = false;
SubCB.Checked = false;
}
}
private void AddCB_CheckedChanged(object sender, EventArgs e)
{
if (AddCB.Checked == true)
{
operation = 3;
DivCB.Checked = false;
SubCB.Checked = false;
MulCB.Checked = false;
}
}
private void SubCB_CheckedChanged(object sender, EventArgs e)
{
if (SubCB.Checked == true)
{
operation = 4;
DivCB.Checked = false;
AddCB.Checked = false;
MulCB.Checked = false;
}
}
private void oneDCB_CheckedChanged(object sender, EventArgs e)
{
if(oneDCB.Checked == true)
{
digits = 1;
twoDCB.Checked = false;
threeDCB.Checked = false;
}
}
private void twoDCB_CheckedChanged(object sender, EventArgs e)
{
if ( twoDCB.Checked == true)
{
digits = 2;
oneDCB.Checked = false;
threeDCB.Checked = false;
}
}
private void threeDCB_CheckedChanged(object sender, EventArgs e)
{
if (threeDCB.Checked == true)
{
digits = 3;
oneDCB.Checked = false;
twoDCB.Checked = false;
}
}
private void button8_Click(object sender, EventArgs e)
{
// operations: 1. (*) 2. (/) 3. (+) 4. (-)
// digits are as number indicates.
// Second window popup.
Form2 settingsForm = new Form2();
settingsForm.Show();
}
}
}
Here's form2, naked pretty much.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FinalProject
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void FinishedBtn_Click(object sender, EventArgs e)
{
}
}
}
This might work.
There are comments in the code.
The workflow is creating a new instance of the class Form2 and setting two public variables. Public means that they can be accessed from outside of the class (see here, if you want). Then the method Show() is called and the Form appears. In the Form2 code, the public variables now have the values previously specified and can be used.
Form1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FinalProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// this is to make sure only one box is checked for both selections. Starts here
private void label1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void MulCB_CheckedChanged(object sender, EventArgs e)
{
if ( MulCB.Checked == true)
{
operation = 1;
DivCB.Checked = false;
AddCB.Checked = false;
SubCB.Checked = false;
}
}
private void DivCB_CheckedChanged(object sender, EventArgs e)
{
if (DivCB.Checked == true)
{
operation = 2;
MulCB.Checked = false;
AddCB.Checked = false;
SubCB.Checked = false;
}
}
private void AddCB_CheckedChanged(object sender, EventArgs e)
{
if (AddCB.Checked == true)
{
operation = 3;
DivCB.Checked = false;
SubCB.Checked = false;
MulCB.Checked = false;
}
}
private void SubCB_CheckedChanged(object sender, EventArgs e)
{
if (SubCB.Checked == true)
{
operation = 4;
DivCB.Checked = false;
AddCB.Checked = false;
MulCB.Checked = false;
}
}
private void oneDCB_CheckedChanged(object sender, EventArgs e)
{
if(oneDCB.Checked == true)
{
digits = 1;
twoDCB.Checked = false;
threeDCB.Checked = false;
}
}
private void twoDCB_CheckedChanged(object sender, EventArgs e)
{
if ( twoDCB.Checked == true)
{
digits = 2;
oneDCB.Checked = false;
threeDCB.Checked = false;
}
}
private void threeDCB_CheckedChanged(object sender, EventArgs e)
{
if (threeDCB.Checked == true)
{
digits = 3;
oneDCB.Checked = false;
twoDCB.Checked = false;
}
}
private void button8_Click(object sender, EventArgs e)
{
// operations: 1. (*) 2. (/) 3. (+) 4. (-)
// digits are as number indicates.
// Second window popup.
// it's the question form, right?
Form2 questionForm = new Form2();
//"Write" your settings in the other form's variables
//You will have to write code that finds out which checkbox is which number! For now its fixed.
questionForm.operation = 2;
questionForm.digits = 1;
questionForm.Show();
//Hide Form1
this.Hide();
}
}
}
Form2:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FinalProject
{
public partial class Form2 : Form
{
public static int operation;
public static int digits;
public Form2()
{
InitializeComponent();
}
//do NOT paste this. It can be added by creating an event handler
// you also might not need this, but this method is called when this Form appears. It's an example.
// https://msdn.microsoft.com/en-us/library/zwwsdtbk(v=vs.80).aspx
private void Form2_Load(object sender, EventArgs e)
{
//here you can use your variables for example (also anywhere within this class!)
//e.g.
Textbox1.Text = (string)operation;
}
private void FinishedBtn_Click(object sender, EventArgs e)
{
}
}
}
I'm making an application for a friend's birthday, where a window with changing compliments is supposed to pop up.
The window freezes, however, and the labels don't change. I Googled it, and read something about using Backgroundworker in order to seperate the GUI-thread from the changing process.
Still doesn't work.
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace ProjectL
{
public partial class Form1 : Form
{
private MessageHandler theHandler = new MessageHandler();
private BackgroundWorker theBackgroundWorker = new BackgroundWorker();
public Form1()
{
InitializeComponent();
}
private void StartButton_Click(object sender, EventArgs e)
{
StartButton.Visible = false;
theBackgroundWorker.DoWork += new DoWorkEventHandler(theBackgroundWorker_doYourWork);
//theBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(theBackgroundWorker_doYourWork);
theBackgroundWorker.RunWorkerAsync();
theHandler.RunMessage(hBDLabel, youAreLabel, mainLabel, this);
}
void theBackgroundWorker_doYourWork(object sender, DoWorkEventArgs e)
{
theHandler.RunMessage(hBDLabel, youAreLabel, mainLabel, this);
}
}
}
This is what's supposed to happen from the background, using a class I've named MessageHandler:
class MessageHandler
{
public List<String> GenerateComplimentTexts()
{
List<String> stringList = new List<String>();
//Adding a bunch of compliments into a List<String>
return stringList;
}
public void RunMessage(Label hBDLabel, Label youAreLabel, Label mainLabel, Form1 form)
{
List<String> stringList = GenerateComplimentTexts();
Thread.Sleep(2000);
form.Text = "Happy Birthday Goose!!!";
hBDLabel.Text = "Happy Birthday Goose!";
Thread.Sleep(3000);
youAreLabel.Text = "You are...";
Thread.Sleep(2000);
foreach (String e in stringList)
{
mainLabel.Text = e;
//form.Test = e
Thread.Sleep(1000);
}
Thread.Sleep(3000);
mainLabel.Text = "";
youAreLabel.Text = FinalMessage;
}
private String _finalMessage = "FINAL MESSAGE";
public String FinalMessage {get {return _finalMessage;}}
}
Still, nothing changes on my window. Everything is pretty much frozen, except for the text in the top-bar of the form itself, if I choose to uncomment
form.Text = e;
Any advice?
You could achieve it using Timers instead of a BackgroundWorker.
It would probably look like this :
MainForm :
public partial class Form1 : Form
{
private Timer timer;
private MessageHandler theHandler = new MessageHandler();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
timer = new Timer();
timer.Interval = 1000;
timer.Tick += TimerOnTick;
// Initialize the other labels with static text here
}
private void TimerOnTick(object sender, EventArgs eventArgs)
{
theHandler.ShowNext(label1);
}
private void StartButton_Click(object sender, EventArgs e)
{
timer.Start();
}
}
And the MessageHandler class :
public class MessageHandler
{
private List<String> compliments = new List<string>();
private int index = 0;
public MessageHandler()
{
GenerateComplimentTexts();
}
private void GenerateComplimentTexts()
{
List<String> stringList = new List<String>();
//Adding a bunch of compliments into a List<String>
compliments = stringList;
}
public void ShowNext(Label label)
{
label.Text = compliments.ElementAt(index);
index = (index >= compliments.Count - 1) ? 0 : index + 1;
}
}
To update the UI, use the ReportProgress method of the background worker. ReportProgress raises the ProgressChanged event and you can update your UI from there. Be sure to set the WorkerReportsProgress property of the backgroundworker to true.
Try this code:
private void StartButton_Click(object sender, EventArgs e)
{
StartButton.Visible = false;
theBackgroundWorker.DoWork += new DoWorkEventHandler(theBackgroundWorker_doYourWork);
theBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(theBackgroundWorker_ProgressChanged);
theBackgroundWorker.RunWorkerAsync();
}
void theBackgroundWorker_doYourWork(object sender, DoWorkEventArgs e)
{
var w = sender as BackgroundWorker;
List<String> stringList = GenerateComplimentTexts();
Thread.Sleep(2000);
w.ReportProgress(0, "Happy Birthday Goose!!!");
w.ReportProgress(1, "Happy Birthday Goose!");
Thread.Sleep(3000);
w.ReportProgress(2, "You are...");
Thread.Sleep(2000);
foreach (String e in stringList)
{
w.ReportProgress(3, e);
Thread.Sleep(1000);
}
Thread.Sleep(3000);
w.ReportProgress(3, "");
w.ReportProgress(2, FinalMessage);
}
void theBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var msg = e.UserState.ToString();
switch (e.ProgressPercentage)
{
case 0:
form.Text = msg;
break;
case 1:
hBDLabel.Text=msg;
break;
case 2:
youAreLabel.Text =msg;
break;
case 3:
mainLabel.Text=msg;
break;
}
}
Have a try with this:
1.) Copy Timer to Form
2.) Copy the following Code into the timer1_tick-Event.
private int _counter;
private int _currentIndex;
private void timer1_Tick(object sender, EventArgs e)
{
switch (_counter)
{
case 1:
form.Text = "Happy Birthday Goose!!!";
hBDLabel.Text = "Happy Birthday Goose!";
break;
case 2:
timer1.Interval = 3000;
break;
case 3:
youAreLabel.Text = "You are...";
break;
case 4:
if (stringlist.count = (_currentIndex -1))
{
timer1.Enabled = false;
}else {
mainLabel.Text = e;
timer1.Interval = 1000;
return;
}
break;
}
_counter ++;
}
Not the most elegant way, but it should work.
I have a checkbox shown as button. I want to make it flash when it is checked. From what Ive found, i think the simplest way is to use a timer to rotate the background color of the button.
Where I am stuck is finding the back color of the checked button. Can someone tell me what the back color is changed to by default (via designer) when the button is checked? Without that I cannot get the timer to begin the oscillation.
What I have is a Mute Button. When the mute is active i want the button to flash until it is pressed again to turn the mute off.
In case I'm wrong and the back color actually does not change, what changes about the button to make it appear pressed?
code:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
instructorTimer.Enabled = true;
}
private void instructorTimer_Tick(object sender, EventArgs e)
{
// interval is 2000
if (checkBox1.BackColor == System.Drawing.SystemColors.Control)
checkBox1.BackColor = System.Drawing.SystemColors.ControlDark;
else
checkBox1.BackColor = System.Drawing.SystemColors.Control;
}
Maybe SystemColors.Control is what you are looking for.
Make sure you have the tick event hooked up. It looks suspect:
private void Form1_Load(object sender, EventArgs e) {
timer1.Tick += instructorTimer_Tick;
}
I would also change the color immediately, for instant feedback:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox1.BackColor = SystemColors.ControlDark;
timer1.Enabled = true;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox1.BackColor = Color.Green;
Application.DoEvents();
TimeSpan ts = new TimeSpan();
do
{
}
while (ts.Milliseconds == 2000);
checkBox1.BackColor = SystemColors.Control;
}
If you're willing to use a UserControl instead of trying to repurpose Button - the following should work great and you can extend it if something doesn't work like you like:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace FlashyButton
{
public partial class FlashyButton : UserControl
{
private CheckState _Checked = CheckState.Unchecked;
[Browsable(true)]
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
lblText.Text = value;
Invalidate();
}
}
public FlashyButton()
{
this.CausesValidation = true;
InitializeComponent();
lblText.MouseClick += (sender, e) => { OnMouseClick(null); };
}
public void SetFont(Font WhichFont)
{
this.Font = WhichFont;
}
public CheckState GetCheckedState()
{
return this._Checked;
}
public void SetCheckedState(CheckState NewCheckState)
{
this._Checked = NewCheckState;
}
protected override void OnMouseClick(MouseEventArgs e)
{
this._Checked = (this._Checked == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked;
this.BorderStyle = (this._Checked == CheckState.Checked) ? System.Windows.Forms.BorderStyle.Fixed3D : System.Windows.Forms.BorderStyle.FixedSingle;
tmrRedraw.Enabled = (this._Checked == CheckState.Checked);
if (this._Checked == CheckState.Unchecked)
{
this.BackColor = SystemColors.Control;
}
this.Invalidate(); //Force redraw
base.OnMouseClick(e);
}
private float Percent = 100;
private void tmrRedraw_Tick(object sender, EventArgs e)
{
Percent -= 2;
if (Percent < -100) Percent = 100;
this.BackColor = Color.FromArgb(
255,
Lerp(255, SystemColors.Control.R, (int)Math.Abs(Percent)),
Lerp(0, SystemColors.Control.G, (int)Math.Abs(Percent)),
Lerp(0, SystemColors.Control.B, (int)Math.Abs(Percent))
);
}
private int Lerp(int Start, int End, int Percent)
{
return ((int) ((float)(End - Start) * ((float)Percent / 100f)) + Start);
}
}
}
And here is the .Designer code as well (just replace what you already have when you make a new control by this name)
namespace FlashyButton
{
partial class FlashyButton
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.lblText = new System.Windows.Forms.Label();
this.tmrRedraw = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// lblText
//
this.lblText.AutoSize = true;
this.lblText.Location = new System.Drawing.Point(4, 4);
this.lblText.Name = "lblText";
this.lblText.Size = new System.Drawing.Size(55, 17);
this.lblText.TabIndex = 0;
this.lblText.Text = "Sample";
//
// tmrRedraw
//
this.tmrRedraw.Interval = 10;
this.tmrRedraw.Tick += new System.EventHandler(this.tmrRedraw_Tick);
//
// FlashyButton
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.lblText);
this.Name = "FlashyButton";
this.Size = new System.Drawing.Size(148, 148);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblText;
private System.Windows.Forms.Timer tmrRedraw;
}
}
This worked for me when I had a CheckBox with Appearance = Button and FlatStyle = Flat and wanted it flashing when checked:
private void timer_Flashing_Tick(object sender, EventArgs e)
{
if (checkBox_Refresh.Checked)
{
if (checkBox_Refresh.FlatAppearance.CheckedBackColor == Color.Red)
{
checkBox_Refresh.FlatAppearance.CheckedBackColor = Color.Transparent;
}
else
{
checkBox_Refresh.FlatAppearance.CheckedBackColor = Color.Red;
}
}
}