Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / MFC

Dynamic button function call: alternative for BEGIN_MESSAGE_MAP

Rate me:
Please Sign up or sign in to vote.
3.53/5 (22 votes)
18 Feb 2010CPOL3 min read 82.4K   1.4K   110   12
This article discusses a trick to define/re-define a dynamic button's click event.

Screenshot - DynButtonGIF.gif

Introduction

This article is going to show another aspect of BEGIN_MESSAGE_MAP() provided in VC++ (MFC). A brief introduction about this: in MFC, whenever there is a need to make a button control dynamic, we often get hung up on the point of defining a map to link with the corresponding method for that button such that when that button is clicked, our method will get called. This article is going to show you a sample of code where I have created a dynamic button, which is mapped with a function as per the job selected by the radio buttons, rather than using a pre-defined map.

Background

As an MFC developer, you may already know that whenever you have to create an application in which buttons or controls are going to be created dynamically, you need to presume the constant (Resource_ID) for controls. You also have to specify the method corresponding to the map, like ON_COMMAND(RESOURCE_ID, methodName) in BEGIN_MESSAGE_MAP(). As a result, whenever the button is clicked, the corresponding method would get invoked.

However, for a more dynamic environment, we may need to find an alternative way in which we can redefine the click event when it is already specified.

As a .NET developer, you may also be aware of delegates, pointers to functions that play a significant role in defining a method for any event of a control. This article talks about a similar functionality for a non-.NET environment. For the time being, this functionality is defined for the button-click event only. This is achieved using the ON_COMMAND() aspect of MFC with a pre-defined message map. The message map is defined and assigned values based on the requirements of the control. In future, I'll try to cover other events of MFC so that it may become more flexible for all events.

Using the code

We use a trick here: just like BEGIN_MESSAGE_MAP(), information about ID and its corresponding method is collected and stored in a pre-defined map. The following code is used for the creation of the map containing the ID and the function pointers:

C++
typedef void (CDynButtonDlg::*fn)(int i);
typedef std::map< UINT, fn > EventMessageMap;

Using this map type, we create a new variable. Here is the actual instance:

C++
EventMessageMap msgMap;

Whenever we need to create a button dynamically, we'll make a corresponding entry in this map:

C++
// To Create Dynamic Button with #define DYNAMIC_BUTTON_ID 123
m_btnDynamic.Create("Dynamic", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, 
    CRect(100,150,200,200),this, DYNAMIC_BUTTON_ID);

// Make Entry in Map for this ID
msgMap[DYNAMIC_BUTTON_ID] = &CDynButtonDlg::Job1;

Now, our work of changing functions is simple. Whenever we wish to change the functionality of a function, we just need to do this:

C++
// Make Entry in Map for this ID
msgMap[DYNAMIC_BUTTON_ID] = &CDynButtonDlg::Job2;

The only remaining question to be answered is, "How will this function be called when the button is clicked?" The answer is:

C++
// OnCmdMsg is called when any command is fired
BOOL CDynButtonDlg::OnCmdMsg(UINT nID, int nCode, 
    void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
    // Here we'll iterate our Map & call it's corresponding function.
    EventMessageMap::iterator itTrg = msgMap.find( nID );
    if(itTrg != msgMap.end())
    {
        fn btnM = msgMap[nID];
        this->*btnM)(5);
    }
    return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

I am not claiming that this is the only way to do this. Another way could be by putting conditions and call functions accordingly. I just found a new way to accomplish this task, so I am sharing it with all of you here.

What's next

I wish to make MFC events more flexible as delegates are in .NET. I'll wait for your valuable comments. I'll update this article if I could find more free time/issues.

Happy coding! :)

History

  • 21 June 2007 -- Original version posted.
  • 17 February 2010 -- Updated description.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Working in Patni Computer Systems, Noida(INDIA). I like to work in C/C++ even from my school time & mostly worked using C++, VC++, COM.

I want to give something bigger than biggest to IT field. Try is going on.

I like to make friends.
That’s all about me.

Ok! See you.
Have a nice Life.

Comments and Discussions

 
QuestionHow to Get/Set Event when Create Dynamic as Child ? Pin
Member 1057023017-Apr-18 22:46
Member 1057023017-Apr-18 22:46 
Thanks for sharing this Dynamic Button . looks good.
After several changing. I am stuck on the button click will never get back from
CDynButtonDlg::OnCmdMsg()

follow by changing Create function.
From:
m_btnDynamic.Create("Dynamic", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, CRect(10,10,160,60),this, DYNAMIC_BUTTON_ID);

To:
m_btnDynamic.Create("Dynamic", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, CRect(10,10,160,60),GetDlgItem(IDC_STATIC_TRY), DYNAMIC_BUTTON_ID);


Can some one help on this ?
I had tried
OnChildNotify , ON_WM_PARENTNOTIFY()
, but still not working.
GeneralMy vote of 3 Pin
Member 102364872-Feb-14 23:13
Member 102364872-Feb-14 23:13 
QuestionCan I use message mapping of external windows applications Pin
staler.ideas14-Jul-11 22:05
staler.ideas14-Jul-11 22:05 
Generalthis->*btnM)(5); Pin
CODEPC19-Feb-10 2:19
CODEPC19-Feb-10 2:19 
GeneralRe: this->*btnM)(5); Pin
firehore_00730-Jun-11 4:08
firehore_00730-Jun-11 4:08 
GeneralIt's good Pin
Ram.Cse11-Apr-08 11:35
Ram.Cse11-Apr-08 11:35 
GeneralRe: It's good Pin
Sumit Kapoor13-Apr-08 23:38
Sumit Kapoor13-Apr-08 23:38 
GeneralIt's helpful! Pin
James Huo27-Jan-08 14:48
James Huo27-Jan-08 14:48 
GeneralThis is great!! Pin
pointer29-Aug-07 3:23
pointer29-Aug-07 3:23 
GeneralWell done Pin
wu27612010-Aug-07 18:58
wu27612010-Aug-07 18:58 
GeneralHOHO Pin
desk11185-Aug-07 22:08
desk11185-Aug-07 22:08 
GeneralGreat job Pin
butchi peddi24-Jun-07 18:35
butchi peddi24-Jun-07 18:35 

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.