Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
По счастью, нашлась недокументированная возможность. Выяснилось, и это очень важный нюанс, который не разъяснен в MSDN: У функции CReadClass есть 3 параметра, 2 последних имеют умолчание NULL:
CRuntimeClass* ReadClass(const CRuntimeClass* pClassRefRequested = NULL, UINT* pSchema = NULL, DWORD* obTag = NULL);
throw CArchiveException;
throw CNotSupportedException;
Первый параметр – RuntimeClass для проверки на соответствие загружаемого класса.
Второй параметр – поинтер на UINT – версию сериализуемого класса.
Третий параметр, и это самое интересное (кстати, в MSDN записано, что, он предназначен для внутреннего использования в функции ReadClass и обычно задается как NULL) – если не задан нулем, возвращает в младших 2-х байтах значение, сериализованное из архива, а CArchiveException при этом не вырабатывается! Версия при этом не заполняется.
Отсюда решение, которое проиллюстрировано во фрагменте кода:
#define BASE_DATA_VERSION 0x100
IMPLEMENT_SERIAL(MyClass, CObject, VERSIONABLE_SCHEMA | BASE_DATA_VERSION)
void MyClass::Serialize(CArchive& ar) {
UINT Version=NULL;
CObject::Serialize(ar);
DWORD Tag;
if(ar.IsLoading()) {
TRY {
ar.ReadClass(RUNTIME_CLASS(MyClass), &Version, &Tag);
if (Version == BASE_DATA_VERSION)
ar >> dwValue; // описано в классе DWORD dwValue;
else {
WORD HighW;
ar >> HighW;
dwValue = MAKELONG(Tag, HighW);
}
ar.Read( title, sizeof(title)); // описано в классе
// char title[LEN_TITLE];
ar>> val1;
ar>> val2; // нормальная сериализация
…
Борис БердичевскийЗдравствуйте Алекс!
Только что подписался на вашу рассылку, и прочитал все выпуски из архива. Мне показался интересным вопрос из выпуска N2 про возможность структурного сохранения данных в MFC.
На мой взгляд опубликованные ответы были не очень точны, т.к. в MFC все-таки имеются некоторые способы такого хранения, хотя конечно не совсем до конца доделанные.
Прежде всего существует класс COleDocument, который позволяет хранить данные в compound file – в которых как раз и хранятся иерархические данные.
У этого класса есть, к сожалению не документированный, член m_lpRootStg который представляет из себя корневой storage документа. К сожалению в MFC нет стандартных средств работы со storage, но никто не мешает пользоваться его собственным интерфейсом.
Зато есть класс COleStreamFile который инкапсулируют в себе IStream являясь в то же время потомком CFile, что делает возможным его использования для CArchive и соответственно serialize.
И наконец последнее замечание. К сожалению, модель MFC такова, что при использовании своих IStorage объектов, их НЕОБХОДИМО записывать в функции serialize, иначе они могут потеряться при команде Save As.
Вот и все что я хотел напистаь. Может немного сумбурно и поздновато, но может кому-нибудь пригодиться.
С уважением,
Nick PisanovСпасибо Нику за ответ и полезную информацию. Я просто хочу заметить, что все-таки вместо "недоделанных" способов чаще предпочитаю использовать свои, хоть с потом и кровью созданные, но доделанные, удобные, не основывающиеся на недокументированных возможностях, досконально известные и работающие на все 100%.
Но это вопрос философский, конечно… Иногда действительно это приводит к изобретению велосипеда. Программирование – это все-таки больше искусство, чем наука ;) Каждый творит по-своему.
Пришло дополнение к прошлому выпуску:
Hello!
Маленькое замечание. После Shell_NotifyIcon( NIM_ADD, &nid); надо еще добавить ::DestroyIcon(nid.hIcon);
Я как-то делал анимацию иконки в трэе (типа как TheBat крылышками там машет) и долго не мог понять, почему после нескольких часов работы прога вешает всю систему, а никакой утечки памяти нет.
Андрей, НорильскОгромное спасибо, Андрей! Действительно, если делать такие анимации в tray, то своевременное уничтожение иконки становится критичным.
И еще на тему прошлого выпуска:
В 11 выпуске был вопрос, касаемо часов и реестра. Дело не в тебе, а в авторе сообщения. Дело в том, что windoza ставит в этот ключ что-то только если user что-то поменял в разделе "язык и стандарты". Если же там всё по умолчанию, то в реестре у тебя будет по этому пути только параметр Locale, указывающий код страны, правила записи даты, времени и т.п. которой используются для вывода системной даты.
Пригожев Александр (alexproger)Что ж, видимо так оно и есть. Я дописал нужные параметры и все заработало. Но только после того, как я изменил региональный стандарт с русского на английский(США). Те два параметра, в которых вы записывали свое имя – на самом деле это метки "до полудня" и "после полудня", по умолчанию равные "AM" и "PM". В русском стандарте эти метки не используются.
ПРОШУ ВНИМАНИЯ:Это последний выпуск рассылки в этом сезоне. К сожалению, я не знаю никого, кому мог бы доверить вести рассылку на время моего отпуска (и кто бы горел желанием это делать), поэтому рассылка также уходит в отпуск до конца лета .
Большая просьба не ждать от меня ответа на свои письма раньше сентября – я буду отсутствовать физически. Прошу прощения у тех, на чьи письма и вопросы не успел ответить.
Надеюсь, что рассылка для вас является интересной и познавательной. Также уверен, что после выхода из отпуска она станет еще полезнее, так как я собираюсь воплотить несколько новый идей. А еще осенью должен открыться официальный сайт рассылки. Так что
до встречи в новом сезоне! Оставайтесь с нами! ©Алекс Jenter mailto:[email protected] Красноярск, 2000.Программирование на Visual C++
Выпуск №13 от 7 сентября 2000 г.
Здравствуйте, дорогие подписчики!
Чрезвычайно рад приветсвовать вас после чуть более чем месячного отдыха. Как вы уже наверное сами догадались, рассылка вышла из отпуска и снова будет периодически радовать вас всяческой полезной информацией о мощнейшем современном инструменте разработки, а именно Microsoft Visual C++, ну а также о всем, что с ним связано. Начинается новый сезон выпусков, и начинается он с весьма счастливого номера – тринадцатого ;) Впрочем, я никогда не был особенно суеверным, так что пропускать это замечательное число никак не намерен.
Я взял на себя смелость немного изменить оформление рассылки – спасибо ребятам с subscribe.ru, они наконец-то догадались, что далеко не все пребывают в диком восторге от их цвета для фона страницы HTML-варианта, который мне почему-то всегда напоминал цвет известного сельскохозяйственного удобрения. Теперь это можно изменить, что я, особо не мешкая, и сделал. Впрочем, как говорится, на вкус и цвет товарища нет, так что будем условно считать возможную дискуссию на эту тему несостоявшейся.
За время моего отсутствия пришло много писем с вопросами и предложениями, и я думаю, что самые интересные из них мы разберем в ближайших выпусках.
Есть, к сожалению, и не очень приятные новости. Сейчас у меня будет оставаться не так много времени на рассылку, как раньше. Выпуски будут выходить так же регулярно, но, возможно, самую малость пореже. И еще: я не буду делать отдельную текстовую версию, придется положиться на конвертер сервера. Прошу прощения у подписчиков текстового варианта. Понимаю, что звучит банально (я такие утверждения встречал почти в каждой рассылке, а теперь дошел до того, что пишу это сам) но HTML-вариант ДЕЙСТВИТЕЛЬНО гораздо лучше выглядит и занимает ненамного больше времени для загрузки.
MFCНачать всегда труднее всего, так что, облегчая себе задачу, я решил не начинать все заново и строить "новый мир" на обломках "старого", а просто продолжить с того места, на котором остановился. Итак, если вы помните, в предыдущем (двенадцатом) выпуске, я вам рассказывал о том, как с помощью MFC организовать набор закладок, без которых, замечу, просто немыслим удобный и структурированный интерфейс для диалога с большим количеством различных опций (вновьподписавшимся рекомендую обратиться к архиву рассылки, ссылка на него есть в конце этого выпуска). Кстати, в некоторых книгах закладки называют "вкладками", и некоторые считают, что так правильнее, хотя суть от этого, конечно же, не меняется.
Набор закладок: пара замечанийОписанный мной в #12 способ организации закладок в принципе работает, но имеет два существенных недостатка, на которые обратил внимание мой хороший друг, программист Bad Sector. Одновременно он подсказал пути их устранения.
Недостаток первый: в фокусе ввода закладки, при нажатии клавиши "Enter" не происходит передача сообщения родительскому окну, содержащему набор, а идет его обработка "на месте". Это может, в худшем случае, привести к удалению содержимого текущей закладки с экрана, а кнопка по умолчанию родительского диалога не сработает. Сразу скажу, что проблема разрешается перекрыванием PreTranslateMessage(), но есть способ проще и лучше, который я опишу чуть ниже.