CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    May 2006
    Location
    Mumbai, India
    Posts
    292

    Message Handler and Command Handler

    Hi,

    Can anyone explain me the difference between Message Handler and Command Handler.

    If function provided in Message Handler is invoked on Send/PostMessage then how the same is invoked in case of command handler.

    Thanks,
    Sachin.

  2. #2
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: Message Handler and Command Handler

    please show us the code snippets of each and we can point out what the difference is.
    Also, what do you mean by this
    If function provided in Message Handler is invoked on Send/PostMessage then how the same is invoked in case of command handler
    Please elaborate.

  3. #3
    Join Date
    May 2006
    Location
    Mumbai, India
    Posts
    292

    Re: Message Handler and Command Handler

    Hi kirants...

    These are some lines of code

    Code:
    MESSAGE_HANDLER(WM_STATICTABCLICKED, OnStatictabclicked)
    COMMAND_HANDLER(IDC_CHECK_ENABLE_DIST, BN_CLICKED, OnCheckEnableAppDistribution);
    I understand that WM_STATICTABCLICKED is a message so we use Message_Hanler.
    Similarly Is BN_CLIKED a message a button control sends to the dialog. Or it works in some different way.

    Also..
    If I use API SendMessage() to send STATICTABCLICKED msg to this dialog then it will invoke OnStatictabclicked function.
    Is there some way I can invoke OnCheckEnableAppDistribution manually..

    Hope I am clear..
    Thanks..

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: Message Handler and Command Handler

    Quote Originally Posted by sachin871
    Hi kirants...

    These are some lines of code
    You should have mentioned in your OP that you mean ATL message/command handlers.
    Code:
    MESSAGE_HANDLER(WM_STATICTABCLICKED, OnStatictabclicked)
    COMMAND_HANDLER(IDC_CHECK_ENABLE_DIST, BN_CLICKED, OnCheckEnableAppDistribution);
    Quote Originally Posted by sachin871
    Also..
    If I use API SendMessage() to send STATICTABCLICKED msg to this dialog then it will invoke OnStatictabclicked function.
    Is there some way I can invoke OnCheckEnableAppDistribution manually..
    Yes, you can.
    You have to send the WM_COMMAND message with the WPARAM, LPARAM set as described in MSDN BN_CLICKED article.
    Victor Nijegorodov

  5. #5
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: Message Handler and Command Handler

    MESSAGE_HANDLER and COMMAND_HANDLER are just macros defined in a header file. When you compile your code, each one will be as good as having this piece of code.

    • MESSAGE_HANDLER is defined like this:
      Code:
      if(uMsg == msg) \
      { \
      	bHandled = TRUE; \
      	lResult = func(uMsg, wParam, lParam, bHandled); \
      	if(bHandled) \
      		return TRUE; \
      }
      which translates to this for your code:
      Code:
      if(uMsg == WM_STATICTABCLICKED)
      {
      	bHandled = TRUE;
      	lResult = OnStatictabclicked(uMsg, wParam, lParam, bHandled);
      	if(bHandled)
      		return TRUE;
      }
    • Similarly, COMMAND_HANDLER is defined like this:
      Code:
      #define COMMAND_HANDLER(id, code, func) \
      if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
      { \
      	bHandled = TRUE; \
      	lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
      	if(bHandled) \
      		return TRUE; \
      }
      which translates to this for your code:
      Code:
      if(uMsg == WM_COMMAND && IDC_CHECK_ENABLE_DIST == LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
      {
      	bHandled = TRUE;
      	lResult = OnCheckEnableAppDistribution(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);
      	if(bHandled)
      		return TRUE;
      }


    That is what the two macros essentially do. Now, wrapping these 2 lines, you must be having a BEGIN_MSG_MAP and END_MSG_MAP , isn't it ? What does that do ?
    BEGIN_MSG_MAP is defined like this:
    Code:
    #define BEGIN_MSG_MAP(theClass) \
    public: \
    	BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
    	{ \
    		BOOL bHandled = TRUE; \
    		(hWnd); \
    		(uMsg); \
    		(wParam); \
    		(lParam); \
    		(lResult); \
    		(bHandled); \
    		switch(dwMsgMapID) \
    		{ \
    		case 0:
    and END_MSG_MAP thus:
    Code:
    #define END_MSG_MAP() \
    			break; \
    		default: \
    			ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
    			ATLASSERT(FALSE); \
    			break; \
    		} \
    		return FALSE; \
    	}
    Now, if you put all these things together in your class, say CMyWindow, all these macros essentially build a huge function body like below:
    Code:
    class CMyWindow : CWindow
    {
    public: 
    	BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0)
    	{ 
    		BOOL bHandled = TRUE; 
    		(hWnd); 
    		(uMsg); 
    		(wParam); 
    		(lParam); 
    		(lResult); 
    		(bHandled); 
    		switch(dwMsgMapID) 
    		{ 
    		case 0:
    
    		if(uMsg == WM_STATICTABCLICKED)
    		{
    			bHandled = TRUE;
    			lResult = OnStatictabclicked(uMsg, wParam, lParam, bHandled);
    			if(bHandled)
    				return TRUE;
    		}
    		
    		if(uMsg == WM_COMMAND && IDC_CHECK_ENABLE_DIST == LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
    		{
    			bHandled = TRUE;
    			lResult = OnCheckEnableAppDistribution(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);
    			if(bHandled)
    				return TRUE;
    		}
    
    		break; 
    		default: 
    			ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)n"), dwMsgMapID); 
    			ATLASSERT(FALSE); 
    			break; 
    		} 
    		return FALSE; 
    	}
    }
    You see from the above that, as you add message map entries, you are silently building a long function body for ProcessWindowMessage for each of the message your class would like to handle.

    The common denominator, as you see, is basic to windows programming. The UINT msg for the message, the WPARAM and the LPARAM. As long as you Send/Post the msg, WPARAM and LPARAM to a window, you are good. Only thing is, you need to make sure you send it right.

    To answer your question, if you see code above, COMMAND_HANDLER is jusy yet another message handler, albeit specialized in some way. It is specialized to decode the WPARAM to extract out the LOWORD and HIWORD and interpret them as the control ID and the notification code respectively. If you want to trigger the OnCheckEnableAppDistribution programmatically, all you would do is something like below:
    Code:
    PostMessage(hTargetWnd, WM_COMMAND, MAKEWPARAM(controlID,BN_CLICKED),0);
    As you see from the COMMAND_HANDLER code above, that is all you need. However, it is not good. If you read up on WM_COMMAND documentation, you will see the lParam also has special meaning. So , you need to send it accordingly.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured