Reputation: 1945
I am currently building a windows form application and I have got the next problem, I can't declare a variable global because the syntax im using won't allow me to do that, also, i need to declare the variable in the method it self and at last, it must loop so its able to count. This is what I have got so far:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
int i;
m_bIsTimerOn = true;
while (m_bIsTimerOn)
{
i++;
label1->Text = (i.ToString());
}
}
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
m_bIsTimerOn = false;
timer1->Enabled = false;
}
m_bIsTimerOn is a globally boolean. As you might see here my problem is if i press button1 the program is just stuck in the while loop. I would like to know that the moment you press button2 the while loop stops I also would like to know if this is even possible. If you could response in c++ that would also be fine.
Thank you in advance.
Upvotes: 1
Views: 70
Reputation: 67128
I suppose you want to increment i
while timer is on. If you need to update i
for each timer tick then it's pretty easy, remove that loop (and that variable BTW) and simply do update inside timer Tick
event:
private:
int _i;
void button1_Click(Object^ sender, EventArgs^ e) {
_i = 0;
timer1->Enabled = true;
}
void _timer1_Tick(Object^ sender, EventArgs^ e) {
label1->Text = (i++).ToString();
}
void button2_Click(Object^ sender, EventArgs^ e) {
timer1->Enabled = false;
}
If i must be updated independently from timer ticks then you have to move it to a BackgroundWorker
or simply in event handler for Application::Idle:
void OnIdle(Object^ sender, EventArgs^ e) {
label1->Text = (_i++).ToString();
}
void button1_Click(Object^ sender, EventArgs^ e) {
_i = 0;
Application::Idle += gcnew EventHandler(this, Form1::OnIdle);
timer1->Enabled = true;
}
void button2_Click(Object^ sender, EventArgs^ e) {
Application::Idle -= gcnew EventHandler(this, Form1::OnIdle);
timer1->Enabled = false;
}
As final note: you may even keep your loop as is and put a call to Application::DoEvents()
just after your label1->Text = (i.ToString());
but this will probably consumes a lot of CPU, slow down your application and open your code to reentrancy, I'd really avoid something like that...
Upvotes: 1
Reputation: 1796
Your program is in endless loop because the while loop prevents the messages from getting processed and hence your button2_Click does not get invoked. To make you application capable of processing the messages that occurs, add Application.DoEvents() in your loop as:
while (m_bIsTimerOn)
{
i++;
label1->Text = (i.ToString());
Application.DoEvents(); // causes the application to handle pending events
}
So now, if you press the second button, m_bIsTimerOn will become false and your loop will terminate.
Upvotes: 0