Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
65-96.doc
Скачиваний:
5
Добавлен:
11.11.2019
Размер:
340.99 Кб
Скачать

Создание средств прокрутки окна

Если класс представления породить от класса CScrollView, то автоматически добавляются в окно представления полосы прокрутки, и предоставляется часть кода для поддержки операций прокрутки. Подключение полос прокрутки к окну представления осуществляется классом CScrollView. Функции-члены класса CScrollView обрабатывают сообщения WM_HSCROLL и WM_VSCROLL, которые полосы прокрутки посылают объекту представления. Эти функции перемещают область вывода внутри окна и поддерживают масштабирование изображения по размеру окна, определяют режим преобразования и точку начала координат окна представления и выполняют другие действия. Класс CScrollView поддерживает управление прокруткой с помощью мыши и не поддерживает прокрутку с помощью клавиатуры. Разработчику необходимо добавлять поддержку прокрутки с помощью клавиатуры самостоятельно.

Рис. 4.1. Полосы прокрутки програмы MyPaint

Преобразование координат

Рассмотрим более подробно способ поддержки прокрутки в классе CScrollView. Когда документ открывается впервые, левый верхний угол рисунка отображается в левом верхнем углу окна представления. Однако при прокрутке документа с помощью полосы прокрутки MFC корректирует значение атрибута, называемого началом области просмотра.

Начало области просмотра определяет положение текста или графики относительно окна. Обычно точка с координатами (0, 0) находится в левом верхнем углу окна представления, а точка с координатами (100, 180) — на расстоянии 100 пикселов от левого края окна и 180 пикселов от его верхнего края (рис. 4.2).

Рис. 4.2. Окно представления до прокрутки

Если прокрутить документ вниз на 40 пикселов, то MFC скорректирует начало области просмотра так, что обе точки появятся в окне на более высоких позициях. Точка с координатами (0, 0) не будет видна (все, что выводится за пределами окна, отсекается), а точка с координатами (100, 180) будет выведена на расстоянии 180 – 40 = 140 пикселов от верхней границы окна. На рис. 4.3 показано окно представления после прокрутки.

После того как MFC скорректирует начало области просмотра, функция CMуPaintView::OnDraw() перерисует линии в окне представления, задавая те же координаты для каждой линии. Линии будут выведены с учетом прокрутки в результате изменения начала области просмотра. Привлекательность такой системы состоит в том, что не нужно модифицировать функцию CMуPaintView::OnDraw() для работы с полосами прокрутки, операции прокрутки реализуются автоматически.

Координаты, заданные при рисовании объекта, называют логическими координатами (logical coordinates). Фактические координаты объекта внутри окна называют координатами устройства (device coordinates). На рис. 4.3 показано их различие. Так, логические координаты отмеченной точки рисунка имеют значение (100, 180), координаты устройства с учетом прокрутки на 40 пикселов вниз составляют (100, 140). Все координаты, передаваемые функциям рисования MFC, например, CDC::MoveTo() и CDC::LineTo(), являются логическими координатами. Такие координаты, как позиции курсора мыши, передаваемые обработчикам сообщений мыши, являются координатами устройства.

Рис. 4.3. Окно представления после прокрутки

До момента добавления к программе средств прокрутки логические координаты совпадали с координатами устройства. После добавления средств прокрутки необходимо внести изменения, позволяющие преобразовывать логические координаты в координаты устройства и наоборот. Так, координаты курсора мыши, переданные обработчику сообщения мыши, необходимо преобразовать из фактических (координат устройства) в логические, поскольку эти координаты передаются функциям рисования. В противном случае линия рисунка может отображаться неправильно.

Чтобы преобразовать координаты устройства в логические, необходимо использовать контекст устройства, который связан с данным окном. Объект контекста устройства (device context — DC) управляет выводом информации в окно, сохраняет атрибуты режима рисования и предоставляет функции для отображения текста или графики посредством структуры данных GDI (Graphic Device Interface —графический интерфейс устройства). В объекте контекста устройства хранятся такие графические объекты, как перья для отображения линий, кисти для заливки фона, шрифт для отображения текста, рисунки для копирования, палитра для определения возможных цветов и область отсечения. Начало области просмотра является одним из атрибутов рисунка, сохраняемых в объекте контекста устройства.

Базовым классом контекстов устройств является класс CDC, от которого порождаются другие классы контекстов устройств. Класс CClientDC, управляет контекстом дисплея, связанным с клиентской (рабочей) областью окна. Для вывода информации в клиентскую область окна необходимо создать объект контекста устройства окна представления с помощью конструктора класса CClientDC(). Аргументом конструктора является указатель на объект класса главного окна CWnd, которому принадлежит объект CClientDC. Для активного окна аргументом является значение this. Напомним, что указатель this указывает на объект, для которого вызывается функция-член класса, а выражение (*this) используется, чтобы получить текущий объект. Другие классы контекстов устройств, производные от CDC, будут рассмотрены ниже.

Перед выводом данных на экран MFC вызывает виртуальную функцию CView::OnPrepareDC(), которую пользователи переопределяют для обеспечения вывода данных на принтер. В нашем случае функция OnPrepareDC() наследуется классом CScrollView и корректирует начало области просмотра на основании текущей позиции прокрученного рисунка. Пользователю не нужно заботиться о явном вызове этой функции перед вызовом OnDraw(). Из любого другого обработчика сообщений, использующего контекст устройства окна представления, например, из OnLButtonDown() или OnMouseMove() функцию OnPrepareDC()придется вызывать явно. Прототип функции такой:

virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL );

Параметры: pDC — контекст устройства, связанный с клиентской областью окна, pInfo = NULL при выводе данных на экран.

Получив контекст устройства и определив начало области просмотра, можно преобразовать координаты устройства в логические координаты, которые будут переданы функциям рисования. Для этого используется функция CDC::DPtoLP(), которой передаются координаты курсора мыши в качестве координат устройства. Для преобразования логических координат в координаты устройства используют функцию CDC::LPtoDP(). Преобразования координат выполняют, если используют функции-члены класса контекстов устройств CDC, в которых параметрами являются логические координаты, и функции-члены класса окна CWnd и его производных, в которых параметрами являются координаты устройств. Координаты курсора мыши являются координатами устройства. Область, в которой проверяется попадания курсора мыши, должна задаваться в координатах устройства. Координаты точки изображения, которые должны сохраняться после прокрутки изображения в окне представления, необходимо задавать в логических координатах.

Линии, которые пользователь рисует, перемещая курсор мыши с нажатой левой кнопкой, соединяют две точки, координаты которых являются логическими координатами. Следовательно, в функции-обработчики сообщений мыши необходимо добавить вызов методов CClientDC() определения контекста устройства, CView::OnPrepareDC() определения начала области просмотра, функции CDC::DPtoLP() преобразования координат устройства в логические координаты. Прототипы функций следующие:

void DPtoLP( LPRECT lpRect ) const;

void DPtoLP( LPSIZE lpSize ) const;

Параметры lpRect — указатель на структуру RECT или объект класса CRect; lpSize — указатель на структуру SIZE или объект класса CSize.

Структура RECT (класс CRect) определяет координаты левого верхнего и правого нижнего угла прямоугольника, имеет такое объявление.

typedef struct tagRECT {   LONG left;   LONG top;   LONG right;   LONG bottom; } RECT;

Структура SIZE (класс CSize) определяет ширину и высоту прямоугольника и имеет такой формат.

typedef struct tagSIZE {    int cx;    int cy; } SIZE;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]