dcsimg
December 6, 2016
Hot Topics:

Using Timers in MFC Applications

  • July 30, 1998
  • By Jay Wheeler
  • Send Email »
  • More Articles »

Download Source Code and Example


Timer Events in MFC Applications

Event timers are always handy to have around and useful in nearly every project. When a timer is readily available, such as the Timer control in Visual Basic, you find all kinds of reasons to use one in an application. The lack of a timer object in MFC is, in my opinion, a serious oversight.

Luckily, Microsoft Windows NT/95 systems provide a number of timers for use by application programs. This tutorial provides information on how to install timers in your MFC application, and how to start, process and stop the timers.

In the final section of the tutorial, we develope a simple timer project which is capable of rough animation of an icon in the dialog window. This project is useful in any compute or I/O bound application, and illustrates the techniques involved with installing and using a system timer.

These steps were developed and tested on a WindowsNT 4.0 workstation and Windows95 using VisualC++ 4.2 with Microsoft Foundation Classes.

Installing a Timer

  1. In the header file of the dialog using the timer,

    1. Add a message number for each timer needed:

        #define IDT_TIMER_0 WM_USER + 200
        #define IDT_TIMER_1 IDT_TIMER_0 + 1

    2. Add the timer interrupt handler

        OnTimer (UINT TimerVal)

      to the Generated Message Map:

      1. locate the section under Implementation where the AFX_MSG message map is declared (usually begins with the line OnInitDialog());

      2. add a line just after the last line in the message map (just before the "//}}AFX_MSG"):

          afx_msg void OnTimer (UINT TimerVal);

        This should be the last entry in the message map.

  2. In the dialog implementation (.cpp) file,

    1. Locate the dialog class start

    2. Find the line starting "BEGIN_MESSAGE_MAP"

    3. After the last entry in the message map (before the line "//}}AFX_MSG_MAP"), add

        ON_WM_TIMER ( )

Starting the timer

To start the timer, you must issue a SetTimer command:

    t-number = SetTimer (t-message, t-interval, NULL)

where:

    t-message The message number assigned for processing the timer request.
    This is referred to as IDT_TIMER_0 in the installation instructions.
    t-interval The timer duration, in mSec.
    t-number The system timer number assigned to this event, or 0 if no timers available.

For Example:

    
    
    
        UINT  StartTimer (UINT TimerDuration)
    
        {
    
            UINT    TimerVal;
    
    
    
            TimerVal = SetTimer (IDT_TIMER_0, TimerDuration, NULL);
    
            if (TimerVal == 0)
    
            {
    
                    MessageBox ("Unable to obtain timer",
    
    		      "IDT_TIMER_0",
    
    		      MB_OK|MB_SYSTEMMODAL);
    
            }
    
    
    
            return TimerVal;
    
    
    
        }// end StartTimer
    
    
    
      
    To start the timer, pass it the value of the timer duration, in milliseconds (mSec). If the returned value is non-zero, the timer has been initialized.

    Note: You must save the assigned timer value in order to stop the timer, and also to know which timer to process in a multi-timer application.

Stopping the Timer

To stop the timer, issue the KillTimer command:

    t-result = KillTimer (t-number);

where:

    t-number The system timer number from either the SetTimer or OnTimer methods.
    t-result The boolean result of the operation, TRUE indicating success.

For Example:

    
          BOOL StopTimer (UINT TimerVal)
    
          {
    
    
    
              //
    
              //    Stop the timer
    
              //
    
              if (!KillTimer (TimerVal))
    
              {
    
                  return FALSE;
    
              }
    
    
    
              //
    
              //    Place clean-up code following this point.
    
              //
    
    
    
    
    
              return TRUE;
    
    
    
          } // end StopTimer
    
    
    
      

Processing Timer Events - The OnTimer Method

    After the timer has been started, the OnTimer event will be called each time the timer counts down to zero (reaches terminal count) from the requested value. This event is asynchronous to the timer - a message is placed in the message queue of the calling process and the timer is automatically restarted.

    The timer can be stopped (refer to Stopping the Timer) upon entry to the OnTimer routine, or left to run if the event will not occur again before processing the OnTimer routine has completed.

    The OnTimer method will be executed each time the timer reaches terminal count. The code in this method should be short and concise; it should be code which must be executed each time the timer reaches its terminal count, such as changing the view of an animated drawing or icon, or setting a flag to process latter, or starting a thread to handle the more complex functions.

    Example:

    
    
    
        void OnTimer (UINT TimerVal)
    
        {
    
            //////////////////////////////////////////////
    
            //
    
            //    Stop the timer
    
            //
    
            //////////////////////////////////////////////
    
    
    
            if (!KillTimer (TimerVal))
    
            {
    
    
    
            }
    
    
    
            //////////////////////////////////////////////
    
            //
    
            //    Process the event
    
            //
    
            //////////////////////////////////////////////
    
    
    
    
    
            //////////////////////////////////////////////
    
            //
    
            //    Restart the timer, if needed, before exiting
    
            //
    
            //////////////////////////////////////////////
    
    
    
    
    
        }
    
      

