Click here to Skip to main content
12,897,444 members (48,770 online)
Click here to Skip to main content
Add your own
alternative version


49 bookmarked
Posted 9 Nov 2000

A thread-safe timed message box

, 12 Feb 2001
Rate this:
Please Sign up or sign in to vote.
The system Message Box that is closed atuomatically after some time

What is the code for

This is for using the systems MessageBox (no extra dialog creation needed). After a time with no user-response the dialog is automatically closed. An optional text showing the time left to interact is provided. It's also a replacement for MSDN Q181934 (doesn't work)


Before calling MessageBox, a timer is installed. In the timer's callback-procedure the message-text from the box is replaced (optional).

When the box should be closed, a WM_COMMAND is posted to the MessageBox Window.


I decided to collect all the information corresponding to the MessageBox (title, Message, Flags ...) in a class. Then there is the problem that only a static timer-callback-procedure can be installed with the SetTimer()-function: one can not access the class-members (as it is static).

To solve this problem, I inserted a Map to store the classes corresponding to a timer-id:


class CDlgTimedMessageBox
    // ...

    UINT         ShowMessageBox(BOOL *pbStoppedByUser=NULL);
    // ...

    static void  CALLBACK GlobalTimerProc(HWND hwnd, UINT uiMsg, 
                                          UINT idEvent, DWORD dwTime);
    void         LocalTimerProc(void);
    // ...

    static       CMapPtrToPtr        m_mapTimerIdToClassMe;

    // to call the messagebox within one line !

    static UINT  TimedMessageBox(...);

    UINT         m_idTimer;


UINT CDlgTimedMessageBox::ShowMessageBox(BOOL *pbStoppedByUser)
    // ...
    m_idTimer = ::SetTimer(NULL, 0, 1000, 
                    (TIMERPROC) CDlgTimedMessageBox::GlobalTimerProc);
    // ...
    // ...

void CALLBACK CDlgTimedMessageBox::GlobalTimerProc(HWND hwnd, 
                               UINT uiMsg, UINT idEvent, DWORD dwTime)
    CDlgTimedMessageBox    *pMe = NULL;
    // Find the corresponding class by the timer-id
                                                       (void *&) pMe);
    if( pMe!=NULL )

void CDlgTimedMessageBox::LocalTimerProc(void)
    // find the Message-Box-window

    // Calculate time since start
    if( too long running )
        // Stop MessageBox
        // replace text of MessageBox    

Finding the MessageBox

hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while( (hWnd!=NULL) && (m_hMsgBox==NULL) )
    pWnd = CWnd::FromHandle(hWnd);

    if( AfxIsDescendant(m_hParent, hWnd) && ::IsWindowVisible(hWnd) && 
        (m_Title.CompareNoCase(title)==0) )
        m_hMsgBox = hWnd;
    hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);


Put it in one function

There is one function you can use to call the messagebox without creating a class-instance: CDlgTimedMessageBox::TimedMessageBox() does the rest for you!

UINT CDlgTimedMessageBox::TimedMessageBox(UINT flags, LPCTSTR ptszMessage, 
                          LPCTSTR ptszTitle, 
                          DWORD dwTimeout, UINT dDefaultReturn,
                          LPCTSTR ptszMessageTimer, HWND hwndParent, 
                          BOOL *pbStoppedByUser)
    CDlgTimedMessageBox    msgBox(flags, ptszMessage, ptszTitle, 
                                  dwTimeout, dDefaultReturn, 
                                  ptszMessageTimer, hwndParent);

    return msgBox.ShowMessageBox(pbStoppedByUser);

You can pass a BOOL * to get the info, if the user has pressed a button.



The map-access is enclosed by a CCriticalSection.


BOOL	stoppedByUser;
UINT	erg;

erg  = CDlgTimedMessageBox::TimedMessageBox(MB_YESNO|MB_ICONHAND, 
		"Please press a button", 
		5000, IDYES, 
		"\nin the next %lu sec !", 
		NULL, &stoppedByUser);


