
- •Управление обменом и проверкой данных
- •Функции класса cWnd для манипулирования элементами управления диалогового окна
- •Связывание методов класса диалогового окна с элементами управления
- •Использование шрифтов в диалоговом окне
- •Некоторые стандартные шрифты Windows
- •Некоторые константы выравнивания текста
- •Задание 2. Создание класса диалогового окна и связывание его методов и атрибутов с элементами управления
- •Задание 3. Определение обработчиков сообщений, генерируемых элементами управления
- •Обработчики сообщения bn_clicked приложения FontDemo
- •Задание 4. Отображение диалогового окна и данных в его элементах управления
- •Задание 5. Отображение текста в окне представления в соответствии с выбранными в диалоговом окне атрибутами
Задание 3. Определение обработчиков сообщений, генерируемых элементами управления
Для определения обработчика сообщений, связанных с открытием диалога, необходимо сгенерировать функцию CFormatDlg::OnInitDialog(), которая получает управление при открытии диалогового окна Format непосредственно перед его отображением. Затем необходимо добавить обработчики сообщений, генерируемых каждым флажком и переключателями. Выполните следующие действия для создания обработчиков сообщений, генерируемых при открытии диалогового окна и его элементами управления.
Добавьте объявление защищенной (protected) переменной m_RectSample типа RECT в класс CFormatDlg, выбрав команду AddAdd Variable контекстного меню класса и заполнив соответствующие поля. Эта переменная определяет координаты рамки Sample в диалоговом окне, в которой будет отображаться образец текста.
Сгенерируйте функцию 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(); };
В функцию 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 }
Добавьте обработчики сообщений, генерируемых каждым флажком и переключателями, которые будут получать управление всякий раз при выборе или отмене выбора элемента управления. Для определения обработчиков сообщений в окне Class View выберите класс CFormatDlg, разверните список идентификаторов сообщений в окне Properties, щелкнув на кнопке Events (События). Для идентификатора IDC_BOLD флажка Bold разверните список сообщений и выберите BN_CLICKED. Для выбранного сообщения выполните команду <Add> OnBnClickedBold (рис. 6.13). В файл FormatDlg.h добавится объявление функции-члена, в файл FormatDlg.cpp — ее определение.
При желании можно скорректировать имя функции, заменив его значением 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()
Для реализации обработчика сообщений, источником которых являются флажки, в функцию 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(); }
Выполните аналогичные действия для добавления обработчиков сообщений, генерируемых флажками 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(); };
В файл 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(); }
Для идентификации положения образца текста в рамке 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 { // объявления атрибутов и методов };
Добавьте обработчики сообщений, генерируемых переключателями 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(); } }
Определите функцию, которая получает управление при изменении содержимого поля 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(); } }
Переопределите функцию 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();
В определение функции 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); }
Сохраните изменения, постройте программу и протестируйте ее.
Вы получите главное окно, в котором не отображается диалоговое окно и, значит, не демонстрируются действия обработчиков сообщений от элементов управления. Ниже приводится таблица соответствия идентификаторов элементов управления и функций-обработчиков сообщений, генерируемых этими элементами управления.
Т а б л и ц а 6.7