Click here to Skip to main content
Click here to Skip to main content

Delay MessageBox with auto-close option

By , , 13 Aug 2002
 

Overview

A delay message box will not allow the user to dismiss it until the delay interval has run out. It does this by disabling the OK button on the message box till the specified time interval expires. One example of a situation where this might be useful is a shareware program that has expired its trial period. Say you want to show a message box to the user and you want to make sure it stays there for at least 10 seconds. Anyway Nish started writing this class with a totally different idea. He wanted to center his message box on it's parent window. That's when he found out that, message boxes do this by default. In his case they were not doing so because he had made them owned by the desktop. Anyway Nish ended up writing a delay message box that also has an auto-close option. If the auto-close option is set to true, then the message box will close on it's own once the delay period has terminated. This was how the CDelayMessageBox class was born.

What turned out as a simple attempt to center a message box has ended up in some rather complicated code with WH_CBT hooks, invisible windows, a CWnd* to HWND map and a sub-classed message box window that overrides DefWindowProc of all things to override. It sure seems like a lot of work for such a simple sounding task. But it is the write-once-use-multiple-times kind of class and thus Nish hopes his methods are justified.

That's when Shog got interested in the class. Shog is the type of guy who hates any kind of code obfuscation and he's always trying to figure out easier ways of doing things. Anyhow he modified Nish's class so that it was more MFC-ied. We decided to call it CDelayMessageBox2 because while it didn't extend the class in anyway, the implementation was thoroughly revamped. Both the classes are presented in this article as well as in the demo project and the class source. You'll find the following files to be of interest to you.

  • DelayMessageBox.cpp - This was the original implementation file and you can take a look at this one if you are interested in seeing elementary examples of the use of WH_CBT hooks and window sub-classing.
  • DelayMessageBox.h - The header file for the original class
  • DelayMessageBox2.cpp  - This is the new implementation file and you can see some high quality MFC type sub classing here.
  • DelayMessageBox2.h - The header file for the revised class.

Usage

The CDelayMessageBox and CDelayMessageBox2 classes have only one public method in addition to the constructor. There is no parameter-less constructor. By the way, in the rest of the article when you see CDelayMessageBox, it represents both the classes unless specifically mentioned otherwise.

Constructor

Constructs a CDelayMessageBox object.

CDelayMessageBox(CWnd* pParent);

pParent - This will be the parent window of the eventual message box that will be displayed. You should not set this to NULL. The parent window must be a valid CWnd that holds a valid HWND.

Note - In CDelayMessageBox2 you can set pParent to NULL.

MessageBox method

Displays the message box.

int MessageBox(<br>
    LPCTSTR lpszText, <br>
    int count, <br>
    bool bclose = false, <br>
    MBIcon icon = MBICONNONE );

lpszText - Points to a null-terminated string containing the message to be displayed. You may use a CString here.

count - This is the delay in seconds. You can use any delay from 0 - the maximum size of an int, but you are advised to keep it under 60 for all practical purposes.

bclose - If this is set to true, the message box will close on its own after the delay period, otherwise the OK button is enabled so that the user can dismiss the message box manually.

icon - This is an MBIcon enumeration which can take one of the following values.

  • CDelayMessageBox::MBIcon::MBICONNONE
  • CDelayMessageBox::MBIcon::MBICONSTOP
  • CDelayMessageBox::MBIcon::MBICONQUESTION
  • CDelayMessageBox::MBIcon::MBICONEXCLAMATION
  • CDelayMessageBox::MBIcon::MBICONINFORMATION

Sample Code

/*
    You may use either of the classes. 
    In behaviour they are identical.
    It's in the implementation that they differ.
*/

//CDelayMessageBox mbox(this); 
CDelayMessageBox2 mbox(this);

mbox.MessageBox(m_text,
    m_delay,
    m_close,(CDelayMessageBox2::MBIcon)mbicon);

Technical details

CDelayMessageBox

CDelayMessageBox is derived from CWnd and it creates a CWnd object in it's constructor. The window that is created has a unique title text and is hidden. The unique text is a GUID. The class has a static CMapPtrToPtr member using which we maintain an HWND to CWnd* map. This is so that any number of threads may simultaneously use the CDelayMessageBox  class. In other words it's thread-safe.

When the MessageBox method is called we use SetWindowsHookEx to set a WH_CBT hook. We then start a timer at a 1-second interval and use CWnd::MessageBox to show our message box. In the hook proc we enumerate all the child windows of the message box window using EnumChildWindows. In the callback for EnumChildWindows, we disable the OK button. We also subclass the message box window to a custom CWnd derived class. And we also unhook the WH_CBT hook. In the timer proc, we keep decreasing the count and also keep changing the title text of the message box to reflect the remaining time in seconds. When the count reaches zero we enable the OK button or if the auto-close option is true we dismiss the message box using a WM_CLOSE message.

The custom CWnd derived class into which we subclass the message box was added as a bug fix to a problem reported by Andreas Saurwein where he found that the message box can be closed using the space bar. This is because a WM_COMMAND message is sent to the message box window with a BN_CLICKED notification when the space bar is pressed. This has been handled by overriding DefWindowProc and filtering out this message.

CDelayMessageBox2

Now we don't have a hidden CWnd parent for the message box. We create the CWnd object using AfxHookWindowCreate when the call to MessageBox(...) is made. MFC will call SetWindowsHookEx for you. Now the message box has been sub-classed by our CWnd derived class. We override OnSubclassedInit and we disable the OK button and start our timer. We also override OnCreate where we call AfxUnhookWindowCreate as we don't have any further need for the hook.

The timer proc is similar to the timer proc in the original class and we keep changing the title text to reflect the remaining time in seconds. Once the delay interval has elapsed we post a WM_CLOSE to the message box. And also enable the OK button.

Class source listings

Both the old and new classes are listed here. They both use contrastingly different techniques to solve the delay message box problem. We thought you might want to compare them and that might also help to understand the inner workings better. Now the class has out-valued itself in the sense, it is now a class with a lot more academic value than utility. Both the implementations reveal a lot about the inner workings of Windows.

Header files

Old one

#pragma once

// COkayWnd

class COkayWnd : public CWnd
{
    DECLARE_DYNAMIC(COkayWnd)

public:
    COkayWnd();
    virtual ~COkayWnd();

protected:
    DECLARE_MESSAGE_MAP()
public:     
protected:
    virtual LRESULT DefWindowProc(UINT message, 
        WPARAM wParam, LPARAM lParam);
};


class CDelayMessageBox : public CWnd
{
    DECLARE_DYNAMIC(CDelayMessageBox)

public:
    CDelayMessageBox(CWnd* pParent);
    virtual ~CDelayMessageBox();    

    enum MBIcon
    {
        MBICONNONE = 0,
        MBICONSTOP = MB_ICONSTOP,
        MBICONQUESTION = MB_ICONQUESTION,
        MBICONEXCLAMATION = MB_ICONEXCLAMATION,
        MBICONINFORMATION = MB_ICONINFORMATION
    };

    int MessageBox(LPCTSTR lpszText, int count, 
        bool bclose = false, MBIcon icon = MBICONNONE );    

protected:
    HHOOK m_hHook;
    HWND m_hMsgBoxWnd;
    HWND m_hOK;
    int m_count;
    bool m_autoclose;   
    COkayWnd m_OkayWnd;

    static LRESULT CALLBACK CBTProc(int nCode,
        WPARAM wParam, LPARAM lParam);
    static BOOL CALLBACK EnumChildProc( HWND hwnd, 
        LPARAM lParam );
    static CMapPtrToPtr m_map;

    CString FormTitle(int num);

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnTimer(UINT nIDEvent);
};

New one

#pragma once

class CDelayMessageBox2 : public CWnd
{
    DECLARE_DYNAMIC(CDelayMessageBox2)

public:
    CDelayMessageBox2(CWnd* pParent);

    enum MBIcon
    {
        MBICONNONE = 0,
        MBICONSTOP = MB_ICONSTOP,
        MBICONQUESTION = MB_ICONQUESTION,
        MBICONEXCLAMATION = MB_ICONEXCLAMATION,
        MBICONINFORMATION = MB_ICONINFORMATION
    };

    int MessageBox(LPCTSTR lpszText, int count, 
        bool bclose = false, MBIcon icon = MBICONNONE ); 

protected:
    int m_count;
    bool m_autoclose; 
    HWND m_hWndParent;

    CString FormTitle(int num);

    virtual LRESULT DefWindowProc(UINT message, 
        WPARAM wParam, LPARAM lParam);
    afx_msg LRESULT OnSubclassedInit(WPARAM wParam, 
        LPARAM lParam);
    afx_msg int OnCreate(
        LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnTimer(UINT nIDEvent);

    DECLARE_MESSAGE_MAP()
};

C++ implementation files

Old one

#include "stdafx.h"
#include "DelayMessageBox.h"


CMapPtrToPtr CDelayMessageBox::m_map;

IMPLEMENT_DYNAMIC(CDelayMessageBox, CWnd)
CDelayMessageBox::CDelayMessageBox(CWnd* pParent)
{
    m_hHook = NULL;
    m_hMsgBoxWnd = NULL;
    m_hOK = NULL;
    m_autoclose = NULL;
    m_OkayWnd.m_hWnd = NULL;

    Create(NULL,
        "{8B32A21C-C853-4785-BE20-A4E575EE578A}",
        WS_OVERLAPPED, CRect(0,0,0,0),
        pParent,1000); 
    m_map[m_hWnd] = this; 
}

CDelayMessageBox::~CDelayMessageBox()
{ 
    m_map.RemoveKey(m_hWnd);
    DestroyWindow();
}


BEGIN_MESSAGE_MAP(CDelayMessageBox, CWnd)
    ON_WM_TIMER()
END_MESSAGE_MAP()

BOOL CALLBACK CDelayMessageBox::EnumChildProc( 
    HWND hwnd, LPARAM lParam )
{
    CDelayMessageBox *pthis = 
        static_cast<CDelayMessageBox*>((LPVOID)lParam);
    char str[256]; 
    ::GetWindowText(hwnd,str,255);
    if(strcmp(str,"OK") == 0)
    {
        pthis->m_hOK = hwnd;
        if(pthis->m_count>0)
        {
            ::EnableWindow(pthis->m_hOK,FALSE); 
        }
        return FALSE;
    }
    return TRUE;
}

LRESULT CALLBACK CDelayMessageBox::CBTProc(
    int nCode,WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_ACTIVATE )
    { 
        void* p; 
        m_map.Lookup(::FindWindowEx(::GetParent(
            (HWND)wParam),NULL,NULL,
            "{8B32A21C-C853-4785-BE20-A4E575EE578A}"),p); 

        CDelayMessageBox* pthis = (CDelayMessageBox*)p; 
        pthis->m_hMsgBoxWnd = (HWND)wParam; 
        EnumChildWindows(pthis->m_hMsgBoxWnd,
            EnumChildProc,(LPARAM)pthis); 
        UnhookWindowsHookEx(pthis->m_hHook);
        if(pthis->m_count>0)
            pthis->m_OkayWnd.SubclassWindow(
                pthis->m_hMsgBoxWnd);
        pthis->m_hHook = NULL;

    }
    return FALSE;
}
void CDelayMessageBox::OnTimer(UINT nIDEvent)
{
    if(nIDEvent == 100 && m_hMsgBoxWnd )
    { 
        if(m_count>0)
            m_OkayWnd.SetWindowText(FormTitle(--m_count));

        if(m_count == 0)
        {
            if(m_OkayWnd.m_hWnd)
            {
                m_OkayWnd.UnsubclassWindow();
                m_OkayWnd.m_hWnd = NULL;
            }
            ::EnableWindow(m_hOK,TRUE);
            KillTimer(100);
            m_hOK = NULL;
            if(m_autoclose)
                ::PostMessage(m_hMsgBoxWnd,WM_CLOSE,0,0);
            m_hMsgBoxWnd = NULL; 
        }
    } 

    CWnd::OnTimer(nIDEvent);
}

int CDelayMessageBox::MessageBox(LPCTSTR lpszText, 
                int count, bool bclose,MBIcon icon)
{ 
    m_autoclose = bclose;
    m_hHook = SetWindowsHookEx(WH_CBT,CBTProc,
        AfxGetApp()->m_hInstance,
        AfxGetApp()->m_nThreadID);
    m_count = count;
    SetTimer(100,1000,NULL); 
    CWnd::MessageBox(lpszText,FormTitle(m_count),icon);
    return IDOK;
}


CString CDelayMessageBox::FormTitle(int num)
{
    CString s;
    s.Format("%d seconds remaining",num);
    return s;
}


// COkayWnd

IMPLEMENT_DYNAMIC(COkayWnd, CWnd)
COkayWnd::COkayWnd()
{
}

COkayWnd::~COkayWnd()
{
}


BEGIN_MESSAGE_MAP(COkayWnd, CWnd)
END_MESSAGE_MAP()



// COkayWnd message handlers

LRESULT COkayWnd::DefWindowProc(UINT message, 
                WPARAM wParam, LPARAM lParam)
{   
    if(message == WM_COMMAND)
    {
        if(HIWORD(wParam) == BN_CLICKED )
            return 0;
    }

    return CWnd::DefWindowProc(message, wParam, lParam);
}

New one

#include "stdafx.h"
#include "DelayMessageBox2.h"
#include <afxpriv.h>

IMPLEMENT_DYNAMIC(CDelayMessageBox2, CWnd)
CDelayMessageBox2::CDelayMessageBox2(CWnd* pParent)
{
    m_hWndParent = pParent->GetSafeHwnd(); // can be NULL
    m_autoclose = NULL;
    m_count = 0;
}