5.11.2000     posted to Code Project
14.11.2000   bugfixes for NT4
05.02.2001   bug reported when created with MBYES: defbutton then is IDCANCEL
05.02.2001   global function went to class-scope


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Markus Loibl
Germany Germany
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralMy vote of 1 Pin
Sudhindra Sathya19-Nov-10 1:26
memberSudhindra Sathya19-Nov-10 1:26 
QuestionHow to show other icons in the messagebox.. Pin
Jigar Mehta23-Nov-04 20:48
memberJigar Mehta23-Nov-04 20:48 
GeneralCompiling errors Pin
shalala7-Oct-03 21:11
membershalala7-Oct-03 21:11 
GeneralRe: Compiling errors Pin
cristitomi21-Mar-07 6:35
membercristitomi21-Mar-07 6:35 
Generaltimed out MessageBox Pin
Xeena2-Oct-02 6:53
memberXeena2-Oct-02 6:53 
Generalbottons Pin
Anonymous17-Jun-02 5:29
memberAnonymous17-Jun-02 5:29 
GeneralIf you like this then.... Pin
Anonymous12-Mar-02 7:23
memberAnonymous12-Mar-02 7:23 
General"Fire and Forget" addition Pin
M.Lansdaal12-Feb-02 14:53
memberM.Lansdaal12-Feb-02 14:53 
GeneralTimer Pin
Joachim12-Nov-01 2:59
memberJoachim12-Nov-01 2:59 
GeneralRe: Timer Pin
mloibl12-Nov-01 21:10
membermloibl12-Nov-01 21:10 
GeneralRe: Timer Pin
Alfred Rohr22-Nov-01 5:04
memberAlfred Rohr22-Nov-01 5:04 
GeneralMemory Leaks Pin
eljkmw22-Aug-01 17:53
membereljkmw22-Aug-01 17:53 
GeneralRe: Memory Leaks Pin
Alan Adams28-Oct-04 11:04
memberAlan Adams28-Oct-04 11:04 
QuestionHOW? Pin
TGWG6-Jul-01 7:00
memberTGWG6-Jul-01 7:00 
AnswerRe: HOW? Pin
MLoibl17-Jul-01 20:50
memberMLoibl17-Jul-01 20:50 
GeneralMissing include Pin
Anonymous6-Jul-01 4:52
memberAnonymous6-Jul-01 4:52 
GeneralAlways on top Pin
newbie22-Jun-01 3:20
membernewbie22-Jun-01 3:20 
GeneralRe: Always on top Pin
MLoibl17-Jul-01 20:56
memberMLoibl17-Jul-01 20:56 
QuestionAfxIsDescendant() ? Pin
Peter Sjöström28-Mar-01 5:58
memberPeter Sjöström28-Mar-01 5:58 
AnswerRe: AfxIsDescendant() ? Pin
MLoibl28-Mar-01 20:10
memberMLoibl28-Mar-01 20:10 
AnswerRe: AfxIsDescendant() ? Pin
Wes Jones17-Jul-01 13:19
memberWes Jones17-Jul-01 13:19 
GeneralIcky global functions! Pin
Paul Wolfensberger17-Nov-00 4:15
memberPaul Wolfensberger17-Nov-00 4:15 
GeneralRe: Icky global functions! Pin
MLoibl5-Feb-01 3:51
memberMLoibl5-Feb-01 3:51 
GeneralRe: Icky global functions! Pin
MLoibl5-Feb-01 9:13
memberMLoibl5-Feb-01 9:13 
>>destroyed or a method is called:
In the code, when the last timer is finished, then it happens:
// done with the box
m_bStoppedByTimer = TRUE;
::PostMessage(m_hMsgBox, WM_COMMAND, (WPARAM) m_DefaultReturn, (LPARAM) m_hDefaultButton);

I think you can do this also from a function. But first you have to check if the handles are ok: Do this with GetWindowHandles().
The members are protected, so derive your own class and insert a function doing this.

GeneralCrashes immediately on NT4 Pin
Anonymous13-Nov-00 1:40
memberAnonymous13-Nov-00 1:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170424.1 | Last Updated 13 Feb 2001
Article Copyright 2000 by Markus Loibl
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid