Программирование на Visual C++. Архив рассылки
Шрифт:
Итак, что я получил практически ничего не делая? На этот вопрос легко ответить. Все, что перечислено в следующем списке (плюс многое другое, что я еще просто не успел оценить, я уверен) было предоставлено MFC:
• Стандартное диалоговое окно открытия файла
• Список недавно открытых файлов в меню Файл
• Возможность перетаскивать файлы из Проводника
• Невообразимое ощущение легкости.
После заполнения моего класса представления (METAVVW.CPP) кодом, необходимым для успешной отрисовки расширенного метафайла, мне стало ясно что я возвращаюсь к своим старым привычкам неорганизованного кодирования на C. Так что я решил убрать весь этот код из класса представления и создать класс, который будет заниматься загрузкой и воспроизведением метафайлов.
Для целей моего маленького приложения, Load и Draw были самыми важными функциями этого класса. Полностью в духе C++, я также написал несколько дополнительных функций для доступа к различным атрибутам метафайла, таким как дескриптор (handle), строка описания, и указатель на заголовок. Следующий код (взятый из CEMF.H) дает хорошее представление о том, что я сделал из этого класса. Заметьте, что я унаследовал класс от CObject, а не от CDC или CMetaFileDC. CDC включает в себя функции PlayMetaFile и AddMetaFileComment, и в ретроспективе, возможно, было бы более удобно унаследовать класс от CDC. Наследование от CMetaFileDC казалось неправильным, потому что я не создавал метафайлы, а просто просматривал уже существующие. Тем не менее, полностью функциональный класс метафайла мог бы быть унаследован и от CMetaFileDC. Да, есть много способов содрать с кота шкуру (прошу прошения у любителей кошек!)
Функция Load подозрительно смотрит на начало файла, как и мой предыдущий код в функции Serialize. Но теперь нет объекта типа CArchive со всеми
Функция Draw вызывается из функции OnDraw класса представления. Особо интересного там ничего не происходит. Если есть палитра, на что указывает не равное NULL значение переменной-члена m_hPal, палитра выбирается в контекст устройства (DC). Я был сильно озадачен, когда узнал что CDC::SelectPalette требует указатель на объект типа CPalette. Но я был так же заинтригован, когда вдруг обнаружил функцию CPalette::FromHandle. Я мог легко преобразовать дескриптор палитры в объект типа CPalette. Далее это было уже просто делом воспроизведения метафайла с помощью CDC::PlayMetaFile.
Что же еще находится в классе CEMF? Как я упоминал выше, есть две закрытых (private) функции, которые управляются с палитрой и заголовком. Я их не буду обсуждать в этой статье, кому интересно см. статьи "Enhanced Metafiles in Win32" и "EMFDCODE.EXE: An Enhanced Metafile Decoding Utility", обе доступны в MSDN. Конечно, вы вероятно захотите также взглянуть на файлы CEMF.CPP и CEMF.H программы METAVIEW, приложенной к статье! Если вы захотите сделать из этого класса что-либо серьезное, предлагаю добавить следующую дополнительную функциональность: возможность делать нумерованые последовательности метафайлов и работать с метафайлами, содержащимися в буфере обмена. Опять же, эти темы описываются в вышеупомянутых статьях.