BEGIN_MESSAGE_MAP(CDelayMessageBox2, CWnd)
    ON_WM_TIMER()
    ON_WM_CREATE()
    ON_MESSAGE(WM_INITDIALOG, OnSubclassedInit)
END_MESSAGE_MAP()


// Purpose: Unhook window creation
int CDelayMessageBox2::OnCreate(
        LPCREATESTRUCT lpCreateStruct)
{
    AfxUnhookWindowCreate();
    return CWnd::OnCreate(lpCreateStruct);
}

// Purpose: Disable OK button, start timer
LRESULT CDelayMessageBox2::OnSubclassedInit(
    WPARAM wParam, LPARAM lParam)
{
    LRESULT lRet = Default();
    CWnd* pOk = GetDlgItem(IDCANCEL);
    if ( NULL != pOk )
        pOk->EnableWindow(FALSE);
    SetTimer(100,1000,NULL); 
    return lRet;
}

// Purpose: display running countdown, close when finished.
void CDelayMessageBox2::OnTimer(UINT nIDEvent)
{
    if (nIDEvent == 100)
    { 
        if (m_count>0)
            SetWindowText(FormTitle(--m_count));

        if (m_count == 0)
        {
            CWnd* pOk = GetDlgItem(IDCANCEL);
            if ( NULL != pOk )
            {
                pOk->EnableWindow(TRUE);
                pOk->SetFocus();
            }
            KillTimer(100);
            if (m_autoclose)
                PostMessage(WM_CLOSE,0,0);
        }
    }
}

// Purpose: Display a message box, hooking it to do stuff
int CDelayMessageBox2::MessageBox(LPCTSTR lpszText, 
                    int count, bool bclose,MBIcon icon)
{ 
    m_autoclose = bclose;
    m_count = count;
    AfxHookWindowCreate(this);
    return ::MessageBox(m_hWndParent, 
        lpszText, FormTitle(m_count), icon);
}

// Purpose: compose a title for the dialog based 
// on the # of seconds left to disable it

CString CDelayMessageBox2::FormTitle(int num)
{
    CString s;
    s.Format("%d seconds remaining",num);
    return s;
}

// Purpose: prevent dialog from closing before 
// it has timed out
LRESULT CDelayMessageBox2::DefWindowProc(
    UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_COMMAND && m_count > 0)
    {
        if(HIWORD(wParam) == BN_CLICKED ) 
            return 0;
    }
    return CWnd::DefWindowProc(message, wParam, lParam);
}

Conclusion

This class started off with one idea and ended up with another. This was also one of Nish's first proper attempts with using hooks. So he might have made some erroneous assumptions. But he is counting on the wonderful feedback that is available through the thousands of CodeProject visitors and regulars. Shog would also like to see whether there is any way to further simply the class. Thank you.

Updates and fixes

  • Aug 14 2002 - Shog has joined Nish as co-author and now there is a more MFC-ied version of the class available. Both classes have been retained as they both depict various interesting win32 techniques.
  • Aug 13 2002 - A bug was reported by Andreas Saurwein where he discovered that the space bar can close the delayed message box. This has been fixed by sub-classing the message box window and handling the message that causes this behaviour.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Authors

Shog9
Software Developer
United States United States
Member
Poke...

Nish Sivakumar
United States United States
Member
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionClose the MessageBox when exit programmemberforzamilan21 Sep '05 - 17:25 
Hi, my problem is: When I call to show a MessageBox, and then exit the program (by DestroyWindow the main dialog). The MessageBox remain and the program will not exit until I press the OK button of message box. How can I program to close the openning message box when exit main program?
Thanks.
QuestionWhy annoying the user?memberuweph4 Apr '05 - 21:50 
If I'm testing a program, a 'feature' like that is a big minus factor.
Even a message like 'the program has expired' is clear enough in a normal message box.
 
The user is not the programmer's enemy!
AnswerRe: Why annoying the user?memberoriginSH20 Jul '07 - 1:53 
Yeah but if you annoy the user in a minor way often enough they might actually cough up the cash to buy your app :P
 
This feature is designed for when you have shareware apps that are time limited. THe user cna continue to use the app but you have to put in a little 'nag' screen to remind them they really should pay. It's kinder to the user than the alternative of just stopping all use of the application.
Generalvery urgentmembernandeeshds10 Jan '05 - 3:47 
i nish,
 
the work u have done is realy superb.
 
for my application i don't need ok button.
 
can u pls tell me how to remove ok button from the message box.
 
