Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. PostMessage... philosophy...

PostMessage... philosophy...

Scheduled Pinned Locked Moved C / C++ / MFC
com
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Remi Morin
    wrote on last edited by
    #1

    Hi, I have a Home-Made control who post a message. This control can be placed anywhere. All of this stuff run very well but something is not like I wan't it to be and it's the first time I use Message queuing

    void MyHomeMadeControl::AMethod(void)
    {

    PostMessage(GetParent(),
                (UINT)this,
                (long)&m\_Var);
    

    }

    class CBoopView : public CView { //some stuff MyHomeMadeControl m_Ctrl_1; MyHomeMadeControl m_Ctrl_2; //everything else }

    void CBoopView::OnZoomScroll(MyHomeMadeControl* WParam,MyHomeMadeParam* lParam)
    {
    if(&m_Ctrl_1 == WParam)
    {
    //Here I know it's m_Ctrl_1
    }
    else
    {
    //Here m_Ctrl_2...
    }
    }

    I don't think it's a very good way to do so... It is possible in my PostMessage to do something like

    PostMessage(GetParent(),
                GetCurrentId(), //this return the Id of my CWnd (you know the UINT nID of the create function)
                (long)&m\_Var);
    

    so that way I will used Id number instead of pointers... thanks (by the way if there is a "standart way to identify the Object who Post the message tell me) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

    T 1 Reply Last reply
    0
    • R Remi Morin

      Hi, I have a Home-Made control who post a message. This control can be placed anywhere. All of this stuff run very well but something is not like I wan't it to be and it's the first time I use Message queuing

      void MyHomeMadeControl::AMethod(void)
      {

      PostMessage(GetParent(),
                  (UINT)this,
                  (long)&m\_Var);
      

      }

      class CBoopView : public CView { //some stuff MyHomeMadeControl m_Ctrl_1; MyHomeMadeControl m_Ctrl_2; //everything else }

      void CBoopView::OnZoomScroll(MyHomeMadeControl* WParam,MyHomeMadeParam* lParam)
      {
      if(&m_Ctrl_1 == WParam)
      {
      //Here I know it's m_Ctrl_1
      }
      else
      {
      //Here m_Ctrl_2...
      }
      }

      I don't think it's a very good way to do so... It is possible in my PostMessage to do something like

      PostMessage(GetParent(),
                  GetCurrentId(), //this return the Id of my CWnd (you know the UINT nID of the create function)
                  (long)&m\_Var);
      

      so that way I will used Id number instead of pointers... thanks (by the way if there is a "standart way to identify the Object who Post the message tell me) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

      T Offline
      T Offline
      Tomasz Sowinski
      wrote on last edited by
      #2

      Wrong, wrong, wrong. You're trying to use a parent window pointer as message identifier. This will not work.

      #define WM_MY_MESSAGE (WM_USER + 1)
      ...
      GetParent()->PostMessage(WM_MY_MESSAGE, someWparam, someLparam);

      You can pass object pointer as wParam or lParam, as long as window that's going to process the message is in the same process. In your case it's true. There's another caveat: PostMessage places message in the queue. Receiving window will not get this message immediately - and depending on application, the object that you passed as message parameter may no longer exist. In such case, use SendMessage instead of PostMessage. One final note: when you are using your controls only within this program, you may establish communication between windows without messages. Just cast the pointer returned by GetParent() to correct type and call whatever method you need:

      // inside YourHomeMadeControl
      CBoopView *pView = (CBoopView*)GetParent();
      pView->Foo(param1, param2, param3);

      Tomasz Sowinski -- http://www.shooltz.com

      R 1 Reply Last reply
      0
      • T Tomasz Sowinski

        Wrong, wrong, wrong. You're trying to use a parent window pointer as message identifier. This will not work.

        #define WM_MY_MESSAGE (WM_USER + 1)
        ...
        GetParent()->PostMessage(WM_MY_MESSAGE, someWparam, someLparam);

        You can pass object pointer as wParam or lParam, as long as window that's going to process the message is in the same process. In your case it's true. There's another caveat: PostMessage places message in the queue. Receiving window will not get this message immediately - and depending on application, the object that you passed as message parameter may no longer exist. In such case, use SendMessage instead of PostMessage. One final note: when you are using your controls only within this program, you may establish communication between windows without messages. Just cast the pointer returned by GetParent() to correct type and call whatever method you need:

        // inside YourHomeMadeControl
        CBoopView *pView = (CBoopView*)GetParent();
        pView->Foo(param1, param2, param3);

        Tomasz Sowinski -- http://www.shooltz.com

        R Offline
        R Offline
        Remi Morin
        wrote on last edited by
        #3

        Some difficulties to understand... this is a sumary of my .h file

        class MyHomeMadeControl :public CWnd
        {
        // Construction
        public:
        MyHomeMadeControl ();
        // Overrides
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(MyHomeMadeControl )
        private:
        virtual BOOL Create(const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
        //}}AFX_VIRTUAL

        // Implementation
        public:
        virtual ~MyHomeMadeControl ();
        // Generated message map functions
        protected:
        //{{AFX_MSG(MyHomeMadeControl )
        afx_msg void OnPaint();
        afx_msg void OnTimer(UINT nIDEvent);
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
        };
        static UINT WM_ON_TIMER_HOMEMADE= RegisterWindowMessage("MyHomeMadeControl_OnTimer");

        and then the function on timer in the cpp file: void CGraphScroll::OnTimer(UINT nIDEvent) { //here to ba able to import this code anywhere I have to do something like this GetParent()->PostMessage(WM_ON_TIMER_HOMEMADE,(UINT)this,something); /*this will require a #include "parent.h" witch I don't know ((CBoopView)GetParent())->OnTimer(Anything I want) */ } So in a boopView (who can be a any kind of CWnd derived class) I have to trap this message, and I can have 0 to n instance of MyHomeMadeControl. So for catch the message what I did work, but it's very strange... for a CButton It work very well and it's done like this

        ON_BN_CLICKED(IDC_BUTTONX, OnButtonX)

        ON_BN_CLICKED is a macro and it will be replace by

        ON_CONTROL(BN_CLICKED, IDC_BUTTONX, OnButtonX)

        it's exactly what I wan't to re-create with my Home made control, no matter how many of them exist, any of them will find whitch handler to use...

        ON_CONTROL(WM_ON_TIMER_HOMEMADE,IDC_MYHOME_MADE_CONTROL_1,OnTimerControl_1)
        ON_CONTROL(WM_ON_TIMER_HOMEMADE,IDC_MYHOME_MADE_CONTROL_2,OnTimerControl_2)

        this doesn't work... Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

        T 1 Reply Last reply
        0
        • R Remi Morin

          Some difficulties to understand... this is a sumary of my .h file

          class MyHomeMadeControl :public CWnd
          {
          // Construction
          public:
          MyHomeMadeControl ();
          // Overrides
          // ClassWizard generated virtual function overrides
          //{{AFX_VIRTUAL(MyHomeMadeControl )
          private:
          virtual BOOL Create(const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
          //}}AFX_VIRTUAL

          // Implementation
          public:
          virtual ~MyHomeMadeControl ();
          // Generated message map functions
          protected:
          //{{AFX_MSG(MyHomeMadeControl )
          afx_msg void OnPaint();
          afx_msg void OnTimer(UINT nIDEvent);
          //}}AFX_MSG
          DECLARE_MESSAGE_MAP()
          };
          static UINT WM_ON_TIMER_HOMEMADE= RegisterWindowMessage("MyHomeMadeControl_OnTimer");

          and then the function on timer in the cpp file: void CGraphScroll::OnTimer(UINT nIDEvent) { //here to ba able to import this code anywhere I have to do something like this GetParent()->PostMessage(WM_ON_TIMER_HOMEMADE,(UINT)this,something); /*this will require a #include "parent.h" witch I don't know ((CBoopView)GetParent())->OnTimer(Anything I want) */ } So in a boopView (who can be a any kind of CWnd derived class) I have to trap this message, and I can have 0 to n instance of MyHomeMadeControl. So for catch the message what I did work, but it's very strange... for a CButton It work very well and it's done like this

          ON_BN_CLICKED(IDC_BUTTONX, OnButtonX)

          ON_BN_CLICKED is a macro and it will be replace by

          ON_CONTROL(BN_CLICKED, IDC_BUTTONX, OnButtonX)

          it's exactly what I wan't to re-create with my Home made control, no matter how many of them exist, any of them will find whitch handler to use...

          ON_CONTROL(WM_ON_TIMER_HOMEMADE,IDC_MYHOME_MADE_CONTROL_1,OnTimerControl_1)
          ON_CONTROL(WM_ON_TIMER_HOMEMADE,IDC_MYHOME_MADE_CONTROL_2,OnTimerControl_2)

          this doesn't work... Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

          T Offline
          T Offline
          Tomasz Sowinski
          wrote on last edited by
          #4

          So your control is designed to be a child of any parent and you want to use ON_CONTROL? It's easy: just remember that you need to call SendMessage rather than PostMessage (there's no need to use a queue). Control notifies its parent by sending one of two messages: WM_COMMAND or WM_NOTIFY. In 16-bit Windows there was only WM_COMMAND, that's why edit, listbox, button and other 'old' controls use this method. OTOH, common controls that made their debut in 32-bit Windows, like listview, treeview, toolbar etc. use WM_NOTIFY. I'd suggest to use WM_NOTIFY as a method of communitaction between the control and any parent window. Use the following code to notify the parent about some event. Note the NM_SOMEEVENT - this is just a unsigned integer number that your parent needs to know. There's no need to use RegisterMessage in this scenario.

          NMHDR hdr = { m_hWnd, ::GetWindowLong(m_hWnd, GWL_ID), NM_SOMEEVENT };
          GetParent()->SendMessage(WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);

          Parent will get WM_NOTIFY. MFC magic routes this message through message map. Use ON_NOTIFY to insert the handler into msgmap of parent window:

          ON_NOTIFY(NM_SOMEEVENT, IDC_MYHOME_MADE_CONTROL_1, OnSomeEvent)

          More details in MSDN, just search for WM_NOTIFY and ON_NOTIFY. Tomasz Sowinski -- http://www.shooltz.com

          R 2 Replies Last reply
          0
          • T Tomasz Sowinski

            So your control is designed to be a child of any parent and you want to use ON_CONTROL? It's easy: just remember that you need to call SendMessage rather than PostMessage (there's no need to use a queue). Control notifies its parent by sending one of two messages: WM_COMMAND or WM_NOTIFY. In 16-bit Windows there was only WM_COMMAND, that's why edit, listbox, button and other 'old' controls use this method. OTOH, common controls that made their debut in 32-bit Windows, like listview, treeview, toolbar etc. use WM_NOTIFY. I'd suggest to use WM_NOTIFY as a method of communitaction between the control and any parent window. Use the following code to notify the parent about some event. Note the NM_SOMEEVENT - this is just a unsigned integer number that your parent needs to know. There's no need to use RegisterMessage in this scenario.

            NMHDR hdr = { m_hWnd, ::GetWindowLong(m_hWnd, GWL_ID), NM_SOMEEVENT };
            GetParent()->SendMessage(WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);

            Parent will get WM_NOTIFY. MFC magic routes this message through message map. Use ON_NOTIFY to insert the handler into msgmap of parent window:

            ON_NOTIFY(NM_SOMEEVENT, IDC_MYHOME_MADE_CONTROL_1, OnSomeEvent)

            More details in MSDN, just search for WM_NOTIFY and ON_NOTIFY. Tomasz Sowinski -- http://www.shooltz.com

            R Offline
            R Offline
            Remi Morin
            wrote on last edited by
            #5

            thanks, it work very well :) So it's the way to do that but question, this structure take all my parameters so in my method (OnSomeEvent in you'r example) I have to call a method like

            m_cMyHomeMadeControl.GetCurrentValues(all parameters I wan't)

            it's a good way (the parent have to know what is his child) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

            T 1 Reply Last reply
            0
            • R Remi Morin

              thanks, it work very well :) So it's the way to do that but question, this structure take all my parameters so in my method (OnSomeEvent in you'r example) I have to call a method like

              m_cMyHomeMadeControl.GetCurrentValues(all parameters I wan't)

              it's a good way (the parent have to know what is his child) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

              T Offline
              T Offline
              Tomasz Sowinski
              wrote on last edited by
              #6

              Calling child directly is one possibility. However, you could also easily add your own information. Just derive some struct from NMHDR:

              struct MyNotifyInfo : public NMHDR
              {
              int yourMember1;
              char yourMember2[100];
              };

              You could also create struct with NMHDR as first member:

              struct MyNotifyInfo
              {
              NMHDR nmhdr;
              int yourMember1;
              char yourMember2[100];
              };

              The second method is used by Windows SDK - these header files must be compilable even in plain old C which doesn't support inheritance. Have a look at MSDN docs for NMTREEVIEW, NMLISTVIEW or any struct named NMxxxx. In the parent's handler, just cast NMHDR* to MyNotifyInfo* and you'll be OK. Tomasz Sowinski -- http://www.shooltz.com

              1 Reply Last reply
              0
              • T Tomasz Sowinski

                So your control is designed to be a child of any parent and you want to use ON_CONTROL? It's easy: just remember that you need to call SendMessage rather than PostMessage (there's no need to use a queue). Control notifies its parent by sending one of two messages: WM_COMMAND or WM_NOTIFY. In 16-bit Windows there was only WM_COMMAND, that's why edit, listbox, button and other 'old' controls use this method. OTOH, common controls that made their debut in 32-bit Windows, like listview, treeview, toolbar etc. use WM_NOTIFY. I'd suggest to use WM_NOTIFY as a method of communitaction between the control and any parent window. Use the following code to notify the parent about some event. Note the NM_SOMEEVENT - this is just a unsigned integer number that your parent needs to know. There's no need to use RegisterMessage in this scenario.

                NMHDR hdr = { m_hWnd, ::GetWindowLong(m_hWnd, GWL_ID), NM_SOMEEVENT };
                GetParent()->SendMessage(WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);

                Parent will get WM_NOTIFY. MFC magic routes this message through message map. Use ON_NOTIFY to insert the handler into msgmap of parent window:

                ON_NOTIFY(NM_SOMEEVENT, IDC_MYHOME_MADE_CONTROL_1, OnSomeEvent)

                More details in MSDN, just search for WM_NOTIFY and ON_NOTIFY. Tomasz Sowinski -- http://www.shooltz.com

                R Offline
                R Offline
                Remi Morin
                wrote on last edited by
                #7

                last question... NMHDR hdr = { m_hWnd, ::GetWindowLong(m_hWnd, GWL_ID), NM_SOMEEVENT }; NM_SOMEEVENT - There's no need to use RegisterMessage in this scenario... I can use any value?? 0 to maximum unsigned int? does it can be in conflict whit parent event? or (as I think) only whit MyHomeMadeControl event (in witch case it is easy to avoid) ... thank you very much for you'r help, it's easy to do code whitout bother whit anything... but take care of everything in a windows program is very hard and good book are not easy to find. Thank you very much :) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

                T 1 Reply Last reply
                0
                • R Remi Morin

                  last question... NMHDR hdr = { m_hWnd, ::GetWindowLong(m_hWnd, GWL_ID), NM_SOMEEVENT }; NM_SOMEEVENT - There's no need to use RegisterMessage in this scenario... I can use any value?? 0 to maximum unsigned int? does it can be in conflict whit parent event? or (as I think) only whit MyHomeMadeControl event (in witch case it is easy to avoid) ... thank you very much for you'r help, it's easy to do code whitout bother whit anything... but take care of everything in a windows program is very hard and good book are not easy to find. Thank you very much :) Remi Morin Rmorin@Operamail.com Remi.Morin@Lyrtech.com

                  T Offline
                  T Offline
                  Tomasz Sowinski
                  wrote on last edited by
                  #8

                  There's no possibility of the conflict. Parent's handler will be called only if both conditions are true: 1) code member of NMHDR is equal to 1st parameter of ON_NOTIFY 2) idFrom member of NMHDR is equal to 2dn parameter of ON_NOTIFY In fact, you can use any value as code. However, it would be a good practice to avoid range of codes starting with NM_FIRST and NM_LAST. In this range you'll find some general-purpose codes, like NM_CLICK. I think you should use NM_LAST+1, NM_LAST+2 etc. for your notification codes. Tomasz Sowinski -- http://www.shooltz.com

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups