locked
Post Message between Parent and Child Windows

    Question

  • I want to implement architecture of multiply layers, every layer has their own thread and windows. 

    In my initial modal, I just create two layers in my model.   I find some problem when I post message from parent window.

    In main frame, click startthat will create new thread, the message function as follow:
    MainFrm.cpp //(MessageLayerThread::CWinThread)
    1. void CMainFrame::OnStart()

    {
      //pass the main window handle to the thread in order to create its child window 
    msgThread = new MessageLayerThread(m_hWnd);  

    //create thread call function: InitInstance() 
    msgThread->CreateThread(); 
    }

    2.MessageLayerThread.cpp (MessageLayerThread::CWinThread)

    MessageLayerThread::MessageLayerThread(HWND ai_hParent) : m_hwndParent(ai_hParent)

    {
    }

    BOOL MessageLayerThread::InitInstance()
    {
                TRACE("Run MessageLayerThread.\n");
                CWnd* pParent = CWnd::FromHandle(m_hwndParent);
                CRect rect;
                pParent->GetClientRect(&rect);
               
    //3. Create child window: MessageLayer, m_wndMsgLayerWindow is reference of MessageLayer and has declared in MessageLayerThread.h
                BOOL m_bWindowSuccess = m_wndMsgLayerWindow.Create(_T("CMsgLayerWindow"),WS_CHILD, rect,pParent);

                if (m_bWindowSuccess){
                            TRACE("MessageLayer window is created.\n");
                            m_pMainWnd = &m_wndMsgLayerWindow;
               
    //4.Main window posts message

    pParent->PostMessage(WM_WINDOW_CREATED,(WPARAM)m_wndMsgLayerWindow.m_hWnd);
    }

    return TRUE;
    }

    3. Create child window
    MessageLayer.cpp (MessageLayer::CWnd)
    BOOL MessageLayer::Create(LPCTSTR szTitle, LONG lStyle, const RECT& rect, CWnd* pParent)
    {
                return CWnd::Create(NULL,  
                                        szTitle,  
                                        lStyle,  
                                        rect,  
                                        pParent,
                                        MESSAGE_WINDOW_ID);
    }

    4.Fcuntion for response the message WM_WINDOW_CREATED in InitInstance()
    MainFrm.cpp
    LRESULT CMainFrame::OnMessageWindowCreated(WPARAM wParam, LPARAM lParam)

    {
                if(msgThread != NULL)
                {
               
    //5.if msgThread has created before, child window will post message
                msgThread->m_pMainWnd->PostMessage(ON_RUN,0,0);


                }

                return true;
    }
        
    5. ON_RUN function:
    MessageLayer.cpp(MessageLayer::CWnd)
    LRESULT MessageLayer::OnRun(WPARAM wParam, LPARAM lParam)
    {
                bool flag = false;
                while(!flag){
                TRACE("\n waiting data");
                }

                 return true;
    }


    The main window can’t response in while loop.

    I have some question about that:
    1 I try to add PostMessage directly in 1. OnStart() after  msgThread->CreateThread()

    void CMainFrame::OnStart()
    {
                msgThread = new MessageLayerThread(m_hWnd);  
                msgThread->CreateThread(); 

                if(msgThread != null)

     msgThread->m_pMainWnd->PostMessage(ON_RUN,0,0);

    }

    but there is no response by message. I wonder when the function initInstance() is called. If when I create thread, the function is called automatically, why I can’t post message after that?


    2 I PostMessage in initInstance() by parent window after create child window. And then post message to child window when child thread has created. The message gets response in this case. But I can’t make any operations about main window at this time. How do I modify this to avoid main window freeze.

    Thank you.

     

    Friday, December 16, 2011 5:00 PM

Answers

  • BOOL MessageLayer::Create(LPCTSTR szTitle, LONG lStyle, const RECT& rect, 
    CWnd* pParent)
    {
    return CWnd::Create(NULL, 
    szTitle, 
    lStyle, 
    rect, 
    pParent,
    MESSAGE_WINDOW_ID);
    }
    • Marked as answer by Janet Ding Monday, January 09, 2012 2:15 PM
    Wednesday, December 21, 2011 5:10 PM

All replies

  • >> I wonder when the function initInstance() is called. If when I create thread,
    >> the function is called automatically, why I can’t post message after that?

    Creating a thread does not make it run immediately. It starts running only at some future time controlled by the Windows thread scheduler. So it is not reliable to post message to it immediately after calling CreateThread. The thread may not have executed anything yet.

    Do not post to it until you know the thread has started to run. For example, it looks like your OnMessageWindowCreated function is executed after the thread has started and created its window.

     

    Friday, December 16, 2011 6:40 PM
  • Thanks Scott, the OnMessageWindowCreated function is exactly executed after the thread has started and created its window.

    I mean I can't  post this message directly in OnStart() MainFrm after msgThread->CreateThread() so that I have to post this message in the initInstance() by parent window.

     

    I have another question.

    When I try to post message by parent window in function  InitInstance() of MessageLayerThread like this:

    BOOL MessageLayerThread::InitInstance()
    {
                TRACE("Run MessageLayerThread.\n");
                CWnd* pParent = CWnd::FromHandle(m_hwndParent);
                CRect rect;
                pParent->GetClientRect(&rect);
                
    //3. Create child window: MessageLayer, m_wndMsgLayerWindow is reference of MessageLayer and has declared in MessageLayerThread.h 
                BOOL m_bWindowSuccess = m_wndMsgLayerWindow.Create(_T("CMsgLayerWindow"),WS_CHILD, rect,pParent);

                if (m_bWindowSuccess){
                            TRACE("MessageLayer window is created.\n");
                            m_pMainWnd = &m_wndMsgLayerWindow;
                
    //4.Main window posts message

    pParent->PostMessage(WM_WINDOW_CREATED,(WPARAM)m_wndMsgLayerWindow.m_hWnd);
    }

    return TRUE;

    }

    In WM_WINDOW_CREATED message function , I  post another message by child window that is while loop. At this time, I can move main window but I can't do any operation for the window , why? That means the main thread in while loop??? I try to debug the same program in virtual PC mode(Windows xp SP3), it works fine.

     

    MainFrm.cpp
    LRESULT CMainFrame::OnMessageWindowCreated(WPARAM wParam, LPARAM lParam)

    {
                if(msgThread != NULL)
                {
                
    //5.if msgThread has created before, child window will post message
                msgThread->m_pMainWnd->PostMessage(ON_RUN,0,0);


                }

                return true;
    }
        
    5. ON_RUN function:
    MessageLayer.cpp(MessageLayer::CWnd)
    LRESULT MessageLayer::OnRun(WPARAM wParam, LPARAM lParam)
    {
                bool flag = false;
                while(!flag){
                TRACE("\n waiting data");
                }

                 return true;
    }

    Tuesday, December 20, 2011 4:01 PM
  • The parent/child relationship may be the problem. If the parent tries to send a message to the child window the child window does not accept the message (because it is in a while loop) so the parent cannot proceed.  Some circumstances may cause parent/child windows to use SendMessage inside the operating system.

    Try making a top-level window (pParent = NULL) instead of a child window. That will remove any hidden SendMessage calls between the two windows.

     

     

    Tuesday, December 20, 2011 5:15 PM
  • Hi Scott, how to create child without parent window or null parent that cause assertion failed.

      m_wndMsgLayerWindow.Create(_T("CMsgLayerWindow"),WS_CHILD, rect, null);

     

    Wednesday, December 21, 2011 5:04 PM
  • BOOL MessageLayer::Create(LPCTSTR szTitle, LONG lStyle, const RECT& rect, 
    CWnd* pParent)
    {
    return CWnd::Create(NULL, 
    szTitle, 
    lStyle, 
    rect, 
    pParent,
    MESSAGE_WINDOW_ID);
    }
    • Marked as answer by Janet Ding Monday, January 09, 2012 2:15 PM
    Wednesday, December 21, 2011 5:10 PM
  • Why do you want it to be a child window? There is no such thing as a child without a parent window.

    And why are you creating this window if it is only going to execute a while loop?  A window should process messages.  Especially if you create a top-level window there is a probability that the OS or other programs will send messages to it.

     

    Wednesday, December 21, 2011 6:05 PM
  • I need four window handles to communicate with each other.

    Actually, in initial model, the one is an other window's child window. Message window is child window of main window, the protocol window is child window of message window, the physical window is child window of protocol window.  In program, some message in while loop for waiting data is posted to physical window that cause the window freeze.

    I want to change the design to solve the problem.  

     

    So I just create one window that is child window of main window, and try to post message including while loop the this window in secondary thread. That is my purpose. 

     

    Actually, I develop the program in virtual PC XP SP3, when I post message to child window, it works fine. I move the program to win7, when the message is posted, I can't do any operation to the window. 

     

    I have tried to change create window individually, like this:

    m_wndMsgLayerWindow.Create(_T("CMsgLayerWindow"),WS_CAPTION, CRect(0, 0, 20, 20),null);

    But it pops up assertion failed error.

    How can I create window without parent? 

     

    Tuesday, December 27, 2011 2:53 PM
  • Study the line that asserts and the function that contains that line. That should give you a clue.

     

    Tuesday, December 27, 2011 8:40 PM