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

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

Жанры

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

Jenter Алекс

Шрифт:

Хорошо, если все сообщения модального диалога проходят через стандартную очередь, почему не вызывается CWnd::OnIdle, как часть этого процесса? Проблема в том, что функция CWnd::RunModalLoop вызывает CWinThread::PumpMessage, однако OnIdle вызывается только внутри CWinThread::Run. MFC вызывает CWinThread::Run для запуска вашего приложения после вызова функции InitInstance. В сокращенном виде функция CWinThread::Run выглядит так:

// (from THRDCORE.CPP)

int CWinThread::Run {

 // for doing idle cycle

 BOOL bIdle = TRUE;

 LONG lIdleCount = 0;

 for (;;) {

while (bIdle && !::PeekMessage(…)) {

// call OnIdle while in bIdle state

if (!OnIdle(lIdleCount++)) // assume "no idle" state

bIdle = FALSE;

}

// Get/Translate/Dispatch the message

// (calls CWinThread::PumpMessage) 

 }

}

Я

убрал все лишнее, чтобы заострить внимание на том, как реализована обработка интервала ожидания. Если соообщений не поступает, MFC вызывает CWinThread::OnIdle, каждый раз увеличивая аргумент-счетчик. Вы можете использовать этот счетчик для установки приоритета различиных обработчиков интервала ожидания. Например, можно выполнять форматирование (диска C:, например :)), когда счетчик ожидания равен 1, затем обновлять показания часов при счетчике, равном 2 и т.п. Если OnIdle возвращает FALSE, то MFC прекращает его вызывать и ждет пока ваш поток получит какое-нибудь сообщение, просле чего обработчик будет вызываться снова.

Обратите внимание, что модальный диалог никогда не будет выполнять этот код, поскольку CWnd::RunModalLoop вызывает CWinThread::PumpMessage сразу из своего собственного цикла обработки сообщений. Он не вызывает CWinThread::Run и, следовательно, никогда не обращается к CWinThread::OnIdle. По-видимому, так было задумано разработчиками. Очевидно, что опасно вызывать OnIdle внутри модального диалога, поскольку многие обработчики сообщений создают временные объекты CWnd, которые, вполне возможно, будут существовать все время, пока существует диалог. Частью процесса обработки OnIdle является освобождение временных карт дескрипторов (handle).

Не могу удержаться от упоминания о том, что механизм временной/постоянной карты дескрипторов (handle map), используемый для связывания дескрипторов HWND с классами CWnd – это один из самых потенциально опасных элементов каркаса приложения, даже более опасный, чем карты сообщений. Проблема "временной карты" непрерывно преследует программистов, особенно в многопотоковых приложениях, делая их трудными для написания в MFC.

Итак, каким же образом обрабатывать период ожидания в приложениях, основанных на диалоге, которые не имеют родительского окна? К счастью, это довольно просто. Разработчики MFC предусмотрели возможность перехвата WM_KICKIDLE. RunModalLoop посылает это частное сообщение MFC (вы не найдете его описания в стандартной документации по Win32 API) все время, пока в очереди диалога нет сообщений, так же как CWinThread::Run вызывает OnIdle. RunModalLoop также поддерживает счетчик и увеличивает его для вас. В результате, WM_KICKIDLE является диалоговым эквивалентом OnIdle. Историческая справка: в ранних версиях MFC была реализована подмена модальных диалогов немодальными в комплексе с WM_KICKIDLE в страницах свойств (property sheets). Видимо, эта схема настоько понравилась, что в дальнейшем все немодальные диалоги стали маскироваться под модальные.

Маленькое замечание: у вас может появиться

искушение вызвать функцию OnIdle основного приложения. Вот так, например:

LRESULT CMyDlg::OnKickIdle(WPARAM, LPARAM lCount) {

 return AfxGetApp->OnIdle(lCount);

}

Разработчики MFC утверждают, что это опасно, в связи с проблемой пресловутой временной карты. Лучше всего реализовывать обработку интервала ожидания внутри OnKickIdle. Если хотите, то можно объединить общие команды обработки в отдельную функцию, которую и вызывать из CApp::OnIdle и CMyDlg::OnKickIdle.

