Это очень показательное сообщение. Сообщение WM_CTLCOLOR посылается каждый раз когда само окно или одно из его средств управления должно перерисоваться. В ответ должна вернуться кисть для перерисовки.
Итак, давайте изучать. Создаем приложение на базе MFC AppWizard с именем TestDlg как диалоговое окно. Для класса CTestDlgDlg вызовем Add Windows Message Handler. Найдем там сообщение WM_CTLCOLOR и добавим его обработку к классу.
//////////////////////////////// // CTestDlgDlg dialog class CTestDlgDlg : public CDialog { ...... afx_msg HCURSOR OnQueryDragIcon(); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here // TODO: Return a different brush if the default is not desired return hbr; }
Давайте заменим кисть, чтобы окрасить окно в разные цвета:
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { pDC->SetBkColor(RGB(127,127,127)); return (HBRUSH)::GetStockObject(GRAY_BRUSH); }
Если Вы сейчас запустите приложение, то окно будет серым. Это нормально, мы так и хотели. Поместите на диалоговую панель Edit Box, Static Box. Запустите приложение. Они тоже будут серыми. Эти элементы управления спрашивают кисть для покраски у родителя, то есть они посылают сообщение диалоговому окну с просьбой указать чем красить. Давайте попробуем это исправить.
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if (CTLCOLOR_EDIT == nCtlColor) { pDC->SetTextColor(RGB(0,0,0)); pDC->SetBkColor(RGB(255,255,255)); return (HBRUSH)::GetStockObject(WHITE_BRUSH); } if (CTLCOLOR_STATIC == nCtlColor) { pDC->SetBkColor(RGB(255,0,255)); return (HBRUSH)::GetStockObject(GRAY_BRUSH); } pDC->SetBkColor(RGB(127,127,127)); return (HBRUSH)::GetStockObject(GRAY_BRUSH); }
Вот теперь совсем другое дело. Белое поле редактирования, красный статический элемент. Работает. А что если у нас много элементов управления ??? Как разобраться какой красить ??? Поместите второй элемент управления и код для него:
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if (CTLCOLOR_EDIT == nCtlColor) { UINT id = pWnd->GetDlgCtrlID(); if (id == IDC_EDIT2) { pDC->SetTextColor(RGB(0,0,0)); return (HBRUSH)::GetStockObject(WHITE_BRUSH); } if ( id == IDC_EDIT1) { pDC->SetTextColor(RGB(0,0,0)); return (HBRUSH)::GetStockObject(DKGRAY_BRUSH); } } if (CTLCOLOR_STATIC == nCtlColor) { pDC->SetBkColor(RGB(255,0,255)); return (HBRUSH)::GetStockObject(GRAY_BRUSH); } pDC->SetBkColor(RGB(127,127,127)); return (HBRUSH)::GetStockObject(GRAY_BRUSH); }
Как видите разобраться можно. Есть следующие идентификаторы:
Все это хорошо, только сейчас мы реализовали все как при программировании на WIN32 API без всяких там классов. Но в реальности правильно, если за закраску будет отвечать сам класс. Так должно быть. Не должен диалог отвечать за закраску своих элементов. Иначе при большом количестве идентификаторов ваша функция OnCtlColor() превратится в сплошной switch. Об этом в следующем шаге. А пока посмотрите на результат. Он у Вас должен быть такой же.