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

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

Выпуск №18 от 7 октября 2000 г.

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

После публикации статьи про CPropertySheet меня обвинили в чрезмерной ориентированности на начинающих программистов (на самом деле было использовано другое слово). Так что материал этого выпуска как раз для чуть-чуть более "продвинутых".

И еще, хочу чтобы вы приняли к сведению: я отвечаю НЕ НА ВСЕ приходящие письма. Когда вы присылаете мне вопрос, не нужно рассчитывать на то, что я обязательно на него отвечу или помещу в рубрику "В поисках истины".

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

MFC

Сегодня я хочу представить вашему вниманию статью – перевод из MSJ C++ Q&A, которую прислал Илья Простакишин.

Решение проблемы с OnIdle в dialog-based приложениях

Проблема в том, что OnIdle работает нормально только в приложениях document/view, что не скажешь о приложениях dialog-based. Функция CApp::InitInstance вызывает dlg.DoModal, которая в свою очередь вызывает CWnd::RunModalLoop, а та никогда не обращается к OnIdle. Кажется, что можно производить фоновую обработку посредством WM_ENTERIDLE, но это сообщение направляется только родительскому окну диалога, которого в нашем случае просто не существует. Как решить эту проблему?

Модальные диалоги на самом деле лишь имитируются в MFC. Когда вы вызываете CDialog::DoModal, MFC не вызывает ::DialogBox, как можно было ожидать; вместо этого вызывается ::CreateDialogIndirect, затем модальное поведение имитируется путем блокировки родительского окна и запуска своего собственного цикла обработки сообщений. По существу, тоже самое делает функция ::DialogBox. Тогда зачем изобретать велосипед? А дело в том, что теперь MFC имеет свой собственный цикл, в то время как раньше он "прятался" внутри функции API ::DialogBox. Это позволяет MFC обрабатывать сообщения посредством обычных потоков MFC (CWinThread::PumpMessage), что и делается с другими типами окон. В результате вы можете переопределять CWnd::PreTranslateMessage для модальных диалогов – например, для реализации "горячих" клавиш. Ранние версии MFC позволяли реализовывать свою собственную функцию PreTranslateMessage для модального диалога. Но толку от этого было мало, ведь она все равно никогда не вызывалась, т.к. CDialogDoModal напрямую обращалась к ::DialogBox. При этом управление в программу не возвращалось, пока один из обработчиков сообщений вашего диалога не вызывал EndDialog. По этой же причине была невозможна обработка интервала ожидания.

Вместо этого Windows имеет свой собсвенный механизм, WM_ENTERIDLE, предназначенный для обработки интервала ожидания в модальных диалогах. После обработки одного или нескольких сообщений, если в очереди больше ничего нет, Windows автоматически посылает WM_ENTERIDLE окну-владельцу модального диалога или меню. Работает это только в модальных диалогах. Поскольку MFC теперь использует немодальные диалоги в качестве модальных, WM_ENTERIDLE посылается библиотекой "вручную", чтобы самостоятельно имитировать модальные диалоги, но, опять же, только если имеется родительское окно.

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

Перейти на страницу:

Похожие книги

Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Эта книга представляет собой перевод третьего издания американского бестселлера Effective C++ и является руководством по грамотному использованию языка C++. Она поможет сделать ваши программы более понятными, простыми в сопровождении и эффективными. Помимо материала, описывающего общую стратегию проектирования, книга включает в себя главы по программированию с применением шаблонов и по управлению ресурсами, а также множество советов, которые позволят усовершенствовать ваши программы и сделать работу более интересной и творческой. Книга также включает новый материал по принципам обработки исключений, паттернам проектирования и библиотечным средствам.Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Скотт Майерс , Скотт Мейерс

Программирование, программы, базы данных / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT