Работа с Visual Studio.Net

         

Обработка сообщений от элементов управления

В окно диалога мы ввели четыре кнопки, при нажатии которых в класс диалогового окна посылается уведомляющее сообщение BN_CLICKED. При изменении данных в окнах редактирования посылаются другие сообщения EN_CHANGE. При воздействии на ползунки также посылаются уведомляющие сообщения, которые мы рассматривали в предыдущей главе. Однако, как было отмечено, ползунки посылают и обычные сообщения (WM_HSCROLL или WM_VSCROLL). Если в окне диалога имеется более одного ползунка, то сообщения от них удобно обработать в одной функции, которая вызывается в ответ на сообщение о прокрутке. Введите в класс CPolyDlg реакцию на WM_HSCROLL, так как наши ползунки ориентированы горизонтально:

void CPolyDlg::OnHScroll(UINT

nSBCode, UINT nPos, CScrollBar* pScrollBar)

{

//====== Неинтересное для нас сообщение

if (nSBCode==SB_ENDSCROLL)

return;

//====== Устанавливаем флаг сообщений от ползунков

m_bScroll = true;

//====== Узнаем идентификатор активного ползунка

switch(GetFocus()->GetDlgCtrlID())

{

case IDC_RSLIDER:

//====== Считываем текущую позицию движка

m_nRed = m_rSlider.GetPos();

//====== Синхронизируем поле, редактирования

SetDlgltemlnt(IDC_RED, m_nRed);

break;

case IDC_GSLIDER:

m_nGreen = m_gSlider.GetPos();

SetDlgltemlnt(IDC_GREEN, m_nGreen);

break; case IDC_BSLIDER:

m_nBlue = m_bSlider.GetPos() ;

SetDlgltemlnt(IDC_BLUE, m_nBlue);

break;

}

//====== Снимаем флаг сообщений от ползунков

m_bScroll = false;

}

Сообщения от всех ползунков обрабатываются в одной функции. Идентификатор активного ползунка определяется путем последовательного вызова двух функций GetFocus и GetDlgctrliD, являющихся методами класса cwnd.

Флаг сообщений от ползунков (m_bScroll) понадобился нам для того, чтобы при синхронизации элементов управления не происходили повторные вызовы функций-обработчиков. Дело в том, что при изменении позиции ползунка мы должны привести в соответствие окно редактирования, а при ручном изменении числа в окне редактирования мы должны синхронизировать позицию ползунка. Но сообщение EN_CHANGE посылается как при ручном изменении, так и при программном изменении с помощью функции SetDlgltemlnt. Проследим цепь таких событий: пользователь подвинул движок ползунка, мы вызываем SetDlgltemlnt, она провоцирует посылку сообщения EN_CHANGE, а обработчик этого сообщения корректирует положение ползунка, которое и без того верно.

Введите в класс диалога реакции на уведомления EN_CHANGE от четырех элементов IDC_PEN, IDC_RED, IDC_GREEN И IDC_BLUE. Вы помните, что это надо делать с помощью кнопки Events в окне Properties. Вставьте коды в остовы функций обработки, как показано ниже:

void CPolyDlg::OnChangePen(void)

{

BOOL bSuccess; //====== Попытка преобразовать в число

UINT nSize = GetDlgltemlnt(IDC_PEN, SbSuccess, FALSE);

if (bSuccess && nSize < 101)

{

m_nPen = nSize;

m_pDoc->m_Poly-m_nPenWidth = m_nPen;

m_pDoc->UpdateDrawView();

}

}

Отметьте, что здесь мы намеренно не пользуемся функцией UpdateData, которая провоцирует обмен данными сразу со всеми полями окна диалога, так как хотим показать более экономный способ выборочного (целевого) обмена с помощью функции GetDlgltemlnt. Правда, при таком подходе не работают функции проверки данных типа DDV_ и приходится производить проверку самостоятельно:

void CPolyDlg::OnChangeRed(void) {

//====== Если сообщение спровоцировано ползунком,

//====== то обходим коды его синхронизации

if (!m_bScroll)

{

m_nRed = GetDlgltemlnt(IDC_RED, 0, FALSE);

m_rSlider.SetPos(m_nRed);

//====== Изменяем цвет фона окна редактирования

m_cRed.ChangeColor(RGB(m_nRed, 0, 0));

//====== Корректируем интегральный цвет

UpdateColor();

}

void CPolyDlg::OnChangeGreen(void)

{

if (!m_bScroll)

{

m_nGreen = GetDlgltemlnt(IDC_GREEN, 0, FALSE), m gSlider.SetPos(m_nGreen);

m_cGreen.ChangeColor(RGB(0, m_nGreen, 0)); UpdateColor ();

}

void CPolyDlg::OnChangeBlue(void)

{

if (!m_bScroll)

{

m_nBlue = GetDlglteralnt(IDC_BLUE, 0, FALSE);

m_bSlider.SetPos(m_nBlue);

}

m_cBlue.ChangeColor(RGB(0, 0, m_nBlue));

UpdateColor ();

}

Введите тело вспомогательной функции, которая вычисляет интегральный цвет и вносит изменения, перекрашивая окно диалога IDC_COLOR, и с помощью документа текущий полигон в окне CDrawView:

void CPolyDlg::UpdateColor()

{

COLORREF clr = RGB (m_riRed,m_nGreen,m_nBlue) ;

m_cColor.ChangeColor(clr) ;

m_pDoc->m_Poly.m_BrushColor = clr;

m_pDoc->UpdateDrawView();

}

С помощью Studio.Net введите в класс диалога реакции на уведомляющие сообщения (BN_CLICKED) о нажатии кнопок выбора стандартных геометрий для полигонов (IDCJTRI, IDC_PENT и IDC_STAR). В них мы с помощью техники обратного указателя вновь обращаемся к документу и используем его данные и методы для замены координат точек текущего полигона:

void CPolyDlg::OnClickedTri(void)

{

m_pDoc->m_Poly.MakeTria() ;

m_pDoc->UpdateDrawView() ;

}

void CPolyDlg::OnClickedPent(void)

{

m_pDoc->m_Poly.MakePent() ;

m_pDoc->UpdateDrawView() ;

}

void CPolyDlg::OnClickedStar(void)

{

m_pDoc->m_Poly.MakeStar() ;

m_pDoc->UpdateDrawView();

}

Измените тело конструктора диалогового класса, с тем чтобы при открытии диалога он смог запомнить обратный указатель (адрес документа) и все его элементы были правильно инициализированы:

CPolyDlg::CPolyDlg(CTreeDoc* p)

: CDialog (CPolyDlg::IDD, 0)

{

m_pDoc = p;

m_nPen = p->m_Poly.m_nPenWidth;

//====== Расщепляем цвет фона текущего полигона

COLORREF brush = p->m_Poly.m_BrushColor;

m_nRed = GetRValue(brush); // на три компонента

m_nGreen = GetGValue(brush);

m_nBlue = GetBValue(brush) ;

m_bScroll = false; // Ползунки в покое

Содержание раздела