Is there a way to get the handler function that a control is mapped to in an MFC application?

604 views Asked by At

Lets say I have an MFC application with a button control on it. Is there a way to retrieve that function that OON_BN_CLICKED maps it to? I know CWnd has a GetDlgItem function which will return a pointer to a control. Is there a way to get the function the control is mapped to if I have this pointer?

I have found a method which I believe can be used to send a message to a Dialog item or control: CWnd::SendDlgItemMessage (http://msdn.microsoft.com/en-us/library/e2a6czt1.aspx), but Id' like to be able to know the possible messages.

1

There are 1 answers

2
Nikolay On BEST ANSWER

In most circumstances, you know the messages you can send to a window. I strongly suspect you might be not taking the right path for your task. What are you trying to accomplish actually? I.e. what you are asking is uncommon, and the real task can most probably can be solved by other means.

Anyways. If you have a pointer to some MFC CWnd-derived object, it is still possible to 'reverse engineer' it's MFC message handlers defined in the class pointed by that CWnd*. MFC defines all message handlers in a map using BEGIM_MESSAGE_MAP/END_MESSAGE_MAP. What these macros actually do is, they define a virtual function called GetMessageMap() and a data array containing structures describing message mapping. So you can could use wnd->GetMessageMap() and then iterate over the mapped message handlers. Each entry contains information about the message handler, and the mapped function. Note that GetMessageMap is a protected function, so to access it from outside, you'll need a wrapper. Something like this:

struct Accessor : public CWnd
{
    // overwrite protected
    virtual const AFX_MSGMAP* GetMessageMap() const { return CWnd::GetMessageMap(); }
};

Accessor* msg_map_access = (Accessor*) window;
const AFX_MSGMAP* msg_map = msg_map_access->GetMessageMap();

const AFX_MSGMAP_ENTRY* entry = msg_map->lpEntries;
while (entry->nSig != AfxSig_end)
{
    /// do something with the entries
}

Again, this is not common practice; normally, you never do that. So it would be nice to hear the motivation why you need this.