Click here to Skip to main content
15,886,065 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
Hello everyone!

I have a question like this: let say I have a window form application written in Visual C++ 2010. There are 4 buttons (button1, button2, button3, button4) on the main form. Each button of button1, button2, button3 is associated with an event (event1, event2, event3 respectively). Now what I want to do is when I click on button4, event1 begins to start, after for example 5 seconds, the event2 begins to start and after 4 seconds the event3 begins to start. How could I do that? I think we could use something like Thread->Sleep(int miliseconds) or Timer.

This is what I've added after some people said that my purpose is weird.
Well acctually I'm using visual C++ 2010 to control a washing machine through a Analog-to-digital converter. Each button is for controlling an element like an engine (or motor ), or something like a valve or water pumps. So Each element is turned on after some time and so on. The button4 is for a particular algorithm of controlling the process of water flowing.

Any help would be appreciated!
Thanks in advanced!
Posted
Updated 13-Jun-12 2:39am
v4
Comments
Sergey Alexandrovich Kryukov 13-Jun-12 2:37am    
Is it .NET? And C++/CLI (not C++)? Then tag it properly. You platform? Tag it. You won't be able to get valid answers if you do not provide comprehensive relevant information.
--SA
Sergey Alexandrovich Kryukov 13-Jun-12 2:39am    
Also, why such a weird schema of events? What are event types you are interested in? Don't think you can get valid answers if you are not motivating weird things. Here is why: if one suspects that what you want is wrong, who will waste time on explaining how, as you won't be able to use help anyway. That's why you should start from explaining your goal.
--SA
svatstika 13-Jun-12 8:35am    
Thank SAKrykov for such a good advice. I just did not have time to think and explain clearly. So I've just edited my question and hope that the question now is clear.
Mohibur Rashid 13-Jun-12 3:00am    
If you tell your purpose of this weird thing? if it is the requirements of your project then re-design the project.

Okay, after reading your updated question - forget what I wrote below, although some of the principles may come in handy...

It sounds a bit of a weird way to control a washing machine - having the user press buttons to trigger things manually. It's like using an old twin tub from the 70s. Pump water in, drop in soap powder, set the machine stirring. When it's finished try and get the clothes from the washer to the spinner without flooding the kitchen and so on.

Wouldn't it be better to model your washing machine's low level controls as a set of objects then link them together using various programs, the way an automatic washing machine does today [1]? For analogue control you might as well implement a hardware timer as well rather than relying on the computer - so instead of the computer saying "Okay, start...1, 2, 3, 4, 5... stop!" to the various devices it can just say: "Do your stuff for 5 seconds." This avoids the embarrassment of the computer crashing and the motor burning out as it wasn't meant to be on full spin for half an hour.

Anyway, sounds like the question could be more "here's a design for a control system, what's wrong with it?" more than one about windows programming.

[1] Oo, hang on, you are trying that. One cycle component per button, fired from the first one clicked rather than a triggered dial. The problems with doing it this way are:

- User clicks the start cycle button then for a laugh clicks the spin. The pumps going like crazy trying to force water in while the drum is rotating like mad.
- The computer's doing the timing. Windows is event driven and while on modern hardware I haven't seen this happen in 10 years it can delay timer messages. You'll have to use multimedia timers or some higher resolution ones.

Good luck!

============================================

PS: First reply...

Provided this is Win32 we're talking about and not some new fangled .Net malarkey and you mean form application in it's traditional sense then the way I'd go for this would be (using MFC and raw Win32)

1. Sort out where you're going to add code...

MFC: Derive a new class from CButton
Win32: Implement a window procedure that just forwards calls another window procedure

2. Sort out where you're going to store the object you want to forward messages to...

MFC: Implement a constructor that takes and saves a CWnd * as a parameter. This is the address of the CWnd object that you want to trigger a simulated button press on.
Win32: Write a function to add a property to a window called something like L"relay_to" which takes the HWND to the window you want to trigger a simulated button press on (using SetProp).

3. Sort out how you're going to handle the button click...

MFC: Override OnLButtonUp. The override sets a timer (using CWnd::SetTimer on itself) and add the function to the derived class's message map.
Win32: In your window procedure add a handler for WM_LBUTTONUP. In it call SetTimer.

4. Sort out how you're going to send a WM_LBUTTONUP to another button...

MFC: Override OnTimer. The override kills the timer (CWnd::KillTimer) and sends a WM_LBUTTONUP message to the window supplied to the constructor (CWnd::SendMessage). Add the function to the derived class's message map.
Win32: In your window procedure add a handler for WM_TIMER. In it do a KillTimer on the the window and send a WM_LBUTTONUP message to the HWND stored as a property (using SendMessage and GetProp).

