Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VC_Lect.doc
Скачиваний:
6
Добавлен:
01.07.2025
Размер:
15 Мб
Скачать
☆

8.7.Управление gdi-объектами

Итак, Вы знаете, что GDI-объекты нужно удалять, предварительно отсоединив от контекста устройства. Как же это сделать? Функции семейства CDC::SelectObject() выбирают объект GDI в контекст устройства и возвращают указатель на объект, который был выбран в контекст до этого (и теперь отсоединен). Но возникает проблема: нельзя отсоединить старый объект, не выбрав в контекст новый. Простое решение — «сохранить» первоначальный GDI-объект при выборе своего объекта в контекст и восстановить его по завершении работы. После этого Вы можете удалить свой GDI-объект. Пример приведен ниже:

void CMyView::OnDraw(CDC* pDC)

{

CPen newPen(PS_DASHDOTDOT, 2, (COLORREF) 0); /* создание нового

объекта: черное перо шириной 2 пиксела*/

CPen* pOldPen = pDC->SelectObject(&newPen); /* выбираем новое перо

в контекст и запоминаем старое */

pDC->MoveTo(10, 10);

pDC->Lineto(110, 10);

pDC->SelectObject(pOldPen); // newPen освобождается

} // newPen автоматически уничтожается при выходе

При уничтожении контекста устройства все его GDI-объекты отсоединяются. Таким образом, если известно, что контекст устройства будет уничтожен до того, как будут уничтожены выбранные в него объекты, отсоединять эти объекты не нужно. Например, если Вы объявили перо как переменную-член класса «вид» (и инициализировали его при инициализации объекта «вид»), то не надо отсоединять перо внутри OnDraw(): контекст устройства, временем жизни которого управляет обработчик OnPaint() в базовом классе, будет уничтожен раньше.

8.8.Стандартные gdi-объекты

Windows предоставляет Вам ряд стандартных GDI-объектов (stock GDI objects). Так как эти объекты — часть Windows, заботиться об их удалении не нужно (Windows игнорирует запросы на удаление стандартных объектов). Функция библиотеки MFC CDC::SelectStockObject() выбирает стандартный объект в контекст устройства и возвращает указатель на выбранный ранее объект, который отсоединяется от контекста. Стандартные объекты удобны, когда Вам нужно отсоединить свой собственный нестандартный перед его удалением. Стандартный объект можно применять вместо «старого» объекта, который использовался в предыдущем примере:

void CMyView::OnDraw(CDC* pDC)

{

CPen newPen(PS_DASHDOTDOT, 2, (COLORREF) 0); /* черное перо

шириной 2 пиксела*/

pDC->SelectObject(&newPen);

pDC->MoveTo(10, 10);

pDC->Lineto(110, 10);

pDC->SelectStockObject(BLACK_PEN); // newPen отсоединяется

} // newPen автоматически уничтожается при выходе

Стандартные перья, шрифты и палитры перечислены в описании функции CDC::SelectStockObject() в MSDN.

8.9.Время жизни контекста устройства

В случае контекста устройства «дисплей» в начале каждой функции-обработчика сообщения Вы получаете «свежий» контекст. Набор выбранных объектов (а также режим преобразования координат и другие параметры контекста) теряется после завершения работы функции. Таким образом, контекст устройства необходимо всякий раз настраивать заново. Виртуальная функция-член OnPrepareDC класса CView удобна для установки режима преобразования координат, но своими GDI-объектами Вы управляете сами.

Для других контекстов устройств, таких, как принтеры или буферы памяти, назначенные Вами параметры могут сохраняться дольше. С этими долгоживущими контекстами устройств возникают сложности из-за временной природы указателей на С++ оъекты GDI, которые возвращаются функцией SelectObject. (Временный «объект» будет удален каркасом приложения во время обработки цикла простоя приложения, некоторое время спустя после возврата управления обработчиком.) Вы не можете просто сохранить указатель в переменной-члене класса — вместо этого его необходимо преобразовать в описатель Windows (единственный постоянный идентификатор GDI-объекта) с помощью функции-члена GetSafeHandle. Пример приведен ниже:

// m_pPrintFont указывает на объект CFont, созданный в конструкторе CMyView

// m_hOldFont – переменная-член CMyView типа HFONT, инициализированная 0

void CMyView::SwitchToCourier(CDC* pDC)

{

m_pPrintFont->CreateFont(30, 10, 0, 0, 400, FALSE, FALSE,

0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,

CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,

DEFAULT_PITCH | FF_MODERN,

"Courier New"); // TrueType

CFont* pOldFont = pDC->SelectObject(m_pPrintFont);

//m_hOldFont – переменная-член типа HFONT, в которой хранится указатель

m_hOldFont = (HFONT) pOldFont->GetSafeHandle();

}

void CMyView:SwitchToOriginalFont(CDC* pDC)

{

// FromHandle – статическая функция-член, возвращающая

// указатель на объект

if (m_hOldFont) {

pDC->SelectObject(CFont::FromHandle(m_hOldFont));

}

}

// m_pPrintFont удаляется в деструкторе CMyView

Примечание. Будьте осторожны при удалении объекта, указатель на который возвращает SelectObject. Если Вы создали этот объект сами, то имеете право удалить его. Если же указатель временный, что бывает с объектами, первоначально выбранными в контекст устройства, то объект удалять нельзя.

9.Виды приложений, создаваемые с помощью мастеров Visual C++

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