I don't know how to explain this clearly but I will try my best.
I'm using a DispatcherTimer class in my windows phone 8 project. I've got some check boxes and when a check box is checked and the button is pressed the countdown from a bus schedule starts. Everything works perfectly here but when I uncheck the check box and when I check another one, the same bus time starts and it goes down(countdown) by 2 seconds now. If I uncheck the check box and check another again the same time starts to countdown and the countdown goes by 3 seconds... I don't understand how, because on the click_event there is always a new instance of the class.
The only thing that solves the problem is to reload my wp8 page and check something again and press the button for the countdown to start.
Note: I'm reading my times from a .txt file which are store on a folder within my project (using streamreader).
Any suggestions?
Here is some code:
CheckBox[] listchekbox;
DispatcherTimer timer;
private void Button_Click(object sender, RoutedEventArgs e)//BUTTON CLICK
{
timer = new DispatcherTimer();
listchekbox = new CheckBox[4] { Check1, Check2, Check3, Check4 };
if (Onlyoneclick(listchekbox, 0)) { Gettingbustime(path_names[0]); }
else if (Onlyoneclick(listchekbox, 1)) { Gettingbustime(path_names[1]); }
timer.Interval = new TimeSpan(0,0,1);
timer.Tick += onclick;
timer.Start();
}
private void onclick(object sender, EventArgs e) // TIMER EVENT COUNT
{
Countdown(bus1); // the parameter is the textbox where the result is displayed
Countdown(bus2);
}
private bool Onlyoneclick(CheckBox[] itemselected,int id) // this is not so important
{
int itemcounter = 0;
int falsecounter = 0;
for (int i = 0; i < listchekbox.Length; i++)
{
if (itemselected[i].IsChecked == true && id == i)
{
itemcounter++;
}
else if (itemselected[i].IsChecked == true) { falsecounter++; }
}
if (itemcounter == 1 && falsecounter==0) { return true; }
else { return false; }
}
public void Countdown(TextBlock tx)
{
string minute = tx.Text.Substring(0, 2);
string sekunde = tx.Text.Substring(3, 2);
int minute1 = Convert.ToInt32(minute);
int sekunde1 = Convert.ToInt32(sekunde);
sekunde1 = sekunde1 - 1;
if (sekunde1 < 0)
{
minute1 = minute1 - 1;
sekunde1 = 59;
}
if (minute1 < 0)
{
timer.Stop();
MessageBox.Show("Autobus left!");
}
if (sekunde1 < 10) { tx.Text = minute1.ToString() + ":0" + sekunde1.ToString(); }
else { tx.Text = minute1.ToString() + ":" + sekunde1.ToString(); }
if (minute1 < 10) { tx.Text = "0" + minute1.ToString() + ":" + sekunde1.ToString(); }
if (minute1 < 10 && sekunde1 < 10) { tx.Text = "0" + minute1.ToString() + ":0" + sekunde1.ToString(); }
}
Try removing this code from Button_Click:
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0,0,1);
timer.Tick += onclick;
And add it instead to your constructor.
Related
I just started with the programming language C# a week ago and used the program Visual Studio with win Forms. I've had a problem for a few days.
I want to connect a ProgressBar to different TextBoxes. So that with each filled textBox the ProgressBar increases. When the text is removed, the progressBar should go down again.
So far I've only managed to get the progressBar to increase in general or that the progress bar increases with each letter in a textBox.
Textboxes are Vorname,Nachname,PLZ,Wohnort,Hausnummer,Straße
ProgressBar is Fortschrittsanzeige
private void button1_Click(object sender, EventArgs e)
{
Fortschrittsanzeige.Dock = DockStyle.Bottom;
Fortschrittsanzeige.Maximum = 60;
Fortschrittsanzeige.Minimum = 0;
Fortschrittsanzeige.Style = ProgressBarStyle.Continuous;
if (
Vorname.Text.Length <= 0 ||
Nachname.Text.Length <= 0 ||
PLZ.Text.Length < 4 ||
Wohnort.Text.Length <= 0 ||
Hausnummer.Text.Length <= 0 ||
Straße.Text.Length <= 0
)
{
textBox7.Text = ("Bitte überprüfe deine Eingabe");
}
else
{
Sendebutton.Text = "Gesendet";
textBox7.Text = "Vielen Dank" + Vorname.Text + " " + Nachname.Text + ", wir
haben deine Daten erhalten.";
}
if (Vorname.Text.Length <= 0)
{
Vorname.BackColor = Color.IndianRed;
}
else
{
Vorname.BackColor = Color.White;
Fortschrittsanzeige.Value += 10;
}
if (Nachname.Text.Length <= 0)
{
Nachname.BackColor = Color.IndianRed;
}
else
{
Nachname.BackColor = Color.White;
Fortschrittsanzeige.Step += 10;
}
if (PLZ.Text.Length < 4)
{
PLZ.BackColor = Color.IndianRed;
}
else
{
PLZ.BackColor = Color.White;
Fortschrittsanzeige.Step += 10;
}
if (Wohnort.Text.Length <= 0)
{
Wohnort.BackColor = Color.IndianRed;
}
else
{
Wohnort.BackColor = Color.White;
Fortschrittsanzeige.Step += 10;
}
if (Hausnummer.Text.Length <= 0)
{
Hausnummer.BackColor = Color.IndianRed;
}
else
{
Hausnummer.BackColor = Color.White;
Fortschrittsanzeige.Step += 10;
}
if (Straße.Text.Length <= 0)
{
Straße.BackColor = Color.IndianRed;
}
else
{
Straße.BackColor = Color.White;
Fortschrittsanzeige.Step += 10;
}
}
You can handle the TextChanged event on each TextBox like so
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Length > 0 && _textbox1IsEmpty)
{
progressBar1.Value += 10;
_textbox1IsEmpty = false;
}
else if (textBox1.Text.Length <= 0)
{
progressBar1.Value -= 10;
_textbox1IsEmpty = true;
}
}
and add a private property in your class
private bool _textbox1IsEmpty = true;
You can make a function to optimize it and don't have duplicate code
Here are a few tips to get you started with WinForms and make it easier to connect multiple TextBoxes with a ProgressBar.
The textboxes (and other controls) that are on a Form can be found in the Controls collection of the form.
All of the textboxes on the form can be obtained with a simple query.
For example, in the form Constructor you could go though all the textboxes and attach a TextChanged handler to each.
public MainForm()
{
InitializeComponent();
foreach (TextBox textBox in Controls.OfType<TextBox>())
{
textBox.TextChanged += onAnyTextChanged;
onAnyTextChanged(textBox, EventArgs.Empty); // Initialize
}
ActiveControl = Fortschrittsanzeige;
}
Multiple text boxes can all point to a common event handler.
System.Linq reduces the amount of code needed for things like matching and sorting.
What we're able to do is perform a validation based on all the textboxes whenever any textbox changes.
const int TEXTBOX_COUNT = 6;
private void onAnyTextChanged(object? sender, EventArgs e)
{
if(sender is TextBox textbox)
{
bool isValid;
if(textbox.PlaceholderText == "PLZ")
{
isValid = textbox.TextLength > 3;
}
else
{
isValid = !string.IsNullOrWhiteSpace(textbox.Text);
}
textbox.BackColor = isValid ? Color.White : Color.LightSalmon;
}
// Use System.Linq to count the number of valid textboxes (based on BackColor).
float countValid =
Controls
.OfType<TextBox>()
.Count(_=>_.BackColor== Color.White);
var pct = countValid / TEXTBOX_COUNT;
Fortschrittsanzeige.Value = (int)(pct * Fortschrittsanzeige.Maximum);
Sendebutton.Enabled = countValid.Equals(TEXTBOX_COUNT);
Fortschrittsanzeige.Visible = !Sendebutton.Enabled;
}
The handler allows for "special cases" and will make the Fortschrittsanzeige go backwards if the changed value is no longer valid.
When all textboxes are valid hide Fortschrittsanzeige and enable Sendebutton.
in this program, when the Recall button (recallBtn_Click()) is clicked, it calls a method (that calculates directions) from another class which should then call the showPath() method. the show path method should then display its output in a textBox. But the values don't show even though i can see from debugging that the values are being sent to the text box. can anybody tell me where i went wrong?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
storeRetSelect.SelectedIndex = 0;
PrioritySelect.SelectedIndex = 0;
}
public void showPath(List<PathFinderNode> mPath)
{
var T = new Form1().directionsTextBox;
foreach (PathFinderNode node in mPath)
{
if ((node.X - node.PX) > 0) { T.Text += "Right" + System.Environment.NewLine ; }
if ((node.X - node.PX) < 0) { T.Text += "Left" + System.Environment.NewLine; }
if ((node.Y - node.PY) > 0) { T.Text += "UP" + System.Environment.NewLine; }
if ((node.Y - node.PY) < 0) { T.Text += "Down" + System.Environment.NewLine; }
}
}
private void recallBtn_Click(object sender, EventArgs e)
{
var path = new pathPlan();
string desigString = inputTextBox.Text;
int[] desig = new int[3];
for (int i = 0; i < desigString.Length; i++) { desig[i] = (int)char.GetNumericValue(desigString[i]); }
path.Recall(desig[1], desig[2], (-1) * desig[0]);
}
}
With this line you are initialising a new object and get the reference of the textbox there.
var T = new Form1().directionsTextBox;
But I assume you want to use the textbox of the form which is allready open. Change the line to the following to access the textbox of the current object.
var T = this.directionsTextBox;
please help me i wanted to set my pictureBox into visible for only 1 second then hide it again before going to the next loop. here's my code.
private void sampleTxt_Validated(object sender, EventArgs e)
{
words = "AB"
char[] ch = words.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
if (ch[i] == 'A')
{
a = true;
Application.Idle += imageA;
}
else if (ch[i] == 'B')
{
b = true;
Application.Idle += imageB;
}
}
}
private void imageA(object sender, EventArgs arg)
{
TimeSpan ts;
if(a == true)
{
letterA.Visible = true;
stopWatchA.Start();
ts = stopWatchA.Elapsed;
if (ts.Seconds >= 1)
{
stopwatch();
letterA.Visible = false;
a = false;
}
}
}
private void imageB(object sender, EventArgs arg)
{
TimeSpan ts;
if (b == true)
{
letterB.Visible = true;
stopWatchB.Start();
ts = stopWatchB.Elapsed;
if (ts.Seconds >= 0.5)
{
stopwatch();
letterB.Visible = false;
b = false;
}
}
}
the problem with my code is that it displays both images at the same time.
I want to display the letter "A" image for 1sec first before looping again to display the second image. Is that possible?
You need a loop on letterB, also maybe change the timer from 0.5 to 1.0
I am writing a WinForm application to use SNMP calls either every 30 seconds or 1 minute.
I have a timer working for calling my SNMP commands, but I want to add a texbox counter that display the total time elapsed during the operation.
There are many problems I am having so here is a list:
I want my SNMP timer 'timer' to execute once before waiting the allotted time so I have it going off at 3 seconds and then changing the interval in my handler. But this sometimes makes the timer go off multiple times which is not what I want.
Every time 'timer' goes off and my SNMP calls execute my counter timer 'appTimer' becomes out of sync. I tried a work around where I check if it is in the other handler and then just jump the timer to its appropriate time. Which works but I feel this is making it too complicated.
My last issue, that I know of, happens when I stop my application using my stop button which does not completely exit the app. When I go to start another run the time between both timers is becomes even greater and for some reason my counting timer 'appTimer' starts counting twice as fast.
I hope this description isn't too confusing but here is my code anyway:
using System;
using System.Net;
using SnmpSharpNet;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public static bool stop = false;
static bool min = true, eye = false, firstTick = false;
static string ipAdd = "", fileSaveLocation = "";
static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
static System.Windows.Forms.Timer appTimer = new System.Windows.Forms.Timer();
static int alarmCounter = 1, hours = 0, minutes = 0, seconds = 0, tenthseconds = 0, count = 0;
static bool inSNMP = false;
static TextBox textbox, timeTextbox;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textbox = outputBox;
timeTextbox = timeBox;
ipAdd = "192.168.98.107";
fileSaveLocation = "c:/Users/bshellnut/Desktop/Eye.txt";
min = true;
inSNMP = false;
}
private void IPtext_TextChanged(object sender, EventArgs e)
{
ipAdd = IPtext.Text;
}
private void stopButton_Click(object sender, EventArgs e)
{
stop = true;
timer.Stop();
appTimer.Stop();
count = 0;
hours = minutes = seconds = tenthseconds = 0;
inSNMP = false;
}
// This is the method to run when the timer is raised.
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
inSNMP = true;
timer.Stop();
if (firstTick == true)
{
// Sets the timer interval to 60 seconds or 1 second.
if (min == true)
{
timer.Interval = 1000 * 60;
}
else
{
timer.Interval = 1000 * 30;
}
}
// Displays a message box asking whether to continue running the timer.
if (stop == false)
{
textbox.Clear();
// Restarts the timer and increments the counter.
alarmCounter += 1;
timer.Enabled = true;
System.IO.StreamWriter file;
//if (eye == true)
//{
file = new System.IO.StreamWriter(fileSaveLocation, true);
/*}
else
{
file = new System.IO.StreamWriter(fileSaveLocation, true);
}*/
// SNMP community name
OctetString community = new OctetString("public");
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
param.Version = SnmpVersion.Ver2;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(ipAdd);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Define Oid that is the root of the MIB
// tree you wish to retrieve
Oid rootOid;
if (eye == true)
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.14"); // ifDescr
}
else
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.15");
}
// This Oid represents last Oid returned by
// the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetBulk);
// In this example, set NonRepeaters value to 0
pdu.NonRepeaters = 0;
// MaxRepetitions tells the agent how many Oid/Value pairs to return
// in the response.
pdu.MaxRepetitions = 5;
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to 0
// and during encoding id will be set to the random value
// for subsequent requests, id will be set to a value that
// needs to be incremented to have unique request ids for each
// packet
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV2Packet result;
try
{
result = (SnmpV2Packet)target.Request(pdu, param);
}
catch (SnmpSharpNet.SnmpException)
{
timer.Stop();
textbox.Text = "Could not connect to the IP Provided.";
break;
}
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
textbox.Text = "Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex;
lastOid = null;
break;
}
else
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
count++;
textbox.Text += "#" + count + " " + v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
" " + v.Value.ToString() + Environment.NewLine;
file.WriteLine("#" + count + ", " + v.Oid.ToString() + ", " + SnmpConstants.GetTypeName(v.Value.Type) +
", " + v.Value.ToString(), true);
if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
lastOid = null;
else
lastOid = v.Oid;
}
else
{
// we have reached the end of the requested
// MIB tree. Set lastOid to null and exit loop
lastOid = null;
}
}
}
}
else
{
//Console.WriteLine("No response received from SNMP agent.");
textbox.Text = "No response received from SNMP agent.";
//outputBox.Text = "No response received from SNMP agent.";
}
}
target.Close();
file.Close();
}
else
{
// Stops the timer.
//exitFlag = true;
count = 0;
}
}
private static void ApplicationTimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
tenthseconds += 1;
if (tenthseconds == 10)
{
seconds += 1;
tenthseconds = 0;
}
if (inSNMP && !firstTick)
{
if (min)
{
seconds = 60;
}
else
{
textbox.Text += "IN 30 SECONDS!!!";
if (seconds < 30)
{
seconds = 30;
}
else
{
seconds = 60;
}
}
}
if(seconds == 60)
{
seconds = 0;
minutes += 1;
}
if(minutes == 60)
{
minutes = 0;
hours += 1;
}
timeTextbox.Text = (hours < 10 ? "00" + hours.ToString() : hours.ToString()) + ":" +
(minutes < 10 ? "0" + minutes.ToString() : minutes.ToString()) + ":" +
(seconds < 10 ? "0" + seconds.ToString() : seconds.ToString()) + "." +
(tenthseconds < 10 ? "0" + tenthseconds.ToString() : tenthseconds.ToString());
inSNMP = false;
firstTick = false;
}
private void eyeButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = true;
stop = false;
count = 0;
hours = minutes = seconds = tenthseconds = 0;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Interval = 3000;
firstTick = true;
appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor);
appTimer.Interval = 100;
appTimer.Start();
timer.Start();
}
private void jitterButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = false;
stop = false;
count = 0;
hours = minutes = seconds = tenthseconds = 0;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Interval = 3000;
firstTick = true;
appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor);
appTimer.Interval = 100;
appTimer.Start();
timer.Start();
}
private void Seconds_CheckedChanged(object sender, EventArgs e)
{
min = false;
}
private void Minutes_CheckedChanged(object sender, EventArgs e)
{
min = true;
}
private void exitButton_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void savetextBox_TextChanged(object sender, EventArgs e)
{
fileSaveLocation = savetextBox.Text;
}
}
}
This is very easy to do with a single timer. The timer has a 1/10th second resolution (or so) and can be used directly to update the elapsed time. You can then use relative elapsed time within that timer to fire off your SNMP transaction, and you can reschedule the next one dynamically.
Here's a simple example
using System;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
DateTime lastSnmpTime;
TimeSpan snmpTime = TimeSpan.FromSeconds(30);
DateTime startTime;
TextBox elapsedTimeTextBox;
Timer timer;
public Form1()
{
timer = new Timer { Enabled = false, Interval = 10 };
timer.Tick += new EventHandler(timer_Tick);
elapsedTimeTextBox = new TextBox { Location = new Point(10, 10), ReadOnly = true };
Controls.Add(elapsedTimeTextBox);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
startTime = DateTime.Now;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
// Update elapsed time
elapsedTimeTextBox.Text = (DateTime.Now - startTime).ToString("g");
// Send SNMP
if (DateTime.Now - lastSnmpTime >= snmpTime)
{
lastSnmpTime = DateTime.Now;
// Do SNMP
// Adjust snmpTime as needed
}
}
}
Updated Q&A
With this code the timer fires once at the beginning where after I
press the stop button and call timer.Stop() and then press my start
button the timer doesn't fire until roughly 12 seconds later. Will
resetting the DateTimes fix this?
When the user presses the Start button, set lastSnmpTime = DateTime.MinValue. This causes the TimeSpan of (DateTime.Now - lastSnmpTime) to be over 2,000 years, so it will be greater than snmpTime and will fire immediately.
Also my output time in the text box looks like this: 0:00:02.620262.
Why is that? Is there a way to make it display only 0:00:02.62?
When you subtract two DateTime values, the result is a TimeSpan value. I used a standard TimeSpan formatting string of "g". You can use a custom TimeSpan formatting string of #"d\:hh\:mm\:ss\.ff" to get days:hours:minutes:seconds.fraction (2 decimal places).
Also will the timer go on and print out to the text box when it is run
for over 9 hours? Because I plan to have this running for 24 hrs+
If you use the custom format with 'd' to show the number of days, it will run for TimeSpan.MaxValue which is slightly more than 10,675,199 days, which is more than 29,000 years.
My program opens a series of forms all over the screen, am I able to code in an escape method, so on typing of the word "test" the program will close?
I was looking at the msdn keypress and how they use a switch, would I use something similar to check for the pressed key and if the correct key is pressed, a counter will increment of the correct key presses until, for "test", 4 will be reached, and if the pressed key is incorrect reset the counter and start over until the right order of keys are entered.
I hope that makes sense :P
public partial class TrollFrm : Form
{
int number = 1; //change to 2 and have the first instance of troll count = number - 1
System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public TrollFrm()
{
InitializeComponent();
this.Text = "Trololol - Troll Count: " + number;
startTimer();
}
private void TrollFrm_Load(object sender, EventArgs e)
{
//this.Enabled = false;
}
private void TrollFrm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
public void startTimer()
{
myTimer.Tick += new EventHandler(createForm);
//myTimer.Interval = 500;
myTimer.Start();
}
public void createForm(Object myObject, EventArgs myEventArgs)
{
Form frm = new TrollChildFrm();
Random randomX = new Random();
Random randomY = new Random();
frm.Text = "Trololol - Troll Count: " + number;
int xValue;
int yValue;
number++;
if (number % 2 == 0) //number is even.
{
xValue = (Convert.ToInt32(randomX.Next(1, 1920))) + 200;
yValue = (Convert.ToInt32(randomY.Next(1, 1080))) - 200;
}
else //number is not even.
{
xValue = (Convert.ToInt32(randomX.Next(1, 1920))) - 200;
yValue = (Convert.ToInt32(randomY.Next(1, 1080))) + 200;
}
frm.Show();
frm.Location = new Point(xValue, yValue);
if (number == 20)
{
myTimer.Stop();
}
}
It is an implementation you could use for scenario you described (not tested though):
int exitKeysCount = 0;
private void TrollFrm_KeyDown(object sender, KeyEventArgs e)
{
if (exitKeysCount == 0 && e.KeyCode == Keys.T)
exitKeysCount = 1;
else if (exitKeysCount == 1 && e.KeyCode == Keys.E)
exitKeysCount = 2;
else if (exitKeysCount == 2 && e.KeyCode == Keys.S)
exitKeysCount = 3;
else if (exitKeysCount == 3 && e.KeyCode == Keys.T)
this.Close();
else exitKeysCount = 0;
}
I assumed TrollFrm is your parent form, if they are all invoked somewhere else replace this.Close() with some function in main program function, also TrollFrm needs focus during key presses.
try this parent on your parent form.
int trollCount = 0;
private void TrollFrm_KeyDown(object sender, KeyEventHandler e)
{
if (trollCount == 0 && e.KeyCode == Keys.T)
{
trollCount = 1;
frm.Text = "Trololol - Troll Count:" + trollCount
}
else if (trollCount == 1 && e.KeyCode== Keys.E)
{
trollCount = 2;
frm.Text = "Trololol - Troll Count:" + trollCount
}
else if (trollCount == 2 && e.KeyCode== Keys.S)
{
trollCount = 3;
frm.Text = "Trololol - Troll Count:" + trollCount
}
else if (trollCount == 4 && e.KeyCode== Keys.T)
{
trollCount = 4;
this.Close();
}
else
trollCount = 0;
tell me if you need anything else.