5. Wire the whole unholy mess together starting with the buttons...

MFC: In your dialogue box's constructor make sure that button 1 has a pointer to button 2 which has a pointer to button 3 ad nauseum.
Win32: In WM_INITDIALOG of your dialogue box use the function you wrote in 2 to attach the window handle of button 2 to button 1 and so on.

6. ... then subclass the windows...

MFC: Use DDX_Control in your dialogues UpdateData to route windows messages through the MFC message map for your buttons. One call per button.
Win32: Use SubclassWindow to set the window procedure for the buttons to be the one you wrote earlier

7. Stand back, pull the chain and hope it all works.

There's going to be some bits I missed out of that lot (like where do you put the window procedure pointer you get when you subclass in win32) but it should give you an idea of what you're trying to do. And what a balls ache it is.

Interestingly the solution to this is about as complicated using MFC as it is using raw win32 - which just goes to show that MFC is possibly not as high level as most people would like it to be!

The other interesting bits here are all the ways you can simplify this lot and make it vaguely reusable (introduce an action interface in MFC and Win32 so you can dynamically change window's behaviour, add a jump table in Win32 to save needing big switch statements) but that's a whole 'nother topic.

Still want to do it? :-) If you do you'll come out of it knowing more about windows messaging than man was meant to know.
 
Share this answer
 
v2
Comments
Aescleal 13-Jun-12 22:48pm    
Hi Mr. Univoter, any chance you can tell me why you voted me down? This is so I can either/or:

- improve my answer and perhaps learn how to express myself better next time
- learn something
- disagree with you and say why and let other people make up their mind

I don't do tit for tat univoting so don't let that stand in your way!

Ash
Lets say your first button is the inlet water valve, the second starts the engine, the third opens the outlet valve, and the fourth runs a particular seqence.

Your code should contain control functions such as:

C++
ControlInletValve(BOOL on_or_off);
ControlOutletValve(BOOL on_or_off);
ControlEngine((BOOL on_or_off);


In your button event handlers and timer handler, you will have the basic skeleton code like this (you understand this is not compilable code but rather the correct code structure for your problem):

C++
static int phase;
void CBlaBla::OnButtonClickedButton1()
{
	ControlInletValve(TRUE); // or you could make it a toggle
}
void CBlaBla::OnButtonClickedButton2()
{
	ControlEngine(TRUE); // or you could make it a toggle
}
void CBlaBla::OnButtonClickedButton3()
{
	ControlOutletValve(TRUE); // or you could make it a toggle
}
void CBlaBla::OnButtonClickedButton4()
{
	phase = 0; // this will activate your sequence under timer control
}
void CBlaBla::InitTimer()
{
       phase = LAST_PHASE;
       SetTimer(...); 
       // start self-restarting timer has no effect until "phase" is set to a 
       // value not equal to LAST_PHASE

}
void CBlaBla::OnTimer()
{
	switch (phase)
	{
		case 0:
			ControlOutletValve(TRUE);
			phase++;
			break;
		case 1:
			ControlInletValve(TRUE);
			phase++;
			break;
		// and so on depending on your washing machine algorithm

		case LAST_PHASE:
			// sequence not active, nothing to do
			break;
		
	}
	// call OnTimer of the base class here somewhere
}
 
Share this answer
 
You just can call in the function the event handlers for the next button
for example from OnButtonClickButton1 you can call OnButtonClickButton2 and so on and you can put one timer inside each function so it will be called after the desired time
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 13-Jun-12 2:42am    
What is "call OnButtonClickButton2"? You cannot "call" a button. What timer? How do you know what is the type of the event and the purpose of it? Do you know that you cannot fire an event from anywhere except the instance of a type where it is declared?

Giving answers on something you do not understand yourself, not even close, is not nice. Therefore, I just had to vote 1, sorry.
--SA
Argonia 13-Jun-12 3:10am    
You didnt understand what i wrote call from a function you call the handler for the next button . OnButtonClickButoon1 is a handler function its not a button
stib_markc 13-Jun-12 4:22am    
What you did is meaningless, although it works. Event handlers are there for a purpose, they are called by your application, when the specific event occurs. So, calling one event handler in another event handler? Weird!!
Aescleal 13-Jun-12 8:47am    
I've seen it happen in two places in MFC apps:

- to avoid calling CWnd::SendMessage
- derived class handlers calling base class handlers

Conceptually the first one may seem a bit bent but it's the same as sending a window a message - without the whole sending a window a message thing. The second one is essentially the same as subclassing a Win32 window, again without doing the window subclassing thing.
stib_markc 14-Jun-12 0:52am    
Yes, I know about the first case, but still, I generally use PostMessage or PostThreadMessage for sending messages, which is very comfortable.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900