Раз уж здесь был заведен разговор о предмете обработки интервала ожидания, то не лишним будет упомянуть о следующем – не все программисты знают, что есть также функции OnIdle для классов CDocTemplate и CDocument. Если вы хотите реализовать обработчик периода ожидания для документа или шаблона документа, то все что нужно сделать – это определить одну из этих функций.

Paul DiLascia ([email protected]) Copyright(C) 1995 by Miller Freeman, Inc. Перевод: Илья Простакишин ([email protected])

Если у вас есть материал (на русском языке) по теме, которая, как вы считаете, будет интересна подписчикам рассылки, не стесняйтесь и присылайте.

ВОПРОС-ОТВЕТ

Q. У меня программа с использованием MFC и Doc/View. Я вставил RichEditCtrl во вью. (2-ой версии). Установил шрифт с помощью сообщения SetCharFormat. Внимание, вопрос: почему если я ввожу текст с клавиатуры и использую ReplaceText функцию (не сообщение!) фонты различные? Вроде это сообшение не менялось у второй версии. Заранее спасибо за ответ.

Игорь

A. Думаю, всё дело в режиме IMF_AUTOFONT, который по умолчанию устанавливается для rich edit'а 2-й версии (в 1-й этого режима просто не было). В этом режиме rich edit автоматически переключает язык и фонт, когда пользователь переключает раскладку клавиатуры (в текст rtf вставляется управляющая последовательность "\langXXXX\fX"). Поэтому если язык, установленный в rich edit'е по умолчанию, отличается от выбранного при запуске программы, фонт подменяется как только кто-то начинает набирать текст с клавиатуры, что и приводит к описанному эффекту.

Для решения проблемы следует попробовать отключить режим IMF_AUTOFONT. Выглядит это так (hEdit – дескриптор rich edit'а):

::SendMessage(hEdit, EM_SETLANGOPTIONS, 0, ::SendMessage(hEdit, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONT);

Alexander Shargin

Огромное спасибо Александру за ответ (уже, кстати, третий по счету).

Напоминаю, что в будущем вопросы от Ильи, Александра и всех тех, чьи ответы или материалы были опубликованы, будут рассматриваться вне очереди.

В ПОИСКАХ ИСТИНЫ

Q. Как просканировать LAN на предмет создания поименного списка машин, чтобы затем можно было изпользовать результат в ListBox'e? Пробовал использовать для этой цели SHBrowseForFolder и связанные ф-ции с установленным флагом CIDL_NETWORK, но открывающееся окно для выбора узла и необходимость "раскрывать плюсики" в локальных группах меня не устраивает. Если можно, в API без MFC.

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

Сердце Дракона. Том 20. Часть 1

Клеванский Кирилл Сергеевич
20. Сердце дракона
Фантастика:
фэнтези
боевая фантастика
городское фэнтези
5.00
рейтинг книги
Сердце Дракона. Том 20. Часть 1

Холодный ветер перемен

Иванов Дмитрий
7. Девяностые
Фантастика:
попаданцы
альтернативная история
6.80
рейтинг книги
Холодный ветер перемен

Последнее желание

Сапковский Анджей
1. Ведьмак
Фантастика:
фэнтези
9.43
рейтинг книги
Последнее желание

Отмороженный 7.0

Гарцевич Евгений Александрович
7. Отмороженный
Фантастика:
рпг
аниме
5.00
рейтинг книги
Отмороженный 7.0

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Магия чистых душ 2

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.56
рейтинг книги
Магия чистых душ 2

Наследие Маозари 5

Панежин Евгений
5. Наследие Маозари
Фантастика:
фэнтези
юмористическое фэнтези
5.00
рейтинг книги
Наследие Маозари 5

Локки 4 Потомок бога

Решетов Евгений Валерьевич
4. Локки
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Локки 4 Потомок бога

Граф

Ланцов Михаил Алексеевич
6. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Граф

Миф об идеальном мужчине

Устинова Татьяна Витальевна
Детективы:
прочие детективы
9.23
рейтинг книги
Миф об идеальном мужчине

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Здравствуй, 1984-й

Иванов Дмитрий
1. Девяностые
Фантастика:
альтернативная история
6.42
рейтинг книги
Здравствуй, 1984-й

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

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

Барон не играет по правилам

Ренгач Евгений
1. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон не играет по правилам