Multiple Timers

    The OnTimer method is passed an unsigned integer (UINT) to identify the timer which is interrupting. The value of this timer may be used to stop the associated timer. It can also be used in a multiple timer environment to determine what type of processing must occur.

Example:

    Assumptions:
    1. The timers are started using the example in the section on Installing a Timer.
    2. The timer values are placed sequentially into the array ATimer, as follows:

              ATimer [0] = StartTimer (200);  // a 200 mSec timer
              ATimer [1] = StartTimer (500);  // a 500 mSec timer
              

    
      void OnTimer (UINT TimerVal)
    
      {
    
          int      Index;
    
    
    
          /////////////////////////////////////////////////////////////////////////////
    
          //
    
          //      Check timer number 0
    
          //
    
          ////////////////////////////////////////////////////////////////////////////
    
    
    
          if (TimerVal == ATimer[0])
    
          {
    
              //
    
              //      Process timer 0 message!
    
              //
    
    
    
              return;
    
          }
    
    
    
          ////////////////////////////////////////////////////////////////////////////
    
          //
    
          //      check timer number 1
    
          //
    
          ////////////////////////////////////////////////////////////////////////////
    
    
    
          if (TimerVal == ATimer[1])
    
          {
    
              //
    
              //      Process timer 1 message!
    
              //
    
    
    
              return;
    
          }
    
    
    
          ////////////////////////////////////////////////////////////////////////////
    
          //
    
          //      Not timer number 0 or 1
    
          //
    
          ////////////////////////////////////////////////////////////////////////////
    
    
    
          if (!KillTimer (TimerVal))
    
          {
    
    
    
          }
    
    
    
          CString Message;
    
          Message.format("Unkown timer interrupt: %u", TimerVal);
    
          MessageBox (Message,"OnTimer",MB_OK|MB_SYSTEMMODAL);
    
          
    
      } // end OnTimer
    
    
    
    

IconMover - Timer Application

IconMover is a sample application embodying a timer which signals the program at regular intervals. When the program is signaled, the icon being displayed is changed, leading to a crude animation of the icon.


Program Flow

We start by adding a line to the dialogs' OnInitDialog method to set the value of IconTimer to NULL, indicating that the timer has not yet been assigned.

The dialog window is initialized containing a default icon and 3 buttons: Start, Stop and Exit, corresponding to the OnStart, OnStop and OnOK methods, respectively. The Start button starts the timer, if one is not already running, the Stop button stops the timer, and the Exit button stops the running timer, if one is running, and exits the dialog.

When the Start button has been activated, a timer is started with the default timer interval, 500 mSec., causing a timer message to be generated every 1/2 second.

The OnTimer method is invoked to process each timer generated message. The IconState modulus 4, a number between 0 and 3, inclusive, is used as an index in a select statement to choose the icon to display next. Once the icon is selected (IconId), IconState is incremented for the next timer message. Finally, the SetCurrentIcon method is passed the value in IconId to display the indicated icon in the dialog.

The timer will run until the Stop button is pressed. After stopping the timer, the OnStop method passes the default icon setting, 0, to the SetCurrentIcon method.

The Exit button is used to stop the timer, if it is running, and exit the dialog when you are through with the application.


Methods and Variables

    IconMover is a sample application embodying a timer which signals the program at regular intervals. When the program is signaled, the icon being displayed is changed, leading to a crude animation of the icon.

    The program implements the methods discussed elsewhere in this tutorial:

    As well as several new methods:

    And two public variables:


Methods

UINT StartTimer (UINT TimerDuration)

  • Associates a timer event with the current process and sets its duration, in mSec.
  • Returns the system timer assigned to process the event, or 0 if an error occurs.


BOOL StopTimer (UINT TimerVal)

  • Stops system timer event TimerVal.
  • Returns TRUE if successful.


void OnTimer (UINT TimerVal)

  • Processes the system timer TimerVal.
  • Does not stop the timer.
  • Displays the icon associated with the value in IconState modulus 4 (a number between 0 and 3, inclusive).


void OnOK ( )

  • Processes the EXIT button
  • Stops the timer, if one is active, and exits the dialog


void OnStart ( )

  • Processes the Start button
  • Starts a system timer event and stores the value of the timer in IconTimer


void OnStop ( )

  • Processes the Stop button
  • Stops the system timer event IconTimer


void SetCurrentIcon (int IconId)

  • Sets the current icon being displayed.


Variables

    IconState Contains the value of the next icon to display on the dialog windows.
    IconTimer Contains the value of the system assigned timer. Invalid when NULL.

Last updated: 30 July 1998






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel