- •Задание 3. Создание кода, отображающего текст
- •Задание 4. Использование стандартных шрифтов
- •Задание 5. Поддержка средств прокрутки
- •Подведение итогов
- •Глава 9. Ввод текста
- •Чтение кодов управляющих клавиш и управление полосой прокрутки
- •Виртуальные коды клавиш, которые не генерируют сообщения wm_char
- •Задание 1. Обработка сообщения wm_keydown
- •Чтение кодов символьных клавиш и отображение символов
- •Наиболее часто используемые управляющие клавиши
- •Задание 2. Обработка сообщения wm_char
Задание 4. Использование стандартных шрифтов
Стандартным называется шрифт, который входит в число типовых шрифтов Windows, применяемых для отображения информации в диалоговых и информационных окнах.
Для модификации программы выполните следующие действия.
Создайте ресурс шаблона диалогового окна аналогично рис. 8.10 для выбора стандартного шрифта в диалоговом окне. Для этого выполните команду ProjectAdd Resource…. В окне Add Resource выберите тип ресурса Dialog и нажмите кнопку New. В окне Properties измените идентификатор ресурса шаблона диалогового окна, введя в поле ID значение IDD_SELECTSTDFONT, а в поле Caption — Selection standard font.
Рис. 8.10. Диалоговое окно выбора стандартного шрифта в программе TextDemo
Создайте элементы управления в шаблоне диалогового окна. Выберите на панели инструментов Toolbox элемент Static Text и поместите его в шаблон диалогового окна, щелкнув мышью в его верхней части. В окне Properties в поле Caption укажите надпись Select standard font. Выберите элемент управления Combo Box. Нажав левую кнопку мыши в позиции расположения этого элемента и не отпуская ее, отбуксируйте край появившейся рамки в нужном направлении. Элемент управления Combo Box включает выпадающий вниз список, поэтому отображаемый при перемещении мыши прямоугольник должен быть вытянутым вниз. В окне Properties в поле ID введите идентификатор IDC_STDFONT.
Рис. 8.11. Меню программы TextDemo после добавления команды Standard Font
Для выравнивания элементов управления по центру выделите их и выполните команду FormatCenter in DialogHorizontal.
Добавьте в меню программы TextDemo команду вызова диалогового окна Selection standard font. Для этого в окне Resource View дважды щелкните на идентификаторе меню IDR_MAINFRAME. В окне редактора ресурса меню добавьте новую команду в меню Options, вставив ее после команду Font…. В окне Properties в поле Caption введите надпись &Standard Font…, в поле ID — идентификатор ID_OPTIONS_STANDARDFONT. Полученное меню представлено на рис. 8.11.
Создайте класс диалогового окна, управляющий работой элементов управления при выборе стандартного шрифта. Для добавления нового класса в программу TextDemo откройте окно Class View. Выполните команду Add Class… В группе Templates (Шаблоны) выберите шаблон MFC Class и нажмите кнопку Open. В окне MFC Class Wizard установите такие значения: в поле Class name — имя класса CStandardFontDlg, в поле Base Class — имя базового класса CDialog, значения остальных полей оставьте без изменения (рис. 8.12).
Рис. 8.12. Окно MFC Class Wizard в процессе добавления класса CStandardFontDlg
Для управления диалоговым окном Selection standard font элементам управления необходимо поставить в соответствие переменные-члены класса диалогового окна. Выполните команду AddAdd Variable…, вызвав ее в контекстном меню класса CStandardFontDlg. В диалоговом окне Add Member Variable Wizard (рис. 8.13) введите в поле Variable type значение CString, в поле Variable name — значение m_KindFont, установите флажок Control variable, в поле Control ID выберите значение IDC_STDFONT, в поле Category — значение Value. Нажмите кнопку Finish для окончания работы с диалоговым окном. Переменная m_KindFont будет сохранять значение, выбранное в поле со списком, и использовать его для обмена данными между полем со списком диалогового окна и оперативной памятью. Повторите описанные действия для добавления в класс CStandardFontDlg переменной nIndex типа int. Эта переменная является индексом шрифта, ее значение будет передаваться в функцию выбора стандартного шрифта из набора типовых шрифтов.
void CStandardFontDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_CBString(pDX, IDC_STDFONT, m_KindFont); }
Рис. 8.13. Окно Add Member Variable Wizard в процессе добавления переменной m_KindFont, связанной с элементом управления IDC_STDFONT
Для обработки уведомляющих сообщений, посылаемых элементами управления своему окну-владельцу, добавьте в класс CStandardFontDlg функцию-обработчик сообщения, генерируемого в результате выбора значения в поле со списком. Для этого выделите класс CStandardFontDlg в окне Class View. Затем откройте окно Properties. Щелкните на кнопку Events. В появившемся списке идентификаторов сообщений выберите IDC_STDFONT и разверните список типов сообщений, выберите значение CBN_SELCHANGE и выполните команду <Add> OnCbnSelchangeStdfont. Для упрощения вызова функции мы заменили ее имя значением CStandardFontDlg::OnSelChangeCombo().
BEGIN_MESSAGE_MAP(CStandardFontDlg, CDialog) ON_CBN_SELCHANGE(IDC_STDFONT, OnSelChangeCombo) END_MESSAGE_MAP()
В окне редактора кода функции OnInitDialog()класса CStandardFontDlg добавьте операторы, которые выполняют такие действия: определяют указатель на элемент IDC_STDFONT (поле со списком), получают индекс выбранной строки в поле со списком, устанавливают значение индекса шрифта в зависимости от выбранного значения в поле со списком. Для этой цели используются функции CWnd::GetDlgItem() и ССomboBox::GetCurSel(). Локальная переменная index типа int определяет индекс строки в комбинированном списке. Добавленные операторы выделены полужирным шрифтом в приведенном ниже фрагменте кода.
void CStandardFontDlg::OnSelChangeCombo() { // TODO: Add your control notification handler code here CComboBox *p_combo=(CComboBox*)GetDlgItem(IDC_STDFONT); int index=p_combo->GetCurSel(); if (index==0) nIndex=ANSI_FIXED_FONT; if (index==1) nIndex=ANSI_VAR_FONT; if (index==2) nIndex=DEVICE_DEFAULT_FONT; if (index==3) nIndex=OEM_FIXED_FONT; if (index==4) nIndex=SYSTEM_FIXED_FONT; if (index==5) nIndex=SYSTEM_FONT; }
Перед отображением диалогового окна его элементы управления инициализируют с помощью функции OnInitDialog() класса CStandardFontDlg. Для добавления этой виртуальной функции откройте окно Properties для класса CStandardFontDlg. Выполните команду <Add> OnInitDialog, предварительно развернув список виртуальных функций, нажав кнопку Overrides. Добавьте операторы формирования выпадающего списка элемента управления, используя функцию CComboBox::AddString(). По умолчанию список будет отображаться отсортированным по алфавиту, независимо от порядка добавления строк в него (рис. 8.14).
Рис. 8.14. Диалоговое окно выбора индекса стандартного шрифта во время работы программы TextDemo
BOOL CStandardFontDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here CComboBox *p_combo=(CComboBox*)GetDlgItem(IDC_STDFONT); p_combo->AddString("SYSTEM_FONT"); p_combo->AddString("SYSTEM_FIXED_FONT"); p_combo->AddString("ANSI_VAR_FONT"); p_combo->AddString("ANSI_FIXED_FONT"); p_combo->AddString("DEVICE_DEFAULT_FONT"); p_combo->AddString("OEM_FIXED_FONT"); return TRUE; // return TRUE unless you set the focus to a //control // EXCEPTION: OCX Property Pages should return FALSE }
Рис. 8.15. Окно Event Handler Wizard в процессе добавления обработчика командного сообщения
В класс документа необходимо добавить обработчик командного сообщения, вызванного выбором команды меню Standard Font….. Откройте окно редактора ресурса меню, дважды щелкнув на имени идентификатора меню IDR_MAINFRAME. Вызовите контекстное меню для команды Standard Font….. Выполните команду Add Event Handler. В диалоговом окне Event Handler Wizard мастер уже предложил вам тип сообщения и имя функции. Выберите класс CTextDemoDoc (рис. 8.15) и нажмите кнопку Add and Edit. Как вы помните, при добавлении обработчиков командных сообщений генерируется макрос ON_COMMAND(), прототип и шаблон соответствующей функции.
BEGIN_MESSAGE_MAP(CTextDemoDoc, CDocument) ON_COMMAND(ID_OPTIONS_FONT, OnOptionsFont) ON_COMMAND(ID_OPTIONS_STANDARDFONT, OnOptionsStandardFont) END_MESSAGE_MAP()
Перед добавлением кода, реализующего обработку командного сообщения, необходимо инкапсулировать в класс CTextDemoDoc некоторые переменные. Добавьте объект m_StdFontDlg класса CStandardFontDlg диалогового окна для его последующего отображения. Используйте диалоговое окно Add Member Variable Wizard. Аналогично добавьте переменную m_Text типа CString для формирования отображаемого в окне представления текста. Значение переменной m_IndexStdFont типа int будет передаваться в качестве аргумента в функцию выбора стандартного шрифта. Этой переменной будет присваиваться значение, полученное из диалогового окна выбора индекса стандартного шрифта. Отображение данных документа в программе TextDemo выполняется с помощью функции CTextDemoView::OnDraw(), в которой осуществляется выбор типа диалогового окна для выбора шрифта. Для того, чтобы иметь возможность управлять процессом выбора вариантов отображения текста, введите дополнительную переменную flag типа int. Эта переменная будет принимать значение, равное 1 в случае вызова диалогового окна Font и значение 2, если выбирается стандартный шрифт. Добавленный код демонстрируется полужирным шрифтом в приведенном фрагменте кода.
class CTextDemoDoc : public CDocument { protected: // create from serialization only CTextDemoDoc(); DECLARE_DYNCREATE(CTextDemoDoc) // Overrides public: virtual BOOL OnNewDocument(); virtual void Serialize(CArchive& ar); // Implementation public: virtual ~CTextDemoDoc(); virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; // Generated message map functions protected: DECLARE_MESSAGE_MAP() public: afx_msg void OnOptionsFont();//обработчик команды меню Font COLORREF m_Color;//цвет текста CString m_LineTable[NUMLINES]; //текст, выводимый в окно CFont m_Font;//объект шрифта afx_msg void OnOptionsStandardFont();//обработчик команды //меню Standard Font... CStandardFontDlg m_StdFontDlg; //объект диалогового окна CString m_Text; //отображаемый в окне представления текст int m_IndexStdFont; //индекс стандартного шрифта, полученный //из диалогового окна int flag; //флаг выбора типа диалогового окна: };
В результате выбора команды Standard Font... в меню программы TextDemo должно появиться диалоговое окно выбора стандартного шрифта. Закрытие диалогового окна должно привести к появлению текста, отображенного выбранным шрифтом в окне представления. Создание требуемого текста должно происходить после выбора индекса стандартного шрифта в диалоговом окне при его закрытии нажатием кнопки OK. Код, реализующий описанные действия, показан ниже полужирным шрифтом. Вам необходимо ввести его в функцию CTextDemoDoc::OnOptionsStandardFont().
void CTextDemoDoc::OnOptionsStandardFont() { // TODO: Add your command handler code here if(m_StdFontDlg.DoModal()==IDOK) { flag=2; //признак выбора диалогового окна //создание текста для вывода в окно представления m_Text="This is the "+m_StdFontDlg.m_KindFont+" stock font."; m_IndexStdFont = m_StdFontDlg.nIndex; } // перерисовка окна представления UpdateAllViews (NULL); }
Изменения необходимо внести и в функцию-обработчик командного сообщения, генерируемого при выборе из меню команды Font…. Необходимо указать признак открытия диалога Font. Для этого в код функции CTextDemoDoc::OnOptionsFont() добавьте оператор, выделенный полужирным шрифтом в приведенном ниже фрагменте.
void CTextDemoDoc::OnOptionsFont() { // TODO: Add your command handler code her CString str; //переменная для хранения преобразованных в тип // CString значений int Num = 0; //индекс строк текста // отобразите диалоговое окно Font: CFontDialog FontDialog; if (FontDialog.DoModal () != IDOK) return; flag=1; //признак открытия диалогового окна Font // установите значение m_Color: m_Color = FontDialog.GetColor(); //получите цвета, выбранные //пользователем //остальной код функции }
В нашей программе функция CTextDemoView::OnDraw() отображает текст документа, сформированный в обработчике командного сообщения, генерируемого командой ID_OPTIONS_FONT. Необходимо добавить код, который выполняет такие действия: проверяет признак выбора типа диалогового окна (другими словами, фиксирует выбор команды меню); определяет дескриптор CGdiObject::m_hObject, содержащий GDI-объекты; выбирает стандартный шрифт по его индексу; отображает данные документа (созданный в классе документа текст). Если стандартный шрифт в диалоговом окне Selection standard font не был выбран, то выполняется выход из функции отображения шрифта. Если выбрана команда меню Font…, то отображается текст, содержащий атрибуты выбранного шрифта. Добавьте в функцию CTextDemoView::OnDraw() код, выделенный полужирным шрифтом в приведенном ниже фрагменте.
void CTextDemoView::OnDraw(CDC* pDC) { CTextDemoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here RECT ClipRect; int LineHeight; TEXTMETRIC TM; int Y = MARGIN; if (pDoc->flag==2) { HGDIOBJ m_hObject = ::GetStockObject(pDoc->m_IndexStdFont); if (m_hObject == NULL) return; pDC->SelectStockObject(pDoc->m_IndexStdFont); pDC->TextOut (MARGIN, Y,pDoc->m_Text); } else if (pDoc->flag==1) { // возврат, если шрифт еще не был создан: if (pDoc->m_Font.m_hObject == NULL) return; // выберите шрифт в объект контекста устройства: pDC->SelectObject (&pDoc->m_Font); //остальная часть кода не приводится, см. п.7 упражнения 3 } }
Теперь можно сохранить все изменения, построить и запустить программу TextDemo. Протестируйте программу, выбирая в меню команды Font… и Standard Font…. Вы должны получить диалоговое окно, как показано на рис. 8.14. После закрытия диалогового окна щелчком на кнопке OK в окне представления вы увидите текст, как на рис. 8.16.
Рис. 8.16. Окна представления после выбора стандартных шрифтов в программе TextDemo
Программа TextDemo формирует текст, строки которого полностью не помещаются в окно представления. Увеличение размеров главного окна позволяют просмотреть весь текст. Однако, если выбрать большой размер шрифта, то весть текст просмотреть будет невозможно по причине отсутствия полос прокрутки. Добавление средств прокрутки реализуется в задании 5.
