Алекс Jenter - Программирование на Visual C++. Архив рассылки

Тут можно читать онлайн Алекс Jenter - Программирование на Visual C++. Архив рассылки - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Программирование на Visual C++. Архив рассылки
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание

Программирование на Visual C++. Архив рассылки - описание и краткое содержание, автор Алекс Jenter, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)

Программирование на Visual C++. Архив рассылки - читать книгу онлайн бесплатно, автор Алекс Jenter
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

class CEMF : public CObject {

// Операции

public:

CEMF();

~CEMF();

BOOL Load(const char *szFileName);

BOOL Draw(CDC* pDC, RECT* pRect);

LPENHMETAHEADER GetEMFHeader() {

return ((m_pEMFHdr) ? m_pEMFHdr : NULL);

}

LPTSTR GetEMFDescString() {

return ((m_pDescStr) ? m_pDescStr : NULL);

}

HENHMETAFILE GetEMFHandle() {

return ((m_hemf) ? m_hemf : NULL);

}

protected:

BOOL GetEMFCoolStuff();

BOOL LoadPalette();

// Данные

protected:

CString m_szPathName;

HENHMETAFILE m_hemf;

LPENHMETAHEADER m_pEMFHdr;

LPTSTR m_pDescStr;

LPPALETTEENTRY m_pPal;

UINT m_palNumEntries;

LPLOGPALETTE m_pLogPal;

LOGPALETTE m_LogPal;

HPALETTE m_hPal;

};

Функция Load подозрительно смотрит на начало файла, как и мой предыдущий код в функции Serialize. Но теперь нет объекта типа CArchive со всеми его преимуществами. Нет проблем. Использование объекта типа CFile позволяет прочитать сигнатуру. Функции GetEMFCoolStuff и LoadPalette взяты из моей программы-примера EMFDCODE в MSDN. Они получают копии заголовка метафайла, строки описания, и палитры внедренной в метафайл. Конечно, они теперь находятся в классе CEMF.

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 в будущем изменилось бы, мой код перестал бы работать. Но это все еще меня немного беспокоит. Как-никак, а я бывал достаточно сообразителен, чтобы при необходимости залезать в отладчик, прослеживать за несколькими переменными и затем придумывать способ получения желаемого результата. И это приводит меня к моей первой (и возможно последней) гипотезе: инкапсуляция и сокрытие данных могут мстить за чрезмерный энтузиазм.

Ладно, хватит о гипотезах. Вернемся к программе. Мы обсуждаем отрисовку документа в дочернем окне. Клиентскую область окна мы получили с помощью GetClientRect и поместили в m_rectDraw.

if (pDC->IsPrinting()) {

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

} else {

GetClientRect(&m_rectDraw);

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

}

Затем вызывается функция Draw и пуф! Появляется картинка.

Вывод изображения в окно предварительного просмотра и на принтер

Да, я схитрил. Я здесь сразу буду заниматься двумя представлениями, в окне предварительного просмотра и на принтере. Но я это делаю исключетельно потому, что для MFC между ними очень мало разницы.

Если IsPrinting возвращает TRUE, вызывается функция Draw с тем, что поначалу кажется неинициализированным m_rectDraw.

if (pDC->IsPrinting()) {

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

} else {

GetClientRect(&m_rectDraw);

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

}

К счастью, это все-таки не так. Библиотека опять приходит на помощь. Когда мы печатаем или находимся в режиме предварительного просмотра, несколько функций вызываются до OnDraw. Эти функции можно перекрыть своими. В данном случае я перекрыл функцию OnPrint (которая в конце концов вызывает OnDraw). В эту функцию передается указатель на объект типа CPrintInfo. Один из переменных-членов этого класса – объект типа CRect, определяющий доступную для печати область. Этот прямоугольник просто копируется в m_rectDraw до вызова OnDraw.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Алекс Jenter читать все книги автора по порядку

Алекс Jenter - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Программирование на Visual C++. Архив рассылки отзывы


Отзывы читателей о книге Программирование на Visual C++. Архив рассылки, автор: Алекс Jenter. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x