81.2.8 Using Timer Callbacks

This section describes how an application might use the timer services. First, the application calls the timeGetDevCaps function to determine the minimum and maximum resolution supported by the timer services. Before setting up any timer events, the application uses timeBeginPeriod to establish the minimum timer resolution it will use, as shown in the following code fragment:

#define TARGET_RESOLUTION 1 // Try for 1-millisecond accuracy

TIMECAPS tc;

UINT wTimerRes;

if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)

{

// Error; application can't continue

}

wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);

timeBeginPeriod(wTimerRes);

To start the timer event, the application specifies the amount of time before the callback occurs, the required resolution, the address of the callback function, and user data to supply with the callback. The application might use a function like the following to start a one-time timer event:

UINT SetTimerCallback(NPSEQ npSeq, // Sequencer data

UINT msInterval) // Event interval

{

npSeq->wTimerID = timeSetEvent(

msInterval, // Delay

wTimerRes, // Resolution (global variable)

OneShotCallback, // Callback function

(DWORD)npSeq, // User data

TIME_ONESHOT ); // Event type (one-time)

if(! npSeq->wTimerID)

return ERR_TIMER;

else

return ERR_NOERROR;

}

The following callback function resides in a fixed code segment in a DLL. It is limited to calling those functions that are interrupt-callable. The TimerIntRoutine procedure it calls also resides in a fixed code segment.

void FAR PASCAL

OneShotTimer(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)

{

NPSEQ npSeq; // Pointer to sequencer data

npSeq = (NPSEQ)dwUser;

npSeq->wTimerID = 0; // Invalidate timer id, since no longer in use

TimerIntRoutine(npSeq); // Handle interrupt-time tasks

}

Before freeing the DLL that contains the callback function, the application cancels any outstanding timers. To cancel one timer event, it might call the following function:

void DestroyTimer(NPSEQ npSeq)

{

if(npSeq->wTimerID) // If timer event is pending

{

timeKillEvent(npSeq->wTimerID); // Cancel the event

npSeq->wTimerID = 0;

}

}

Finally, to cancel the minimum timer resolution it established, the application calls timeEndPeriod as follows:

timeEndPeriod(wTimerRes);