Чтение онлайн

на главную - закладки

Жанры

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

Jenter Алекс

Шрифт:

 // создаем новый объект нужного класса

ASSERT(pNewObject->IsKindOf(RUNTIME_CLASS(CMyObject));

 // проверяем класс объекта

Меня удивило, что большинство из вас подписывается именно на HTML – я думал, наши люди как никакие другие считают каждый килобайт. Но, видимо, времена меняются – в лучшую сторону. Дай бог! Так что по вышеописанным причинам я решил поднапрячься и сработать собственный HTML-вариант. То, что получилось, сейчас перед вами, уважаемые HTML-подписчики. Тех, кто выписывает текстовый вариант, уговаривать подписаться на HTML я не буду, потому что прекрасно их понимаю ;) Оба варианта я буду делать лично, никакой автоматической генерации. Enjoy.

ОБРАТНАЯ СВЯЗЬ

Мне пришло интересное письмо на тему предыдущего выпуска. Хочу предложить его вашему вниманию:

Приветствую!

Я

только что обнаружил эту рассылку, подписался и 2 первых выпуска прочитал в архиве. Очень надеюсь, что смогу оказать посильную помощь автору и читателям рассылки, так как около 30 лет занимаюсь программированием и последние 3-4 года – Visual C++. На работе сейчас я программирую именно на этом [языке – AJ], Visual Studio 6.0

В отношении вопроса Броника. Конечно, система сериализации для ActiveX имеется. Для этого рекомендуется использовать класс COLEControl (порожденный из CWnd –>CCMDTarget->CObject).

Вот пример из MSDN (у меня есть этот хелп и на работе и дома)

void CMyCtrl::Serialize(CArchive& ar) {

 DWORD dwVersion = SerializeVersion(ar, MAKELONG(_wVerMinor, _wVerMajor));

 SerializeExtent(ar);

 SerializeStockProps(ar);

 if (ar.IsLoading) {

// загрузить свойства

 } else {

// сохранить свойства

 }

}

Пару замечаний относительно сериализации. Вот пример, как можно поддерживать версию при сериализации. Это важная вещь, поскольку в классы регулярно заносятся новые данные, и чтение-сериализация должны поддерживать старые версии распространенных среди пользователей Вашей программы файлов.

IMPLEMENT_SERIAL(CMyClass, CObject, VERSIONABLE_SCHEMA | 2)

// 2- Номер текущей (новой) версии. 1 - номер старой версии

void CMyClass::Serialize(CArchive& ar) {

 if (ar.IsLoading) {

UINT Version;

ar.ReadClass(RUNTIME_CLASS(CMyClass), &Version);

switch(Version) {

case 2:

// чтение по-новому

break;

case 1:

// чтение по-старому

break;

}

 }

 if (ar.IsStoring) {

ar.WriteClass( RUNTIME_CLASS(CMyClass));

// запись по-новому

 }

}

Понятное дело, при продвижении версии номер в IMPLEMENT_SERIAL возрастает, и добавляется новый случай case только при чтении соответствующих версий.

Еще одно важное замечание. При использовании механизма сериализации мы платим некоторую цену: не допускается никаких абстрактных классов – забудьте, что это существует!

Boris Berdichevski

Что ж, огромное спасибо Борису за комментарии и дополнения. Я надеюсь, он и в будущем будет нам посильно помогать. Что касается вопроса Броника – думаю, он все-таки спрашивал не о том, как сделать сериализацию для ActiveX(хотя это тоже очень интересный момент), а как организовать структурированное хранение данных в файле , наподобие того, что присутствует в ActiveX. Ответа на этот вопрос, за исключением предложенного мной в предыдущем выпуске, пока нет.

Просьба: когда пишете мне, пожалуйста оговаривайте ваше отношение к публикации вашего e-mail адреса. Я оставляю за собой право решать, какие из ваших писем появятся в рассылке. По умолчанию адрес публиковаться не будет. Если вы хотите связаться с человеком, письмо которого вы прочитали в рассылке, но чей адрес не был указан, пишите мне с пометкой в subject'e для кого это письмо.

ВОПРОС – ОТВЕТ

Q. Идея рассылки и её тематика очень понравились, даже добавлять или изменять ничего не хочется, как по заказу. И даже уже вопрос созрел. При первом знакомстве с MFC помню была одна проблема. Никак не получалось сменить пиктограмку курсора во время выполнения программы.

Т.е. последовательность стандартных действий LoadCursor и SetCursor не срабатывала, хотя при создании окна этих действий хватало. В связи с этим вопрос: Какие ещё действия надо выполнить для смены пиктограмки курсора во время работы приложения. Сейчас, к сожалению, интересы лежат не в области C++ и MFC. Поэтому на разрешение вопроса своими силами просто нет времени.

softmax

A. Спасибо за добрые слова о рассылке. По вопросу – проблема здесь в том, что система автоматически при каждом движении мыши восстанавливает тот курсор, который был указан при регистрации класса окна. Вообще я знаю три способа изменить курсор в MFC-приложении, причем два из них имеют некоторые ограничения: один используется, в самом деле, при создании окна, а второй работает только с одним курсором – стандартными песочными часами. Думаю, что стоит описать все три способа, для того, чтобы вы могли выбрать наиболее для вас подходящий. Итак:

Способ №1 (универсальный). Нужно перекрыть функцию OnSetCursor класса CWnd, родителя вашего окна (вида). В ней необходимо сообщение обработать самому, устанавливая нужный курсор. Для тех, кто не знает, сообщение WM_SETCURSOR посылается окну тогда, когда курсор мыши двигается внутри окна, причем мышь приложением не захвачена (с помощью функции SetCapture). Вот пример из MSDN:

BOOL CMyView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {

 if (m_ChangeCursor) {

// устанавливаем стандартный курсор вида "I"

::SetCursor(AfxGetApp->LoadStandardCursor(IDC_IBEAM));

return TRUE;

 }

 return CView::OnSetCursor(pWnd, nHitTest, message);

}

Конечно, можно установить и ваш собственный курсор, только вместо LoadStandardCursor нужно будет воспользоваться LoadCursor или LoadOEMCursor. С помощью параметра nHitTest можно определить область, в которой сейчас находится курсор. Вообще, этот способ лучше применять только тогда, когда вам в самом деле нужно динамически менять один курсор на другой (причем отличный от песочных часов), потому этот способ самый нерациональный (прикиньте-ка. сколько раз будет выполняться этот обработчик). Лучше все нужные курсоры загрузить заранее, а из функции– обработчика Load..Cursor не вызывать. Хотя, в принципе, я для примера сделал такой обработчик – никакой разницы в скорости не заметил…но это уже зависит от конкретного компьютера, наверное. И потом, наверное не стали бы в MSDN это советовать, если бы не знали, что делали ;) 

Ну а тем, кому лишь надо видом курсора показать пользователю, что компьютер сейчас занят какой-то операцией, идеально подходит

Способ №2 (песочные часы). Этот способ самый простой. Вызывайте функцию BeginWaitCursor перед началом операции и EndWaitCursor после ее завершения. Единственный нюанс здесь в том, что если эти два вызова должны находиться в разных функциях-обработчиках, то вам все же придется перекрыть OnSetCursor, причем это выглядит примерно так:

BOOL CMyView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {

 if (m_ChangeCursor) {

RestoreWaitCursor; // восстанавливаем курсор-пес.часы

return TRUE;

 }

 return CView::OnSetCursor(pWnd, nHitTest, message);

}

В этом случае перед вызовом BeginWaitCursor m_ChangeCursor нужно приравнять к TRUE, а после EndWaitCursor – к FALSE.

Способ №3 (класс окна). Этот метод применяется, когда вам для какого-то окна нужно установить конкретный курсор, причем желательно на все время существования окна. Перекрываете PreCreateWindow и регистрируете свой класс окна, изменяя поле lpszClass параметра cs типа CREATESTRUCT:

BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs) {

 cs.lpszClass = AfxRegisterWndClass(

CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, //стили окна

AfxGetApp->LoadCursor(IDC_MYCURSOR),// курсор

(HBRUSH)(COLOR_WINDOW + 1)); // цвет фона окна

 return CView::PreCreateWindow(cs)

}

В качестве первого параметра для AfxRegisterWndClass можно указать "cs.style", чтобы установить стиль окна по умолчанию.

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

Адвокат Империи 3

Карелин Сергей Витальевич
3. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 3

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Дурная жена неверного дракона

Ганова Алиса
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Дурная жена неверного дракона

Вонгозеро

Вагнер Яна
1. Вонгозеро
Детективы:
триллеры
9.19
рейтинг книги
Вонгозеро

Ведьма Вильхельма

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
8.67
рейтинг книги
Ведьма Вильхельма

Папина дочка

Рам Янка
4. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Папина дочка

Законы Рода. Том 6

Flow Ascold
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Как я строил магическую империю 7

Зубов Константин
7. Как я строил магическую империю
Фантастика:
попаданцы
постапокалипсис
аниме
фантастика: прочее
5.00
рейтинг книги
Как я строил магическую империю 7

Лучший из худший 3

Дашко Дмитрий
3. Лучший из худших
Фантастика:
городское фэнтези
попаданцы
аниме
6.00
рейтинг книги
Лучший из худший 3

Штурмовик из будущего 3

Политов Дмитрий Валерьевич
3. Небо в огне
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Штурмовик из будущего 3

Последний попаданец 2

Зубов Константин
2. Последний попаданец
Фантастика:
юмористическая фантастика
попаданцы
рпг
7.50
рейтинг книги
Последний попаданец 2

Идеальный мир для Лекаря 14

Сапфир Олег
14. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 14

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Вдова на выданье

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Вдова на выданье