Практика работы в среде визуального программирования
Начало работы в Visual C++
Вывод текста в окно программы
Создадим программу, которая будет считать символы с клавиатуры и отображать их в клиентском окне. Для этого будем обрабатывать сообщение Windows WM_CHAR. Свяжем с ним функцию OnChar(UINT nChar, UINT nRepCnt, UINT nFlags ). Назовем программу Key. Будем создавать ее с помощью MFC Application Wizard, интерфейс SDI (Single Document Interface).
Этапы написания программы
- буфер под хранение полученных символов.
- Организовать чтение символов с клавиатуры.
- Сохранить символы в документе.
- Отобразить текст.
1. Подготовка буфера для хранения символов
Определим в классе CKeyDoc, прототип которого содержится в заголовочном файле KeyDoc.h, строку-объект StringData класса MFC CString. Для этого добавим следующий код:
class CKeyDoc : public CDocument { …… DECLARE DYNCREATE(CKeyDoc) Public: CString StringData; …… };
Проинициализируем переменную пустой строкой " ". Это делается в конструкторе объекта документа, расположенном в файле KeyDoc.cpp. Конструктор объекта документа CKeyDoc:
CKeyDoc::CKeyDoc() { // TODO: StringData=""; }
2. Чтение символов с клавиатуры
При нажатии клавиши Windows посылает сообщение WM_CHAR. Его надо связать с методом OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) объекта вида. Для этого используем утилиту Class View
- Вызовем контекстное меню класса CKeyView (нажмем правой кнопкой по имени класса в окне утилиты Class View ) выберем пункт Properties.
- Во всплывшем окне свойств нажмем на кнопку Messages.
- Выбираем в списке сообщений WM_CHAR. Раскрываем список действий в пустом поле напротив названия сообщения нажатием левой кнопкой мыши. Выбираем единственный вариант <Add> OnChar. Мастер автоматически создаст обработчик OnChar и откроет файл KeyView.cpp для редактирования тела метода.
3. Сохранение символа в документе
Введенный символ находится в параметре nChar и его необходимо сохранить в строковом объекте StringData. Обработчик OnChar:
void CKeyView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CKeyDoc *pDoc = GetDocument(); //Получение указателя на объект документа ASSERT_VALID(pDoc); //Проверка указателя if(!pDoc) return; pDoc->StringData += char(nChar); //Обновление строки символов Invalidate(); //Вызов метода OnDraw }
Макрос ASSERT_VALID проверяет, что полученный указатель действительно ссылается на документ (иначе ошибка).
4. Отображение текста
Вывод будем осуществлять в методе OnDraw(CDC* pDC) класса вида. Для вызова метода OnDraw используется функция Invalidate. Метод OnDraw:
void CKeyView::OnDraw(CDC *pDC) { … pDC->TextOut(0,0,pDoc->StringData); }
Скомпилируем и запустим программу. Усложним задачу. Потребуем, чтобы текст выводился в центре клиентской области окна. Для решения поставленной задачи изменим метод OnDraw. Измененный метод OnDraw:
void CKeyView::OnDraw(CDC* pDC) { CKeyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CRect rect; //Переменная для хранения размеров клиентской области GetWindowRect(&rect); //Получение размеров клиентской области int x=rect.Width()/2; //Задание координаты X центра клиентской области int y=rect.Height()/2; //Задание координаты Y центра клиентской области CSize size = pDC->GetTextExtent(pDoc->StringData); //Определение размеров выводимой строки в пикселях x -= size.cx/2; //Сдвиг координаты X на половину длины выводимой строки влево y -= size.cy/2; //Сдвиг координаты Y на половину высоты выводимой строки вверх pDC->TextOut(x,y,pDoc->StringData); //Вывод строки в центр клиентской области }
Работа с курсором и мышью
Напишем программу, которая будет создавать курсор, в выбранной произвольной точке клиентской области и выводить текст с указанной позиции. Создадим SDI программу под названием Mouse. Воспользуемся материалом предыдущего пункта: создадим обработчик сообщения WM_CHAR. Чтобы создать курсор, необходимо знать его размеры (обычно высота равна высоте символа, а ширина 1/8 ширины символа). Курсор будем создавать в методе OnDraw. Чтобы определить размеры курсора, необходимо получить данные из структуры TEXTMETRIC. Для этого необходимо создать объект типа TEXTMETRIC и заполнить его поля, используя метод GetTextMetrics(&tm) . Но сначала добавим в прототип класса CMouseView следующие переменные
void CMouseView::OnDraw(CDC* pDC) { CMouseDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; TEXTMETRIC textmetric; //Переменная для хранения информации о шрифте pDC->GetTextMetrics(&textmetric); //Получение информации о шрифте CSize size=pDC->GetTextExtent(pDoc->StringData); //Получение размеров выводимой строки в пикселях CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight); //Создаём курсор CaretPosition.x=size.cx; //Присваивание x корд. конца CaretPosition.y=0; //Присваивание y корд. SetCaretPos(CaretPosition); //Задаем позицию курсора ShowCaret(); //Вывод на экран курсора pDC->TextOut(0,0,pDoc->StringData); }
Рассмотрим задачу вывода строки с места, на который указывает указатель мыши. Свяжем сообщение WM_LBUTTONDOWN с методом OnLButtonDown(UINT nFlags, CPoint point) . Параметр Cpoint (объект класса CPoint) содержит текущие координаты указателя мыши. Для очистки строкового объекта используется метод Empty() класса CString. Обработчик нажатия левой кнопки мыши OnLButtonDown:
void CMouseView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default x=point.x; //Запоминаем координату X места где была нажата левая кнопка мыши y=point.y; //Запоминаем координату Y места где была нажата левая кнопка мыши CMouseDoc* pDoc = GetDocument(); //Получаем указатель на объект документа ASSERT_VALID(pDoc); //Проверяем правильность указателя pDoc->StringData.Empty(); //Очищаем выводимую строку Invalidate(); //Вызываем OnDraw CView::OnLButtonDown(nFlags, point); }
В методе класса OnDraw сделаем изменения:
CaretPosition.x=x+size.cx; //Присваивание x корд. конца CaretPosition.y=y; …… pDC->TextOut(x,y,pDoc->StringData);
Скомпилируем и запустим приложение.