Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

BOOL CEMF::Load(const char *szFileName) {

 UINT uiSig;

 // Сохранить имя файла.

 m_szPathName = szFileName;

 // Проверить сигнатуру

 CFile cfEMF;

 cfEMF.Open(m_szPathName, CFile::modeRead | CFile::shareDenyWrite);

 cfEMF.Read(&uiSig, sizeof(UINT));

 cfEMF.Close;

 // Если это EMF, получить его дескриптор.

 if (uiSig == EMR_HEADER) {

m_hemf = GetEnhMetaFile(m_szPathName);

GetEMFCoolStuff;

LoadPalette;

 } else m_hemf = NULL;

 // Возвращаем результат.

 return ((m_hemf) ? TRUE : FALSE);

}

Функция Draw вызывается из функции OnDraw класса представления. Особо интересного там ничего не происходит. Если есть палитра, на что указывает не равное NULL значение переменной-члена m_hPal, палитра выбирается в контекст устройства (DC). Я был сильно озадачен, когда узнал что CDC::SelectPalette требует указатель на объект типа CPalette. Но я был так же заинтригован, когда вдруг обнаружил функцию CPalette::FromHandle. Я мог легко преобразовать дескриптор палитры в объект типа CPalette. Далее это было уже просто делом воспроизведения метафайла с помощью CDC::PlayMetaFile.

BOOL CEMF::Draw(CDC *pdc, RECT *pRect) {

 ASSERT(m_hemf);

 BOOL fRet = FALSE;

 CRect crect;

 CPalette cpalOld = NULL;

 if (m_hemf) {

if (m_hPal) {

CPalette cpal;

if ((cpalOld = pdc->SelectPalette(cpal.FromHandle(m_hPal), FALSE))) pdc->RealizePalette;

}

fRet = pdc->PlayMetaFile(m_hemf, pRect);

if (cpalOld) pdc->SelectPalette(cpalOld, FALSE);

 }

 return (fRet);

}

Что же еще находится в классе CEMF? Как я упоминал выше, есть две закрытых (private) функции, которые управляются с палитрой и заголовком. Я их не буду обсуждать в этой статье, кому интересно см. статьи "Enhanced Metafiles in Win32" и "EMFDCODE.EXE: An Enhanced Metafile Decoding Utility", обе доступны в MSDN. Конечно, вы вероятно захотите также взглянуть на файлы CEMF.CPP и CEMF.H программы METAVIEW, приложенной к статье! Если вы захотите сделать из этого класса что-либо серьезное, предлагаю добавить следующую дополнительную функциональность: возможность делать нумерованые последовательности метафайлов и работать с метафайлами, содержащимися в буфере обмена. Опять же, эти темы описываются в вышеупомянутых статьях.

Отображение документа

Если я понял Найджела правильно, задача состояла в том, чтобы отображать документ тремя различными способами. Во-первых, как картинку в дочернем окне; потом, в виде текста описывающего заголовок метафайла (тоже в дочернем окне), и, наконец, как картинку в окне предварительного просмотра. К тому же, два представления в дочерних окнах нужно было реализовать через архитектуру многодокументного интерфейса (MDI) предоставленную MFC. Рассмотрим каждую из этих задач по отдельности.

Вывод изображения в дочернем окне

Здесь никаких проблем. Надо просто вызвать функцию-член Draw из класса CEMF. Посмотрите поближе на функцию OnDraw в файле METAVVW.CPP.

void CMetavw1View::OnDraw(CDC* pDC) {

 CMetavw1Doc* pDoc = GetDocument;

 // Флаг для предотвращения рисования во время

 // изменения размера окна, см. OnSize и FullDragOn в этом модуле.

 if (m_fDraw) {

// Если мы печатаем или находимся в режиме предварительного

// просмотра, рабочий прямоугольник узнается из CPrintInfo в OnPreparePrinting

if (pDC->IsPrinting) {

pDoc->m_cemf.Draw(pDC, &m_rectDraw);

} else {

GetClientRect(&m_rectDraw);

pDoc->m_cemf.Draw(pDC, &m_rectDraw);

}

 }

}

Этот код организован вокруг двух условных операторов о которых стоит сказать отдельно. Первое условие является тестом типа "все-или-ничего". Если m_fDraw равно FALSE, не делается никакой попытки что-то нарисовать. Так что же означает m_fDraw? Ну, это мой хитрый прием №2, и я скоро к нему вернусь. Второе условие проверяет ведется ли отрисовка на принтер (или предварительный просмотр) или в дочернее окно. Член-функция IsPrinting класса CDC – это встроенная (inline) функция, которая возвращает public-переменную CDC::m_bPrinting. Раньше, прежде чем воспользоваться этой функцией, я проверял m_bPrinting напрямую. Когда я обнаружил функцию IsPrinting, это меня озадачило. Ведь эта функция просто возвращала значение m_bPrinting и все. Но похоже это больше в духе C++. Если название переменной m_bPrinting в будущем изменилось бы, мой код перестал бы работать. Но это все еще меня немного беспокоит. Как-никак, а я бывал достаточно сообразителен, чтобы при необходимости залезать в отладчик, прослеживать за несколькими переменными и затем придумывать способ получения желаемого результата. И это приводит меня к моей первой (и возможно последней) гипотезе: инкапсуляция и сокрытие данных могут мстить за чрезмерный энтузиазм.

  • Читать дальше
  • 1
  • ...
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: