Q130866: INFO: Using a TimerProc Function in MFC Application
Article: Q130866
Product(s): Microsoft C Compiler
Version(s): 1.0,1.5,1.51,1.52,2.0,2.1,4.0
Operating System(s):
Keyword(s): kbfile kbSample kbMFC kbVC100 kbVC150 kbVC200 kbGrpDSMFCATL
Last Modified: 21-DEC-2001
-------------------------------------------------------------------------------
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), used with:
- Microsoft Visual C++ for Windows, 16-bit edition, versions 1.0, 1.5, 1.51, 1.52
- Microsoft Visual C++, 32-bit Editions, versions 1.0, 2.0, 2.1, 4.0
-------------------------------------------------------------------------------
SUMMARY
=======
The TMRPROC sample is designed to demonstrate how to use the SetTimer() API in
an MFC Application in such a way that the TimerProc() callback function (a
member of a C++ class) is used instead of handling WM_TIMER messages. There are
two makefiles included:
- TMRPROC.MAK, generated by Visual C++ version 1.5.
- TMRPRC32.MAK, generated by Visual C++ version 2.0.
MORE INFORMATION
================
The following file is available for download from the Microsoft Download
Center:
Tmrproc.exe
(http://download.microsoft.com/download/vc15/Sample/3/WIN98/EN-US/tmrproc.exe)
For additional information about how to download Microsoft Support files, click
the article number below to view the article in the Microsoft Knowledge Base:
Q119591 How to Obtain Microsoft Support Files from Online Services
Microsoft used the most current virus detection software available on the date of
posting to scan this file for viruses. Once posted, the file is housed on secure
servers that prevent any unauthorized changes to the file.
NOTE: When extracting files from TMRPROC.EXE, be sure to use the -d option to
create subdirectories.
The challenge of using callback functions as C++ class members can be approached
in several different ways, depending on the circumstances surrounding the
callback. In "Calling All Members:..." (see References below), four different
approaches are mentioned. They are:
- Not accessing any class members from within the static callback.
- Storing the "this" pointer to the object in a static member.
- Passing the "this" pointer to the callback function via a parameter supplied
by APIs that use callbacks.
- Storing a list of "this" pointers mapped to the list of objects servicing the
callback in a static structure.
The TMRPROC sample application illustrates the second and fourth cases. These are
the most likely scenarios MFC Doc/View/UI type applications encounter. Not
accessing any members from a callback is quite limiting, and passing the "this"
pointer in a callback-supplied parameter is dependent on the API. For these
reasons, the sample does not address the first and third cases.
TMRPROC.CPP and .H
------------------
Storing the "this" pointer to the object in a static member is demonstrated in
the CWinApp-derived class, CTmrprocApp.
There is no window associated with this class, so the output used to indicate the
timer event is done via OutputDebugString(). The pThis variable is a static
member variable that is initialized in the constructor to contain the "this"
pointer for the class. The TimerProc() callback is simply a static member
function of type "void CALLBACK EXPORT." It is static, so no "this" pointer is
passed in. For this reason, the pThis member variable is used to store the
CTmrprocApp's "this" pointer. Whenever TimerProc() gets called, the current
instance of CTmrprocApp can be referenced through the CTmrprocApp::pThis
member.
This is the simplest case. There are three functions added to the CTmrprocApp
class to accomplish this objective - TimerProc(), CTmrprocApp::OnAppsettimer(),
and CTmrprocApp::OnAppkilltimer(). The later two are the menu handlers that
allow the user to start and stop the timer.
TMRPRVW.CPP and .H
------------------
Storing a list of "this" pointers mapped to the list of objects servicing the
callback in a static structure is implemented in the view class, CTmrprocView.
In this case, a little more work is required, but not much. Because a timer needs
to be set for each instance of the view class, a scheme must be implemented to
associate each timer ID with a corresponding view object. The view object is
identified by its "this" pointer and the timer by its timer ID (passed back from
SetTimer()). The view class associates these and stores them in a CMapWordToPtr
static member variable. This way, when each view's TimerProc() is called, it can
first look up its "this" pointer in the pointer/ID map, and then update its own
members.
There are several functions needed to start, stop, and reset the count on the
timer. The count is just a running count of the number of times TimerProc() has
been called for the current view. The following are the start, stop, and reset
functions:
CTmrprocView::OnTimerStart() - Start timer in current view.
CTmrprocView::OnTimerStop() - Stop timer in current view.
CTmrprocView::OnTimerReset() - Reset count for current view.
The following are some "all" type functions that can be used to start, stop, and
reset the timer for each view:
CTmrprocView::OnTimerAllStart() - Start timers for all views.
CTmrprocView::OnTimerAllStop() - Stop timers for all views.
CTmrprocView::OnTimerAllReset() - Reset timer count for all views.
REFERENCES
==========
MSDN Technical Articles, C/C++ Articles, "Calling All Members: Member Functions
As Callbacks," by Dale Rogerson.
Additional query words: kbfile tmrproc settimer
======================================================================
Keywords : kbfile kbSample kbMFC kbVC100 kbVC150 kbVC200 kbGrpDSMFCATL
Technology : kbAudDeveloper kbMFC
Version : :1.0,1.5,1.51,1.52,2.0,2.1,4.0
Issue type : kbhowto
=============================================================================
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.