На этом шаге мы рассмотрим общие положения, связанные в выводом информации на различные устройства.
На этом шаге мы расскажем, какие возможности отображения данных на устройства вывода - экран и принтер - предоставляет класс CView.
В Windows приложения и устройства вывода взаимодействуют п другом посредством интерфейса графических устройств (Graphics Device Interface, GDI). Его использование гарантирует правильный вывод на все GDI-совместимые устройства.
GDI управляет структурой данных, называемой контекстом устройства, которая содержит информацию о текущих атрибутах данного устройства. В нее можно включить информацию о цветовой палитре, шрифтах, толщине пера, рисующего линии, типе кисти, закрашивающей области. В Windows API есть GDI-функции для рисования линий и других геометрических фигур, для закрашивания областей и печати текста. Все эти функции осуществляют вывод на контекст устройства, описатель которого передается в качестве параметра.
В MFC контекст устройства и многие функции GDI инкапсулирует класс CDC. В нем представлены функции создания и инициализации контекста устройства, а также функции рисования. Помимо класса CDC существует масса специализированных классов, производных от него (таблица 1).
Класс | Описание |
---|---|
CPaintDC | Инкапсулирует контекст устройства, подготовленный для перерисовки недействительной области окна при получении сообщения WM_PAINT. Конструктор этого класса вызывает функцию CWnd::BeginPaint(), которая создает контекст устройства и подготавливает клиентскую область к графическому выводу. Для очистки памяти из деструктора вызывается функция CWnd::EndPaint() |
CClientDC | Описывает контекст устройства, представляющего клиентскую область окна |
CWindowDC | Инкапсулирует контекст устройства, представляющего все окно вместе с рамкой |
CMetafileDC | Содержит набор структур, хранящих изображение в аппаратно-независимом формате, который необходим при рисовании в метафайл Windows |
Графический вывод данных приложения осуществляется функцией-членом объекта представления OnDraw(). В производном от CView классе, котьорый создал мастер АррWizard, имеется функция-заглушка OnDraw(). К ней можно добавлять свой код для отображения данных. Она выглядит следующим образом:
void CMyAppView::OnDraw(CDC* pDC) { CMyAppDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here }
Обратите внимание на то, что в эту функцию передается указатель на объект CDC. Он необходим для вызова рисующих функций контекста устройства. Кроме того, функция OnDraw() получает указатель на объект документа, который Вы можете использовать для обращения к данным приложения.
Приведем простую реализацию функции OnDraw().
Рис.1. Выбор пункта Add Member Variable
Рис.2. Создание переменной
Рис.3. Выбор конструктора
Рис.4. Добавление строки
CSize TextSize = pDC->GetTextExtent(pDoc->m_string); CRect rect(10,10, 10+TextSize.cx,10+TextSize.cy); rect.InflateRect(4,4); pDC->Rectangle(&rect); pDC->TextOut(10,10,pDoc->m_string);
Рис.5. Функция OnDraw()
Выводы:
Если изменение данных документа может повлиять на их отображение, то представление должно быть перерисовано. Обычно такое происходит при внесении пользователем изменений в представление. При этом код, обновляющий данные документа, должен вызывать функцию-член класса документа UpdateAllViews(), уведомляющую все представления о необходимости перерисовки.
Функция UpdateAllViews() вызывает функцию-член каждого представления OnUpdate(). По умолчанию при этом перерисовывается вся клиентская область представления. Вы можете переопределить эту функцию так, что перерисовываться будут только те части окна, в которых произошло изменение.
Когда представление становится недействительным, Windоws сылает ему сообщение WM_PAINT. Обработчик этого cooбщения OnPaint() создает контекст устройства на основе класса CPaintDC и передает его в функцию OnDraw().
В программировании для Windows практически не существует разницы между выводом на экран и на принтер, потому что GDI - аппаратно-независимый интерфейс. Одни и те же функции могут использоваться для отображения на экран и для печати на принтер в зависимости от контекста устройства. Если объект класса CDC, который получает функция OnDraw(), представляет принтер, то и вывод выполняется на него.
Библиотека MFC позволяет осуществить печать документа. Каркас приложения сам отображает диалоговое окно Print и создает контекст устройства для принтера. При выборе пункта Print в меню File представление передает этот контекст устройства в функцию OnDraw(), которая и осуществляет вывод.
Рис.6. Вызов каркасом приложения функции OnDraw()
Однако между выводом на принтер и на экран есть существенные различия. При печати документ должен быть разделен на страницы, поэтому Вам необходимо знать размер листа бумаги. Кроме того важна на ориентация листа (книжная или альбомная). Для этого в классе CView предусмотрены специальные функции.
На следующем шаге мы рассмотрим конкретный пример приложения в архитектуре "документ/вид".