Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Message Reflection for WTL Controls

0.00/5 (No votes)
25 Jan 2001 1  
Impementation of message reflection for WTL wrappers for Windows Controls
  • Download demo project - 10 Kb
  • Download source - 1 Kb
  • Introduction

    Recently I needed to create a WTL control that would handle all its functionality inside of the control itself, like can be done in any standard MFC control.

    In MFC to do this the Control should get its own notifications back from its parent using message reflection, which is described in TN061-TN062. I did not found anything like this in the current version of WTL, so I decided to implement it myself. I created two macros: the first macro does the reflection - it sends some of the notifications received by the window back to it source, and the second macro which resides in a control wrapper handle these messages. Maybe this way is slightly rude but so far it works and it is simple... ;-)

    Here is the first macros, "reflector":

    #define WM_NOTIFY_REFLECTOR()\
        if(uMsg == WM_NOTIFY)\
        {\
            UINT code = ((LPNMHDR)lParam)->code;\
            switch(code)\
            {\
            case NM_SETCURSOR:\
                break;\
            default:\
                if ((NULL != lParam) &&\
                (NULL != ((LPNMHDR)lParam)->hwndFrom))\
                {\
                    BOOL bHandled = ::SendMessage(((LPNMHDR)lParam)->hwndFrom, \
                                                  WM_NOTIFY + WM_REFLECT_BASE, wParam, lParam);\
                    if(bHandled) \
                        return TRUE; \
                };\
            };\
        }\
    

    To use it just place it in message map of any window which you want to reflect WM_NOTIFY.

    Here is the second macros, "handler":

    #define NOTIFY_REFLECT_CODE_HANDLER(cd, func) \
    { \
        if (((WM_NOTIFY + WM_REFLECT_BASE) == uMsg) && \
            (NULL != lParam) && \
            (cd == ((LPNMHDR)lParam)->code)) \
        {\
            bHandled = FALSE;\
            lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);\
            if(bHandled)\
                return TRUE;\
        }\
    }
    

    Use it just like usual MESSAGE_HANDLER or NOTIFY_HANDLER in message map of control.

        BEGIN_MSG_MAP(CCusomTreeCtrl)
            NOTIFY_REFLECT_CODE_HANDLER(TVN_ITEMEXPANDING, OnExpand)
        END_MSG_MAP()
        LRESULT OnExpand(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
        {
            // disable expanding
    
            LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) pnmh;
            if (pnmtv->action == TVE_EXPAND)
            {
                bHandled = TRUE;
                return 1;
            }
            return 0;
        }
    

    And do not forget to put header file with macroses into stdafx.h.

    I suspect that I missed a lot of important stuff in this implementation but for my needs it works. If you feel that you can improve it just do it or let me know how to do it.

    License

    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