pls give me a reply as soon as possible.
 
thanks and regards
 
nandeesh
GeneralRe: very urgentstaffNishant S10 Jan '05 - 20:02 
Enable auto-close and in EnumChildProc, instead of disabling the OK button, hide it.
 
Nish
GeneralRe: very urgentmembernandeeshds11 Jan '05 - 2:09 
thanks nish,
 
i able to do it out.
 
can u pls tell me how to remove ok button from the message box.
 
thanks in advance
 
nandeesh
GeneralRequestmemberSamCode_B00217 Nov '04 - 20:48 
how can i :
1- save doc of MDI application and reopen it after
2- Update the graphique area of MDI application after updating parameters of drawing

 
Sam
Generala doubt ...sussRaajaOfSelf10 Nov '04 - 9:48 
Nish
Can we not use teh pretranslatemessage instead of DefWindowProc ?
 
BTW ,this was very very informative article ..I did learn alot of things ....
 
I like most of ur articles ,esp the article on Strings ,ws brilliant

 
Cause is my effort;
Effect is God's effort
QuestionClose on focus lost?sussAnonymous28 Aug '04 - 13:46 
How to implement the functionality to close the message box automatically if it (or its parent window) lost the focus or simply is overdrawn with another program? I tried to implement WM_KILLFOCUS and/or WM_SHOWWINDOW into DefWindowProc and inserted an OnKillFocus() and OnShowWindow()-function, but nothing seems to work ...any ideas? I'm using VC6 and the subclassing class.
 
Marc
GeneralAny better way to get the MB_ICONEXCLAMATION ...memberxcavin19 Jul '04 - 21:54 
Any better way to get the icons MB_ICONEXCLAMATION,MB_ICONQUESTION, etc dynamically from OS ?
So that its not hardcoded, which is actually a windows standard.
GeneralRe: Any better way to get the MB_ICONEXCLAMATION ...memberShog920 Jul '04 - 5:55 
Using MB_ICONEXLAMATION et. al. is the accepted method of displaying status icons in Windows. The operating system is free to choose whichever actual images it wants to display.
 

You're one microscopic cog
in his catastrophic plan...

Questioncan I enable the ok button for ever?membercode_code25 Mar '03 - 14:06 
can I enable the ok button for ever?
I need click on OK then close the messagebox,
otherwise wait delay seconds to close itautomaticly
AnswerRe: can I enable the ok button for ever?editorNishant S27 Mar '03 - 20:01 
code_code wrote:
can I enable the ok button for ever?
I need click on OK then close the messagebox,

 
Uhm, in our implementation we didnt consider this situation. Our delay is the delay for the button to be enabled. What you want is a normal message box that closes automatically after a while. Hmmmm. That sounds like a timed messagebox.
 
tell you what - you can do this :-
 
1. start a timer
2. show the messagebox
3. in the timer when your time period expires send a wm_close to the message box HWND (use FindWindow to get it)
 
Good luck
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralUi ConsiderationmemberSwinefeaster19 Aug '02 - 10:48 
Great article!
 
I use something like this in my app --- where the dialog can be simply closed by clicking the mouse anywhere outside of it. But it still *looks* like a modeless dialog, and I haven't figured out a way to tell the users they don't need to hit the Close button.
 
Any thoughts? Smile | :) It's gotta be something to do with tweaking the window styles...
 
Cheers,
 
swine
 
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.

GeneralRe: Ui ConsiderationmemberShog919 Aug '02 - 11:17 
I guess removing the title bar and border would be your best option. It should at least give them a hint that it's not modal. Also, in place of a close button you could do a delayed close when the user moves the mouse - this would ensure they at least see it, but most likely won't have to even think about closing it.
 
---
Shog9
Actually I use to find learning in bars when drinking really useful.
It sort of makes a language liquid.
- Colin Davies, Thinking in English?

GeneralRe: Ui ConsiderationmemberSwinefeaster20 Aug '02 - 10:55 
I'll try that out and see how it looks...
 
Cheers
 
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.

GeneralSetTimermemberBob Eastman14 Aug '02 - 3:37 
I added the class to a project, when I get to the SetTimer
 
