
- •Задание 3. Создание кода, отображающего текст
- •Задание 4. Использование стандартных шрифтов
- •Задание 5. Поддержка средств прокрутки
- •Подведение итогов
- •Глава 9. Ввод текста
- •Чтение кодов управляющих клавиш и управление полосой прокрутки
- •Виртуальные коды клавиш, которые не генерируют сообщения wm_char
- •Задание 1. Обработка сообщения wm_keydown
- •Чтение кодов символьных клавиш и отображение символов
- •Наиболее часто используемые управляющие клавиши
- •Задание 2. Обработка сообщения wm_char
Задание 5. Поддержка средств прокрутки
При генерации программы TextDemo с помощью мастера MFC Application Wizard необходимо указать, что класс представления порождается от класса CScrollView, чтобы окно представления поддерживало средства прокрутки. В этом упражнении вы добавите фрагмент программы, реализующий средства прокрутки.
Удалите виртуальную функцию OnInitialUpdate() класса CTextDemoView, которая вызывается только один раз сразу после запуска программы, поэтому не сможет обновлять объект представления каждый раз, когда меняется объект документа. Для удаления виртуальной функции в окне Class View выберите класс CTextDemoView. Откройте окно Properties. Щелчком на кнопке Overrides разверните список виртуальных функций этого класса. В поле с именем функции OnInitialUpdate разверните список команд и выберите команду <Delete> OnInitialUpdate. Строки кода, относящиеся к функции CTextDemoView::OnInitialUpdate() будут закомментированы.
В процессе работы программы каждый раз при вызове диалогового окна Font будет изменяться документ, что требует обновления его представления. Уведомление о необходимости изменить представление документа формируется функцией UpdateAllViews(NULL) класса CDocument, которая по умолчанию вызывает функцию OnUpdate() класса представления. Следовательно, необходимо добавить функцию CTextDemoView::OnUpdate(). Для ее добавления в класс CTextDemoView повторите действия п. 1, но в поле с именем функции OnUpdate в списке команд выберите команду <Add> OnUpdate.
После выполнения команды <Add> OnUpdate автоматически открывается окно редактора кода добавляемой функции. Удалите комментарии с имен параметров в заголовке функции. Затем добавьте код, который реализует такие действия: определяет указатель на объект документа; создает объект контекста устройства, связанный с клиентской областью окна; выбирает шрифт в объекте контекста устройства; получает метрику текста; вычисляет ширину и высоту текста; устанавливает размеры области прокрутки; прокручивает окно представления к началу документа; объявляет окно представления недействительным для его перерисовки.
void CTextDemoView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { // TODO: Add your specialized code here and/or call the base class CTextDemoDoc* pDoc = GetDocument(); //указатель на документ CClientDC ClientDC (this); //объект контекста устройства int LineWidth = 0; //ширина строки SIZE SizeTotal; //ширина и высота документа TEXTMETRIC TM; //метрика текста //выбор шрифта в объекте контекста устройства ClientDC.SelectObject (&pDoc->m_Font); ClientDC.GetTextMetrics (&TM); //получение метрики текста //ширина прямоугольника с учетом поля отступа SizeTotal.cx = LineWidth + MARGIN; //высота прямоугольника с учетом верхнего поля SizeTotal.cy = (TM.tmHeight + TM.tmExternalLeading) * (NUMLINES + 1) + MARGIN; //установить размер документа SetScrollSizes (MM_TEXT, SizeTotal); //прокрутить окно представления у началу документа ScrollToPosition (CPoint (0, 0)); //объявить недействительным все окно CScrollView::OnUpdate (pSender, lHint, pHint); }
Построив и запустив программу, вы увидите окно с вертикальной полосой прокрутки при отсутствии текста в окне представления. Добавьте в функцию CTextDemoView::OnUpdate() код, который поддерживает средства горизонтальной прокрутки, а в случае отсутствия текста в окне представления полосы прокрутки не отображает. Добавленные операторы должны проверить, выбран ли шрифт в диалоговом окне. Если шрифт не выбран, то необходимо установить нулевой размер документа, при этом полосы прокрутки скрываются. Для обеспечения поддержки горизонтальной прокрутки необходимо вычислить действительную ширину текста путем поиска самой длинной строки в массиве строк. Описанные действия реализуются кодом, который показан полужирным шрифтом ниже.
void CTextDemoView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { //TODO: Add your specialized code here and/or call the base //class CTextDemoDoc* pDoc = GetDocument(); //указатель на документ if (pDoc->m_Font.m_hObject == NULL) // шрифт еще не создан SetScrollSizes (MM_TEXT, CSize (0,0)); else // шрифт создан { CClientDC ClientDC (this); /объект контекста устройства int LineWidth = 0; //ширина строки SIZE SizeTotal; //ширина и высота документа TEXTMETRIC TM; //метрика текста //выбор шрифта в объекте контекста устройства ClientDC.SelectObject (&pDoc->m_Font); ClientDC.GetTextMetrics(&TM); //получение метрики текста //определение ширины текста путем поиска самой длинной строки for (int Line = 0; Line < NUMLINES; ++Line) { //получение ширины и высоты текста с учетом текущего шрифта SizeTotal = ClientDC.GetTextExtent ( pDoc->m_LineTable [Line], //указатель на строку pDoc->m_LineTable [Line].GetLength () //длина строки ); if (SizeTotal.cx > LineWidth) //поиск строки //максимальной ширины (длины) LineWidth = SizeTotal.cx; } //ширина прямоугольника с учетом поля отступа SizeTotal.cx = LineWidth + MARGIN; //высота прямоугольника с учетом верхнего поля SizeTotal.cy = (TM.tmHeight + TM.tmExternalLeading) * (NUMLINES + 1) + MARGIN; //установить размер документа SetScrollSizes (MM_TEXT, SizeTotal); //прокрутить окно представления у началу документа ScrollToPosition (CPoint (0, 0)); } //end of else //объявить недействительным все окно CScrollView::OnUpdate (pSender, lHint, pHint); }
Чтобы завершить эту часть программы, измените заголовок программы аналогично тому, как вы это делали в предыдущих программах. В функцию TextDemoApp::InitInstance() в файле TextDemo.cpp добавьте вызов функции SetWindowText() класса CWnd, в качестве аргумента передайте строку заголовка окна. Добавленный код показан полужирным шрифтом.
BOOL CTextDemoApp::InitInstance() { CWinApp::InitInstance(); // операторы функции не показаны // The one and only window has been initialized, so show and // update it m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); // call DragAcceptFiles only if there's a suffix // In an SDI app, this should occur after ProcessShellCommand m_pMainWnd->SetWindowText("Text Demo"); return TRUE; }
Рис. 8.17. Горизонтальные и вертикальные полосы прокрутки в окне программы TextDemo
Теперь можно построить и запустить программу TextDemo. Выполнив команду меню Font… , выберите шрифт в диалоговом окне. Вы получите окно, которое показано на рис. 8.17.
Разработанные вами версии программы TextDemo не предоставляют возможность вводить символы с клавиатуры, т.е. эту программу нельзя рассматривать как текстовый редактор. В следующем занятии вы узнаете, как воспринимается нажатие клавиш, когда окно программы активно. Выполнив упражнения, вы научитесь редактировать текст.