views:

319

answers:

4

In Single Document Interface (SDI) or Multiple Document Interface (MDI) MFC application, I created an application wide timer in the View. The timer will tick as long as the application is running and trigger some periodic actions.

How can I do the same with Dialog Based MFC application?

  1. Should I create Thread's Timer (SetTimer with NULL HWND) and pass a callback function to it?
  2. Should I create worker threads? My experience with other projects was when I tried to display some feedback GUI from non-GUI/worker threads, I need to roll out my own "delegate"/command pattern and a "delegate invoker"/command invoker. The worker thread will send message (I think using message is safer than direct function call when dealing across thread-boundary, CMIIW) to the UI-thread. and the UI-thread will be the "delegate"/command invoker. Failing to do this and to make sure that the windows/dialogs have the correct parent will result in bizzare behaviors such as the Application suddenly disappears to the background; Window/Dialog that is shown behind the current window/dialog and causing the current window to be unresponsive/unclickable. Probably I was doing something wrong but there were so much problems when dealing with threads.

Are there best practices for this?

+1  A: 

A timer works as well in a dialog-based application as an SDI or MDI app. OTOH, timers are (mostly) a leftover from 16-bit Windows. If you want to do things periodically, a worker thread is usually a better way to do it (and yes, Windows Mobile supports multiple threads).

Edit: in a dialog-based application, the main dialog exists for (essentially) the entire life of the application. Unless you really need the timer during the milliseconds between application startup and dialog creation or dialog destruction and application exit, just attach it to the dialog. Otherwise, you can attach it to the main window -- which MFC creates and destroys, even though it's never displayed.

Jerry Coffin
I know that timer works in Dialog based, but where should I put it? if I put it in the Dialog, it will be killed when the dialog is Destroyed. Should I maintain 1 Dialog opened all the time as a niche for the timer?
afriza
A: 

If you use the MFC Wizard to create the Dialog based app, you probably have a hidden view window as well as a dialog window. The view window creates the dialog with DoModal(), which runs the dialog in the same thread, effectively suspending the view window.

While the dialog is open, the view window will not process any events. So, if the view window owns the timer, it will not process the timer events.

The simplest solution is to create the timer in the dialog and let the dialog handle the timer messages.

Michael J
I will create my timers in the dialog if I need it only for <em>that</em> particular dialog. but I need the timer to be application wide and ticks as long as the application runs.
afriza
I am not sure if there is a hidden View in Dialog-based application, but the Dialog is created during InitInstance() of a class derived from CWinApp. And inside this function, the Application's Main window is set to the Dialog (as opposed to a frame, in SDI/MDI application) so I have the impression that the Dialog is the only HWND I get from the MFC Wizard.
afriza
@afriza - You are correct, the MFC wizard defines the dialog as the main window and there is no hidden view created by it.
Ruddy
I misspoke (my memory is getting bad in my old age). The main class derived from CWinApp doesn't seem to have a Window (i.e. view). The rest was true, that the main thread creates the dialog view using DoModal(). I'll re-write the answer to make more sense.
Michael J
A: 

IMO, use the Timer if it solves the problem. As you've mentioned a Worker Thread interacting with the UI, in MFC, can be more trouble than its worth sometimes.

If the problem is simple enough for a timer to suffice, thats what i'd use (Remember KISS)

SetTimer does not have to be handed a window to work, it can call a callback method.

You can use that in your application - declare in your CWinApp (or anywhere really)

static void CALLBACK OnTimer(HWND, UINT, UINT, DWORD);

Then in the InitInstance call SetTimer(0, [eventid], [time period], OnTimer);

In OnTimer you can get back to the CWinApp instance via AfxGetApp() or theApp since there is only one.

Ruddy
i think [eventid] will be ignored since you are creating Thread's Timer instead of HWND timer.
afriza
A: 
Michael J
Create() returns straight away (putting the Dialog into a different thread). << it doesn't feel right. returning straight away doesn't mean it creates a new thread. It can just rely on the main message loop to pump the messages to the dialog. Btw, I'm currently rushing with the non-periodic part of my app. Hopefully I'll update this 'thread' when I get there. Thanks for following this 'thread'
afriza