int CDelayMessageBox::MessageBox(LPCTSTR lpszText, int count, bool bclose,MBIcon icon)
{
m_autoclose = bclose;
m_hHook = SetWindowsHookEx(WH_CBT,CBTProc,
AfxGetApp()->m_hInstance,
AfxGetApp()->m_nThreadID);
m_count = count;
SetTimer(100,1000,NULL);
 
the program crashes.
 
I access it using:
 
//CDelayMessageBox mbox(this);
CDelayMessageBox::MBIcon mbicon = CDelayMessageBox::MBIcon::MBICONNONE;
CDelayMessageBox mbox(this);
CString m_text = _T("hello");

mbox.MessageBox(m_text,
10,
1,
(CDelayMessageBox::MBIcon)mbicon);
 
Am I doing something incorrectly to cause the crash?
 
thanks
GeneralRe: SetTimereditorNishant S14 Aug '02 - 3:49 
What does the call-stack say? At what point does it crash?
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: SetTimermemberBob Eastman14 Aug '02 - 4:47 
Here is the data from the call-stack
 
_CrtDbgReport(int 2, const char * 0x5f4ac2dc _szAfxWinInl, int 168, const char * 0x00000000, const char * 0x00000000) line 302 + 20 bytes
AfxAssertFailedLine(const char * 0x5f4ac2dc _szAfxWinInl, int 168) line 39 + 20 bytes
CWnd::SetTimer(unsigned int 100, unsigned int 1000, void (HWND__ *, unsigned int, unsigned int, unsigned long)* 0x00000000) line 168 + 42 bytes
CDelayMessageBox::MessageBoxA(const char * 0x009523ac, int 10, unsigned char 1, CDelayMessageBox::MBIcon MBICONNONE) line 102
 
It says that the crash is on line 168 of afxwin2.inl
 
bob
 


GeneralRe: SetTimereditorNishant S14 Aug '02 - 5:33 
From which class are you trying to instantiate the delay message box? Is it a CWnd derived class? Only a CWnd derived class can instantiate the message box. For non-CWnd derived classes use version 2 of the class, and pass NULL instead of this.
 
Regards,
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: SetTimermemberBob Eastman14 Aug '02 - 6:38 
Nish
 
That worked. Thanks for your help, and a very nice class.
 
regards
bob
GeneralRe: SetTimereditorNishant S14 Aug '02 - 18:03 
Bob Eastman wrote:
That worked
 
Ok, that's cool Smile | :)
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralGotcha! Bug.memberAndreas Saurwein13 Aug '02 - 2:36 
You can close it anytime by pressing the space bar Poke tongue | ;-P
 
int x=1, y=5; 
x^=y^=x^=y; // whats the content of x and y now?

GeneralRe: Gotcha! Bug.editorNishant S13 Aug '02 - 5:37 
Andreas Saurwein wrote:
You can close it anytime by pressing the space bar
 
Hello Andreas
 
Thanks for reporting the bug. The issue has been solved and the article has been updated. Smile | :)
 
Regards,
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

QuestionSimilar article?memberAnthony_Yio13 Aug '02 - 0:53 
I did not thoroughly check through your program.
But I feel that your article is quite similar to
 
Enhanced MessageBox - Timer, checkbox and more
By Russ Freeman
 
Still, I respect people who submit their article to codetools.
 

AnswerRe: Similar article?editorNishant S13 Aug '02 - 1:08 
Anthony_Yio wrote:
Enhanced MessageBox - Timer, checkbox and more
By Russ Freeman

 
URL please...
 
Nish
 
p.s. Is it a delay-msg-box too?
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Similar article?memberAnthony_Yio13 Aug '02 - 1:15 
http://www.codetools.com/miscctrl/GSMessageBox.asp
 
Haven't gone through yet. But it has autokill.
GeneralRe: Similar article?editorNishant S13 Aug '02 - 1:21 
Ok
 
I just chk'd it out, he does have an auto-kill feature.
But it's not a delay msgbox.
 
Mine is primarily intended as a delay-msg box Smile | :)
The auto-close is a side-effect in mine Smile | :)
 
Nice one by Russ anyway
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Similar article?memberAnthony_Yio13 Aug '02 - 1:28 
cool
GeneralGoodmemberShog912 Aug '02 - 11:52 
Glad to see you worked out your centering problems Nish, and this is a nice bonus. Smile | :)
 
It does seem rather complex though, doesn't it? What with pointer maps, hidden windows with weird titles, and hooks... Would it be possible instead to subclass the actual message box window itself inside the CBT hook?
 
---
Shog9
If I could sleep forever, I could forget about everything...

GeneralRe: GoodeditorNishant S12 Aug '02 - 15:33 
Shog9 wrote:
Glad to see you worked out your centering problems Nish
 
Yeah, it was rather funny when I realized there were no centering problems to start with.
 
Shog9 wrote:
It does seem rather complex though, doesn't it? What with pointer maps, hidden windows with weird titles, and hooks...
 
Yeah, Fazlul was saying the same thing. Too much work for what it does.
 

Shog9 wrote:
Would it be possible instead to subclass the actual message box window itself inside the CBT hook?
 
Dunn, I didn't try. But we have the HWND. So it should be possible I guess
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: GoodmemberMustafa Demirhan13 Aug '02 - 8:27 
Shog9 wrote:
Would it be possible instead to subclass the actual message box window itself inside the CBT hook?
 
I think in the following implementation, subclassing is used (though I like Nish's way more) :
 
http://codeguru.earthweb.com/misc/TOMsgBox.shtml[^]
 
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix

They say I'm lazy but it takes all my time
GeneralRe: GoodmemberShog913 Aug '02 - 8:31 
Mustafa Demirhan wrote:
I think in the following implementation
 
That looks even weirder! WTF | :WTF:
Do you ever get the feeling that Windows programming is nothing but one gigantic code obfuscation contest...?
 
---
Shog9
If I could sleep forever, I could forget about everything...

GeneralRe: GoodmemberMustafa Demirhan13 Aug '02 - 8:41 
Shog9 wrote:
Do you ever get the feeling that Windows programming is nothing but one gigantic code obfuscation contest...?
 
Always Roll eyes | :rolleyes:
 
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix

They say I'm lazy but it takes all my time
GeneralRe: GoodeditorNishant S13 Aug '02 - 8:57 
Hi Shog
 
I dunno whether you are gonna smile or frown, but today a bug was reported about the space bar dismissing the message box even when the delay wasn't yet over; and I have corrected this and updarted the article. The weird thing is I subclassed the message box window to do this. Now it's a rather complicated bit of code to achieve something like a delayed message box. Hooks, invisible windows, sub classed message boxes and CWnd-HWND maps Unsure | :~
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: GoodmemberShog913 Aug '02 - 15:29 
Nishant S wrote:
Hooks, invisible windows, sub classed message boxes and CWnd-HWND maps
 
Hmm, now that's quite a collection there... a nice little puzzle. I'm sure there's a way, looking at all the clever (infuriating, but clever) hacks that MFC and ATL use to get around bothersome Windows restrictions, i'm convinced there's a short, criptic solution to every WinAPI problem. Now, just to find it...
 
---
Shog9
If I could sleep forever, I could forget about everything...

GeneralRe: GoodeditorNishant S13 Aug '02 - 15:43 
Shog9 wrote:
short, criptic solution to every WinAPI problem
 
cryptic** perhaps, but short? Hmmmm.
 
Nish
 

** note the correct spelling, shog.
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: GoodmemberShog913 Aug '02 - 15:46 
Nishant S wrote:
note the correct spelling, shog.
 
Blush | :O
And it's still early! And i haven't even started drinking yet! Ah, i think this is *not* the night i'll be writing human-readable material...
 
---
Shog9
If I could sleep forever, I could forget about everything...

GeneralRe: GoodmemberColin^Davies13 Aug '02 - 19:25 
Shog9 wrote:
hidden windows with weird titles,
 
mmm .... I have been doing that for a while also.
I have my phone number with a message to send on one window that is in the 'wild'.
Smile | :)

 
Regardz
Colin J Davies


Sonork ID 100.9197:Colin

You are the intrepid one, always willing to leap into the fray! A serious character flaw, I might add, but entertaining.
Said by Roger Wright about me.


GeneralAnother (easy) waymemberFazlul Kabir12 Aug '02 - 9:29 
First, thanks for the contribution.
 
We actually use a delayed message box in the trial version of our product RadVC for Visual C++[^]. The message box is a CDialog - based class and is made visible from the beginning. The "OK" button is invisible in the beginning and the timer makes it visible after a delayed interval, in a way very similar to what you have used in your article.
 
void CExpireDlg::OnTimer(UINT nIDEvent)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if(nIDEvent == m_nIDTimer)
{
KillTimer(m_nIDTimer);
m_nIDTimer = 0;
CWnd* pWndOKBtn = CWnd::GetDlgItem(IDOK);
ASSERT_VALID(pWndOKBtn);
if(pWndOKBtn && pWndOKBtn->GetSafeHwnd())
pWndOKBtn->ShowWindow(SW_SHOWNORMAL);
}
CDialog::OnTimer(nIDEvent);
}

 
As you can guess, the approach is a lot simpler as you do not need to use any hidden window and complex HOOKing mechanism. May be I am missing something on your purpose of using hooks, except the fact that you wanted to learn how that works (as you mentioned in the article).
 
Nevertheless, it's an interesting article to demonstrate a delayed messagebox and Windows hooks. Thanks.
 

// Fazlul
 

Get RadVC today! Play RAD in VC++
http://www.capitolsoft.com

GeneralRe: Another (easy) wayeditorNishant S12 Aug '02 - 15:31 
Fazlul Kabir wrote:
May be I am missing something on your purpose of using hooks, except the fact that you wanted the learn how that works (as you mentioned in the article).
 
Hi FK,
 
Well, I started doing this when trying to center a message box using a hook when I realized the non-centering boxes were children of the desktop Blush | :O
 
But then I guess you have a point in the fact that this seems a lot of work for what I was trying to do. But the difference is that I don't need a dialog resource here, though you probably create your dialog desource in memory!
 
Thanks,
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralJustify yourself, that's all I ask!editorNishant S12 Aug '02 - 8:26 
Look, I don’t have a problem with someone giving me a 1 as long as he justifies it, but what irks me is that someone unjustifiably gave me a 1 just now, about 10 minutes after the article had been up. If there was a reason for that kindly speak it out here. I mean, as the author of the article I feel entitled to know why it deserved a 1, so that I could at least rectify the problem in the next update.
 
Regards,
Nish

 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Justify yourself, that's all I ask!memberGeorge12 Aug '02 - 9:26 
I just gave you 5, but let me comment some...
 
Nishant S wrote:
I mean, as the author of the article I feel entitled to know why it deserved a 1, so that I could at least rectify the problem in the next update.
 
Just like many other democratic votes ratings at CP are anonymous. Get used to it.
 
There is no requirement to explain any rating anybody gives you. Someone has a bad day - bang, you get 1. Someone doesn't like the topic or the form of article - bang, 1 again.
 
I really hate that kind of ranting about giving 1 or 5 or whatever and need of explaining it. In fact it's that ranting that is not justified. Eveybody has right to vote. Simple. There is no need to explain the votes. That is the way it should be.
 
Take it like a man, and relax - it's only numbers after all Wink | ;)
GeneralRe: Justify yourself, that's all I ask!memberPJ Arends12 Aug '02 - 9:56 
George wrote:
it's only numbers after all
 
OMG | :OMG: OMG | :OMG: OMG | :OMG: OMG | :OMG:
 
You play dangerously don't you? Saying that to a man who *lives* for numbers Poke tongue | ;-P
 
I just hope you don't live too close to Nish;)
 


CPUA 0x5041
 
Sonork 100.11743 Chicken Little
 
"So it can now be written in stone as a testament to humanities achievments "PJ did Pi at CP"." Colin Davies
 
Within you lies the power for good - Use it!
GeneralRe: Justify yourself, that's all I ask!memberShog912 Aug '02 - 11:35 
PJ Arends wrote:
You play dangerously don't you? Saying that to a man who *lives* for numbers
 
LOL! Yeah, putting down a man's religion - playing with fire, 'tis! Wink | ;)
 
---
Shog9
If I could sleep forever, I could forget about everything...

GeneralRe: Justify yourself, that's all I ask!editorNishant S12 Aug '02 - 15:36 
PJ Arends wrote:
Saying that to a man who *lives* for numbers
 
Woah there PJ, I say woah there! Don't let everyone know that. It's a secret Wink | ;-)
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Justify yourself, that's all I ask!editorNishant S12 Aug '02 - 15:35 
George wrote:
Someone has a bad day - bang, you get 1. Someone doesn't like the topic or the form of article - bang, 1 again.
 
Correction George!
 
Someone has a bad day - bang, Nish gets 1. Someone doesn't like the topic or the form of article - bang, 1 again for Nish.
 
But overall, thanks Smile | :)
 
Nish
 
p.s. My ranting is also kinda democratic eh?
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Justify yourself, that's all I ask!memberRoger Allen15 Aug '02 - 0:45 
Nishant S wrote:
Someone has a bad day - bang, Nish gets 1
I think its more like "Someone who's article is being read and doesn't do exactly what they want, gets 1".
 
Its happened to all of us. Its a sad thing. If I vote on an article, I always put up a comment.

 
Roger Allen
Sonork 100.10016
 
I think I need a new quote, I am on the prowl, so look out for a soft cute furry looking animal, which is really a Hippo in disguise. Its probably me.

GeneralRe: Justify yourself, that's all I ask!editorNishant S15 Aug '02 - 1:02 
Roger Allen wrote:
If I vote on an article, I always put up a comment.
 
That's the decent way of doing it. I only wish everyone would follow that.
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

QuestionVC6 Version?sussSharbanoe12 Aug '02 - 8:01 
Is there, or will there be a VC6 version, as I don't use, and don't want to use VC.NET
 
WTF | :WTF:

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 14 Aug 2002
Article Copyright 2002 by Shog9, Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid