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

ЖАНРЫ

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

Jenter Алекс

Шрифт:

Что ж, огромное спасибо Борису за комментарии и дополнения. Я надеюсь, он и в будущем будет нам посильно помогать. Что касается вопроса Броника – думаю, он все-таки спрашивал не о том, как сделать сериализацию для 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", чтобы установить стиль окна по умолчанию.

Ну вот и все на сегодня. Удачного вам программирования.

Красноярск, 2000.

Программирование на Visual C++

Выпуск №4 от 25/06/2000

Добрый день, уважаемые подписчики!

Мне приходит очень много ваших писем с вопросами, советами, комментариями, предложениями и т.д. Как повелось, самые интересные из них я публикую в рубриках "Обратная связь" и "Вопрос-ответ". Но, как вы наверное сами понимаете, я просто физически не в состоянии отвечать на такое количество вопросов, касающихся программирования. Я отвечаю быстро, когда сразу знаю ответ, но ведь чаще приходится самому сидеть и разбираться, а на это уходит много времени. От этого в первую очередь страдают другие рубрики рассылки – я не успеваю подготовить хороший материал для вас (кстати, я как раз хочу сделать несколько новых рубрик… но пусть лучше это будет сюрприз). Моя задача как автора рассылки состоит в том, чтобы готовить и публиковать интересную информацию по обозначенной тематике. Я же в последнее время больше сам занимаюсь программированием. Для меня, это, конечно, полезно ;) но вот как насчет вас? На многие вопросы я уже ответил, хотя они не появятся в рассылке, т.к. довольно узко направлены и вряд ли интересны для "широкой общественности". Ответы на другие или слишком обширны и тянут на тему отдельного выпуска, или попросту элементарны.

Решив, что так дальше дело все-таки не пойдет, я придумал новую схему. Мне пришло несколько писем с предложениями помощи от программистов, выписывающих рассылку (огромное спасибо им!), так что теперь лишь на некоторые (самые интересные ;) вопросы я буду отвечать лично (в рубрике "Вопрос-ответ"), а другие просто опубликую отдельно. В дальнейшем эти вопросы (вкратце) уже вместе с ответами на них появятся в рубрике "Вопрос-ответ" (мне, кстати, предлагали расширить эту рубрику – вот хороший повод). Я надеюсь, наше с вами мнение совпадет и вы тоже посчитаете, что так будет лучше. Еще я очень полагаюсь на ваше сотрудничество – если знаете ответ на вопрос, не поленитесь и напишите! Человек будет вам благодарен, да и не только он, а все читатели, которые узнают что-то новое. А я лично преобладающую свою роль программиста-консультанта сменю на роль ведущего рассылки.

С другой стороны, я ни в коем случае не хочу рассылку превращать в тривиальную дискуссионную группу. Будет несколько новых рубрик! Поэтому количество вопросов, рассматриваемых в выпуске, будет ограничиваться (в среднем) двумя-тремя вопросами в рубрике "Вопрос-ответ" плюс два-три вопроса, ожидающие ответа. 

Кстати, могу дать очень хороший совет для тех, кто отчаялся найти решение своей проблемы: попробуйте, действительно, задать вопрос в дискуссионной группе, например на news.microsoft.com, в microsoft.public.ru.vc или microsoft.public.russian.programming, а если знаете английский, лучше в одну из многочисленных microsoft.public.vc.* Там отвечают действительно быстро, сам не раз прибегал к этому! И не забудьте порекомендовать подписаться на рассылку :)

Поделиться с друзьями: