Для определения обработчика сообщений, связанных с
открытием диалога, необходимо сгенерировать функцию CFormatDlg::OnInitDialog(), которая получает управление при открытии диалогового окна Format непосредственно перед его отображением. Затем необходимо добавить обработчики сообщений, генерируемых каждым флажком и переключателями. Выполните следующие действия для создания обработчиков сообщений, генерируемых при открытии диалогового окна и его элементами управления.
11. Добавьте объявление защищенной (protected) переменной m_RectSample типа RECT в класс CFormatDlg, выбрав команду Add4Add Variable контекстного меню класса и заполнив соответствующие поля. Эта переменная определяет координаты рамки Sample в диалоговом окне, в которой будет отображаться образец текста.
12. Сгенерируйте функцию CFormatDlg::OnInitDialog(). Для этого выберите класс CFormatDlg в окне Class View. В окне Properties для выбранного класса диалогового окна разверните список виртуальных функций, щелкнув на кнопке Overrides с изображением зеленого кубика. В списке функций выберите имя OnInitDialog, в комбинированном списке которого выберите команду <Add> OnInitDialog. В интерфейс класса диалогового окна в файл FormatDlg.h добавится объявление функции CFormatDlg::OnInitDialog().
class CFormatDlg: public CDialog
{
DECLARE_DYNAMIC(CFormatDlg)
public:
CFormatDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CFormatDlg();
// Dialog Data
enum { IDD = IDD_DIALOG1 };
//... объявления других переменных и методов
protected:
RECT m_RectSample
public:
virtual BOOL OnInitDialog();
};
13. В функцию CFormatDlg::OnInitDialog()в файле FormatDlg.cpp в добавьте следующий код, показанный ниже полужирным шрифтом. Первый добавленный оператор сохраняет экранные координаты рамки Sample в переменной m_RectSample, второй — преобразует координаты экрана в координаты окна, т. е. в координаты точек внутри диалогового окна относительно его левого верхнего угла. Третий добавленный оператор использует переменную m_SpacingEdit класса CEdit для вызова функции CEdit::LimitText(), с помощью которой ограничивается ввод более одного символа в поле IDC_SPACING диалогового окна, если этой функции передается аргумент со значением 1.
|
BOOL CFormatDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
GetDlgItem(IDC_SAMPLE)->GetWindowRect(&m_RectSample);
ScreenToClient(&m_RectSample);
m_SpacingEdit.LimitText(1);
return TRUE;//return TRUE unless you set the focus to a control
//EXCEPTION: OCX Property Pages should return FALSE
}
14. Добавьте обработчики сообщений, генерируемых каждым флажком и переключателями, которые будут получать управление всякий раз при выборе или отмене выбора элемента управления. Для определения обработчиков сообщений в окне Class View выберите класс CFormatDlg, разверните список идентификаторов сообщений в окне Properties, щелкнув на кнопке Events (События). Для идентификатора IDC_BOLD флажка Bold разверните список сообщений и выберите BN_CLICKED. Для выбранного сообщения выполните команду <Add> OnBnClickedBold (рис. 6.13). В файл FormatDlg.h добавится объявление функции-члена, в файл FormatDlg.cpp — ее определение.
15. При желании можно скорректировать имя функции, заменив его значением OnBold. Для этого в окне Properties щелкните в поле с именем функции OnBnClickedBold справа от идентификатора сообщения BN_CLICKED. Появится текстовый курсор после имени функции (рис. 6.14) и можно удалить часть строки, оставив значение OnBold. Можно внести изменения непосредственно в сами файлы. В результате выполненных действий в файл FormatDlg.h в класс CFormatDlg добавляется объявление функции CFormatDlg::OnBold(), в карте сообщений добавляется соответствующий макрос
|
class CFormatDlg: public CDialog
{
//не приводятся объявления других методов и атрибутов
public:
afx_msg void OnBold();
};
// FormatDlg.cpp: implementation file
BEGIN_MESSAGE_MAP(CFormatDlg, CDialog)
ON_BN_CLICKED(IDC_BOLD, OnBold)
END_MESSAGE_MAP()
16. Для реализации обработчика сообщений, источником которых являются флажки, в функцию CFormatDlg::OnBold()добавьте выделенный полужирным шрифтом код. Добавляемый код реализует изменение значения переменной m_Bold. Если флажок не установлен, и значение m_Bold равно FALSE, то щелчок на этом элементе управления приведет к установке значения переменной m_Bold равным TRUE. Если флажок установлен, то щелчок на нем приведет к удалению отметки и установке значения переменной m_Bold равным FALSE. Изменение параметров форматирования текста должно привести к отображению этого текста в новом формате. Для этого необходимо перерисовать область диалогового окна, ограниченную рамкой Sample, объявив эту область недействительной с помощью функции CWnd::InvalidateRect(). Объявленная часть диалогового окна недействительной требует перерисовки, для этого необходимо послать сообщение WM_PAINT, вызвав функцию CWnd::UpdateWindow().
void CFormatDlg::OnBold()
{
// TODO: Add your control notification handler code here
m_Bold =!m_Bold;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
17. Выполните аналогичные действия для добавления обработчиков сообщений, генерируемых флажками Italic и Underline. Для этих элементов управления диалогового окна определены идентификаторы IDC_ITALIC и IDC_UNDERLINE соответственно. Скорректируйте имена добавленных функций в соответствии с табл. 6.7 (см. в конце параграфа). В интерфейс класса CFormatDlg в файле FormatDlg.h добавятся следующие объявления.
class CFormatDlg: public CDialog
{
DECLARE_DYNAMIC(CFormatDlg)
public:
CFormatDlg(CWnd* pParent = NULL); // standard constructor
//объявления других переменных и функций
public:
afx_msg void OnBold();
afx_msg void OnItalic();
afx_msg void OnUnderline();
};
|
18. В файл FormatDlg.срр реализации класса CFormatDlg добавится определение методов, в карте сообщений добавятся соответствующие макросы:
BEGIN_MESSAGE_MAP(CFormatDlg, CDialog)
ON_BN_CLICKED(IDC_BOLD, OnBold)
ON_BN_CLICKED(IDC_ITALIC, OnItalic)
ON_BN_CLICKED(IDC_UNDERLINE, OnUnderline)
END_MESSAGE_MAP()
void CFormatDlg::OnItalic()
{
// TODO: Add your control notification handler code here
m_Italic =!m_Italic;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
void CFormatDlg::OnUnderline()
{
// TODO: Add your control notification handler code here
m_Underline =!m_Underline;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
19. Для идентификации положения образца текста в рамке Sample (слева, в центре, справа) и выбранного переключателя перед объявлением класса CFormat в файл FormatDlg.h введите определения констант. Константы первого перечисления (равные 0, 1 и 2) — это ссылки на номера переключателей группы Justify диалогового окна Format, а константы второго перечисления — это ссылки на номера переключателей в группе Pitch.
enum {JUSTIFY_LEFT, JUSTIFY_CENTER, JUSTIFY_RIGHT};
enum {PITCH_VARIABLE, PITCH_FIXED};
// CFormatDlg dialog
class CFormatDlg: public CDialog
{
// объявления атрибутов и методов
};
20. Добавьте обработчики сообщений, генерируемых переключателями Left, Center, Right, Variable и Fixed диалогового окна Format. Используйте технологию, описанную в п.п. 3 — 6. Имена функций задайте в соответствии с табл.6.7. Затем добавьте в файл FormatDlg.срр в тело сгенерированных функций код. Каждая из этих функций вызывает функцию CWnd::IsDlgButtonChecked(), чтобы убедиться, что переключатель выбран. Обработчик вызывается при каждом щелчке на переключателе и его выборе, а также при нажатии на клавишу табуляции, когда фокус ввода перемещается на переключатель, но последний не выбирается. Если переключатель установлен, то обработчик присваивает его номер соответствующей переменной (m_Justify или m_Pitch). Добавленный код показан полужирным шрифтом:
void CFormatDlg::OnLeft()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_LEFT))
{
m_Justify = JUSTIFY_LEFT;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
void CFormatDlg::OnRight()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_RIGHT))
{
m_Justify = JUSTIFY_RIGHT;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
void CFormatDlg::OnCenter()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_CENTER))
{
m_Justify = JUSTIFY_CENTER;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
void CFormatDlg::OnFixed()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_FIXED))
{
m_Pitch = PITCH_FIXED;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
void CFormatDlg::OnVariable()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_VARIABLE))
{
m_Justify = PITCH_VARIABLE;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
21. Определите функцию, которая получает управление при изменении содержимого поля IDC_SPACING. Для этого в окне Class View выберите класс CFormatDlg. Затем откройте окно Properties и щелкните на кнопке Events. В появившемся списке идентификаторов элементов управления выберите значение IDC_SPACING. Разверните список сообщений и выберите сообщение EN_CHANGE, посылаемое при каждом изменении текста. Выполните команду <Add> OnEnChangeSpacing. Для упрощения имени замените его значением OnChangeSpacing. Добавьте код в сгенерированную функцию. В этом коде предусмотрите вызов функции CWnd::GetDlgItemInt(), чтобы получить содержимое поля в виде целочисленного значения. Если оно находится в допустимом диапазоне, сохраните его в переменной m_Spacing и перерисуйте образец текста. В файл FormatDlg.cpp добавленный код показан полужирным шрифтом.
void CFormatDlg::OnChangeSpacing()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the
// CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
int Temp;
Temp = (int) GetDlgItemInt(IDC_SPACING);
if(Temp > 0 && Temp < 4)
{
m_Spacing = Temp;
InvalidateRect(&m_RectSample);
UpdateWindow();
}
}
22. Переопределите функцию CWnd::OnPaint(), которая выполняет следующие действия: определяет свойства шрифта System в зависимости от значения m_Pitch; модифицирует свойства шрифта в соответствии со значениями переменных m_Bold, m_Italic, m_Underline и создает на его основе новый шрифт, используемый для вывода текста; задает выравнивание текста согласно значению переменной m_Justify; вызывает функцию CDC::TextOut() для вывода текста. Для объявления и определения функции OnPaint() выполните следующие действия. Откройте окно Class View и выберите класс CFormatDlg. Затем откройте окно Properties и щелкните на кнопке Messages. В списке сообщений выделите сообщение WM_PAINT и выполните команду <Add> OnPaint. В файл FormatDlg.h интерфейса класса CFormatDlg добавится объявление функции в виде
afx_msg void OnPaint();
23. В определение функции CFormatDlg::OnPaint()добавьте код, показанный ниже полужирным шрифтом. Действия, выполняемые функцией, поясняются комментариями.
void CFormatDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CDialog::OnPaint() for painting messages
CFont Font; //создать объект шрифта CFont
LOGFONT LF; //структура, содержащая атрибуты шрифта
int LineHeight; //ширина строки
CFont *PtrOldFont;
int X, Y; //координаты отображения текста
// заполнить структуру LF свойствами стандартного системного
//шрифта:
CFont TempFont;
if (m_Pitch == PITCH_VARIABLE)
TempFont.CreateStockObject (SYSTEM_FONT);
else
TempFont.CreateStockObject (SYSTEM_FIXED_FONT);
TempFont.GetObject (sizeof (LOGFONT), &LF);
// инициализировать поля lfWeight, lfItalic
if (m_Bold)
LF.lfWeight = FW_BOLD;
if (m_Italic)
LF.lfItalic = 1;
if (m_Underline)
LF.lfUnderline = 1;
//создать и выбрать шрифт в объекте контекста устройства:
Font.CreateFontIndirect (&LF);
PtrOldFont = dc.SelectObject (&Font);
// задать выравнивание текста:
switch (m_Justify)
{
case JUSTIFY_LEFT:
dc.SetTextAlign (TA_LEFT);
X = m_RectSample.left + 5;
break;
case JUSTIFY_CENTER:
dc.SetTextAlign (TA_CENTER);
X = (m_RectSample.left + m_RectSample.right) / 2;
break;
case JUSTIFY_RIGHT:
dc.SetTextAlign (TA_RIGHT);
X = m_RectSample.right - 5;
break;
}
// установить режим отображения фона:
dc.SetBkMode (TRANSPARENT);
// вывести строки текста:
LineHeight = LF.lfHeight * m_Spacing;
Y = m_RectSample.top + 15;
dc.TextOut (X, Y, "AaBbCdDdEeFf");
Y += LineHeight;
dc.TextOut (X, Y, "GhHhIiJjKkLl");
Y += LineHeight;
dc.TextOut (X, Y, "MmNnOoPpQqRr");
// отменить выбор шрифта:
dc.SelectObject (PtrOldFont);
}
24. Сохраните изменения, постройте программу и протестируйте ее.
Вы получите главное окно, в котором не отображается диалоговое окно и, значит, не демонстрируются действия обработчиков сообщений от элементов управления. Ниже приводится таблица соответствия идентификаторов элементов управления и функций-обработчиков сообщений, генерируемых этими элементами управления.
Т а б л и ц а 6.7