Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
А теперь у меня вопрос к авторам таких ответов: Каким образом в Debug-версии все может быть нормально, если исчезновение ASSERT'ов оказалось критичным для работы Release-версии? (Хотя, если честно, один такой способ существует, и именно его, скорее всего. имели ввиду авторы писем. Но я просто никогда еще не встречал таких оригиналов, которые в условие макроса ASSERT умудрятся впихнуть что-нибудь помимо самого условия, выделение памяти или инициализацию объекта, например. Никогда так не делайте! Впрочем, уверен, что большинство до такого все-таки не додумалось ;)
Итак, выходит в Debug-версии программа должна была вылетать на "Assertion failed", а это вряд ли можно назвать "нормальным выполнением". Напоминаю, в самом вопросе утверждалось, что в Debug программа работает без проблем.
Вообще, макрос ASSERT предназначен как раз для того, чтобы именно Debug-версия и не работала , если у вас что-то в программе не в порядке! Таким образом, программист сможет сразу понять, что и где у него не так (это, конечно, в идеале ;).
Но замечу, что сам по себе нюанс этот достаточно интересный. Итак, люди – обратите внимание на макросы ASSERT и VERIFY! Напоминаю: VERIFY, в отличие от ASSERT, сохраняется и в Release-версии, хотя в последнем случае он не прерывает программу даже если условие не выполняется.
Читателей, поднявшим этот вопрос, благодарю, а это: Alexander Dymerets, Alexey "Locky" B.R. и Serge Zakharchuk.
В отличие от большинства, Olga Zamkovayaпредложила другой способ выяснить, в чем дело:
…К вопросу о недопустимой операции в Release версии программы из выпуска #5: в числе полезных советов "проверьте свой код", "build all может помочь" и т.п. не было предложено воспользоваться опцией компилятора /GZ (catch Release-build errors in Debug build), что, мне кажется, может быть полезно в данной ситуации.)
Olga ZamkovayaЧто ж, думаю, и это кому-то поможет – ловить Release-ошибки в Debug. По крайней мере можно будет обнаруживать ошибки на стадии, которая как раз предназначена для отлова ошибок;) Thank you, Olga.
Пришло еще одно письмо на тему обработки событий клавиатуры в диалогах. В качестве дополнения в нем описывается один трюк, который, возможно, будет полезен и вам:
Здравствуйте, Алекс!
Решил попробовать свои силы во внесении посильного вклада в понимание не самых понятных вещей, которые касаются каким-либо образом MS VCPP.
Итак, в выпуске №5 промелькнул вопрос об обработке клавиш в диалоге. Я в свое время столкнулся с точно таким же вопросом и даже собирался его решать способом, которым решил автор вопроса, но меня не хватило: я ленивый. Я нашел очень полезную вещь: использование акселераторов (горячих клавиш) – accelerators – в диалогах. Пользуюсь этим способом регулярно и до сих пор. Идея, в принципе, та же: перегрузить PreTranslateMessage.
Код для этой функции:
BOOL CSomeDialog::PreTranslateMessage(MSG* pMsg) {
if (pMsg->message>= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
if (m_hAccel)
if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg)) return TRUE;
return CDialog::PreTranslateMessage(pMsg);
}
Здесь m_hAccel — переменная-член класса CSomeDialog типа HACCEL, инициализированная в OnInitDialog таким, например, способом: m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(m_lpszTemplateName)); Если ее инициализировать таким образом, то будет произведена попытка найти ресурс акселератора с тем же ID, что и ID диалога (например, IDD_SOMEDIALOG), в котором можно прописать какие только душа пожелает клавиши и их комбинации. Если же ресурс найден не будет, то ничего страшного не произойдет.
Обрабатывать команды от акселератора можно стандартным способом — ON_COMMAND в MESSAGE_MAP'е. Я их прописываю руками, без ClassWizard'а. Да, кстати, можно запросто лепить в таблицу акселератора IDшки кнопок (push buttons). Хэндлер для обработки кнопки, объявленный с помощью ON_BN_CLICKED, будет вызван автоматически (это связано с тем, что ON_COMMAND и ON_BN_CLICKED на самом деле — одно и то же).
[…]
Спасибо, что дочитали даже до этого места, надеюсь, содержанием не разочаровал. Ваша рассылка уже rules, а она (я надеюсь) только начинает раскачиваться.
Спасибо за вашу работу и за ее результат.
--
Пишите письма…
(адрес может быть опубликован, но не продан спаммерам :)
Чепкий Николай ( mailto:alterego@a-teleport.com)Адрес я опубликовал, но спаммерам не продавал – так что моя совесть на этот счет чиста. ;) Если это сделает кто-нибудь из читателей – это будет на его, а не моей, совести.
Вопрос этот обсуждался в прошлом выпуске. Преимущество способа, предложенного Николаем, заключается в автоматизации обработки нажатий клавиш. Так что вместо неуклюжего switch'a в случае большого количества клавиш мы получаем удобный списочек – и минимум кода.
Один из читателей прислал интересный совет, предлагаю его вашему вниманию:
Привет!
Хочу обратить внимание на то, что изменение формы окон при помощи SetWindowRgn() не всегда правильно работает в старых версиях Windows – в частности, такая ситуация наблюдалась под Windows 95 (PLUS) не OSR 2.
Зато совершенно точно это работает под '98, NT, 2000.
-------
Хочу предложить полезную уловку, позволяющую при использовании MFC-шаблонов документов управлять MDI-окнами из приложения. Этот трюк можно использовать при отображении разных категорий данных в различных окнах. При этом можно, в частности, автоматически переключать активные MDI-окна при обновлении данных в них.
Представьте библиотеку (класс), следующего вида:
class TReg {
public:
static CMapStringToPtr map;
static BOOL RegisterTemplate(CString strName, CDocTemplate * ptr);
static BOOL HasOpenViews(CString strName);
static BOOL PostForAllViews(CString strName, UINT msg, WPARAM w, LPARAM p);
static BOOL SendForAllViews(CString strName, UINT msg, WPARAM w, LPARAM p);
static CDocTemplate * GetTemplate(CString strName);
...
};
Зачем все элементы статические – легко понять, ведь у нас только один MDI-фрейм.
Далее, в методе WinApp::InitInstance() при порождении шаблонов документов вместо (или вместе с) AddDocTemplate( CDocTemplate * ) записываем TReg::RegisterTemplate( "MyName", CDocTemplate * );
Здесь мы просто добавляем указатели шаблонов в словарь map.
С помощью метода GetTemplate() мы можем извлечь указатель на шаблон из словаря по имени. Используя этот указатель, мы можем:
– открыть новое окно при помощи DocTemplate::OpenDocumentFile();
– закрыть все окна, относящиеся к данному шаблону;
– отправить сообщение всем окнам данного шаблона:
for (POSITION pos= pTempl->GetFirstDocPosition(); pos != NULL; ) {
CDocument * pDoc= pTempl->GetNextDoc(pos);
if (msg == NULL) pDoc->UpdateAllViews(NULL);
else
for (POSITION p1= pDoc->GetFirstViewPosition(); p1 != NULL; ) {
CView * pView= pDoc->GetNextView (p1);
pView->PostMessage (msg, w, l);
}
}
– проверить, имеются ли открытые окна, относящиеся к данному шаблону:
for (POSITION pos = pTempl->GetFirstDocPosition(); pos != NULL; ) {
CDocument * pDoc= pTempl->GetNextDoc(pos);
for (POSITION p1 = pDoc->GetFirstViewPosition(); p1 != NULL; ) {
CView * pView = pDoc->GetNextView(p1);
if (pView != NULL) return TRUE;
Интервал:
Закладка: