Теперь мы попробуем понять как работает этот механизм. Итак, начало программы. В CTestDlgDlg поступает сообщение WM_CTRLCOLOR. В ответ он вызывает OnCtlColor() для класса, которому это сообщение поступило. У нас этот класс CTestDlgDlg:
WM_CTRLCOLOR |____________ OnCtlColor (CTestDlgDlg)
Если в этом классе обработка сообщения есть, то дальше некуда не пойдет. То есть, если при обработке этого сообщения не вызвать базовую функцию класса CDialog::OnCtlColor(pDC, pWnd, nCtlColor) больше ничего не произойдет. OnChildNotify() для классов элементов управления не вызовется. А если все-таки мы вызовем метод базового класса ???
WM_CTRLCOLOR |____________ OnCtlColor (CTestDlgDlg) CDialog::OnCtlColor
CDialog::OnCtlColor() просто вызовет функцию своего родителя CWnd::OnGrayCtlColor().
WM_CTRLCOLOR |____________ OnCtlColor (CTestDlgDlg) CDialog::OnCtlColor |_______________ CWnd::OnGrayCtlColor
Эта функция нигде не документирована и является внутренней для MFC, ну и бог с ней, главное что она делает. Она вызывает функцию CWnd::SendChildNotifyLastMsg().
WM_CTRLCOLOR |____________ OnCtlColor (CTestDlgDlg) CDialog::OnCtlColor |_______________ CWnd::OnGrayCtlColor CWnd::SendChildNotifyLastMsg
С помощью этой функции мы пересылаем сообщение от окна родителя окну ребенка ;-) Эта функция просто вызовет OnChildNotify() класса.
BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult) { _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); return OnChildNotify(pThreadState->m_lastSentMsg.message, pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult); }