Таблица. 5.1 Идентификаторы элементов управления
Элемент |
Идентификатор |
Диалог |
IDD_POLYCOLOR |
Окно редактирования Size |
IDC_PEN |
Кнопка TRI |
IDCJTRI |
Кнопка PENT |
IDC_ PENT |
Кнопка STAR |
IOC_ STAR |
Кнопка Close |
IDOK |
Окно редактирования Red |
IDC_RED |
Окно редактирования Green |
IDC_GREEN |
Окно редактирования Blue |
IDC_BLUE |
Ползунок (Slider) |
IDC_RSLIDER |
Slider |
IDC_GSLIDER |
Slider |
IDC_BSLIDER |
Окно редактирования Color |
IDC_COLOR |
Для трех кнопок (TRI, PENT и STAR) установите стиль Owner draw, так как это будут не стандартные кнопки, а кнопки с изображениями, управляемые классом CBitmapButton. Для ползунков установите следующие стили: Orientation: Horizontal, TickMarks: True, AutoTicks: True, Point: Top/Left.
Для управления диалогом необходимо создать новый класс. Для этого можно воспользоваться контекстным меню, вызванным над формой диалога.
Просмотрите объявление класса CPolyDlg, которое должно появиться в новом окне PolyDlg.h. Как видите, мастер сделал заготовку функции DoDataExchange для обмена данными с элементами управления на форме диалога. Самих функций обмена типа DDX_ еще нет, но мы их создадим немного позже.
Нестандартные элементы управления
Рассмотрим, как создаются элементы управления, имеющие индивидуальный нестандартный облик. Сравнительно новым подходом в технологии создания таких элементов является обработка подходящего сообщения не в классе родительского окна, а в классе, связанном с элементом управления диалога. Такая возможность появилась в MFC начиная с версии 4.0, и она носит название Message Reflection. Элементы управления Windows посылают уведомляющие сообщения своим родительским (parent) окнам. Например, многие элементы, в том числе и Edit controls, посылают сообщение WM_CTLCOLOR, позволяющее родительскому окну выбрать кисть для закраски фона элемента. В версиях MFC (до 4.0), если какой-либо элемент должен выглядеть не так, как все, то эту его особенность обеспечивал класс родительского окна, обычно диалог. Теперь к старому механизму обработки уведомляющих сообщений от дочерних (child) элементов добавился новый, который позволяет произвести обработку уведомляющего сообщения в классе самого элемента. Уведомляющее сообщение как бы отражается (reflected) назад в класс дочернего окна элемента управления. Мы собираемся использовать нестандартные окна редактирования (Red, Green, Blue и Color), с тем чтобы они следили за изменением цвета, отражая текущий выбор как в числовом виде, так и в виде изменяющегося цвета фона своих окон. Эту задачу можно выполнить, создав класс (назовем его cclrEdit), производный от CEdit, и введя в него обработку отражаемого сообщения =WM CTLCOLOR.
Примечание
Примечание
Обратите внимание на символ = перед идентификатором сообщения Windows. Он необходим, чтобы различить два сообщения с одним именем. Наличие символа = означает принадлежность сообщения к группе отражаемых (reflected) сообщений.
Применяя уже известный вам подход, создайте класс cclrEdit с базовым классом CEdit. В процессе определения атрибутов нового класса укажите существующие файлы (PolyDlg.h и PolyDlg.cpp) в качестве места для размещения кодов нового класса. Если возникнут окна диалогов с просьбой подтвердить необходимость погружения кодов в уже существующие файлы, то ответьте утвердительно. Введите изменения в файл PolyDlg.h, так чтобы он приобрел следующий вид:
#pragma once
//===== Класс нестандартного окна редактирования
class CClrEdit : public CEdit
{
DECLARE_DYNAMIC (CClrEdit)
public:
CClrEdit () ;
virtual -CClrEdit () ;
void ChangeColor (COLORREF clr) ; // Изменяем цвета
protected:
DECLARE_MESSAGE_MAP ()
private :
COLORREF ra_clrText; // Цвет текста
COLORREF ra_clrBk; // Цвет фона
CBrush m_brBk; // Кисть для закраски фона
};
//====== Класс для управления немодальным диалогом
class CPolyDlg : public CDialog
{
friend class CClrEdit;
DECLARE_DYNAMIC (CPolyDlg)
public : enum ( IDD = IDD_POLYCOLOR } ;
//====== Удобный для нас конструктор
CPolyDlg (CTreeDoc* p) ;
virtual -CPolyDlg ( ) ;
//====== Отслеживание цвета
void UpdateColor () ;
protected: virtual void DoDataExchange (CDataExchange* pDX) ;
DECLARE_MESSAGE_MAP ( ) private :
CTreeDoc* m_pDoc; // Обратный указатель
CBitmapButton m_cTri; // Кнопки с изображениями
CBitmapButton m_cPent;
CBitmapButton m_cStar;
bool ra_bScroll; // Флаг использования ползунка };
};
Мы изменили конструктор класса CPolyDlg так, чтобы он имел один параметр — адрес документа, который мы используем в качестве обратного указателя. Это поможет нам управлять приложением, оставаясь в рамках методов диалогового класса. Теперь воспользуемся услугами Studio.Net для создания функции-обработчика сообщения =WM_CTLCOLOR в классе нестандартного окна редактирования.
Найдите заготовку тела функции ctlColor в файле PolyDlg.cpp и вставьте в нее следующие коды:
HBRUSH CClrEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetTextColor (m_clrText); // Цвет текста
pDC->SetBkColor (m_clrBk); // Цвет подложки текста
return m_brBk; // Возвращаем кисть
}
Создайте тело вспомогательной функции ChangeColor, которую мы будем вызывать в те моменты существования диалога, когда пользователь изменяет значения элементов управления цветом:
void CClrEdit::ChangeColor(COLORREF clr)
{
//====== Цвет текста - инвертирований цвет фона
m_clrText = ~clr & Oxffffff;
m_clrBk = clr;
//====== Создаем кисть цвета фона
m_brBk.DeleteObject();
m_brBk.CreateSolidBrush (clr);
Invalidate ();
}
Главным управляемым параметром является кисть (m_brBk), которую в ответ на отраженное сообщение =WM_CTLCOLOR надо возвратить каркасу приложения. Попутно мы изменяем цвет текста (setTextColor) и его подложки (setBkColor). Чтобы понять, что такое подложка текста, при отладке временно закомментируйте строку
pDC->SetBkColor (m_clrBk);
При изменении (инвертировании) цвета текста мы вынуждены обнулять четвертый байт переменной m_clrText. В более старых версиях Windows это действие было лишним. Теперь четвертый байт используется для задания степени прозрачности при воспризведении растровых изображений. Если он не равен нулю, то инвертирование цвета не проходит. Первые три байта, как вы помните, задают три компонента (red, green, blue).
Изменение цвета пользователем с помощью элементов управления будет мгновенно отслеживаться в четырех полях диалога (три компонента цвета и суммарный цвет в окне Color). Так как мы хотим отследить изменение цвета и в окне представления, управляемого классом CDrawView, то мы добываем адрес родительского oкna.(GetParent) и вызываем вспомогательную функцию UpdateDrawView.