 |
Установив точку останова по сообщению, для выполнения выпол-
нения вызова UpodateWindow нажмите F7. Поскольку программа не
прерывается и не возвращает управления, сообщение WM_PAINT в окно
не посылается.
Вы можете проверить, что сообщения WM_PAINT не принимались,
путем нажатия правой кнопки "мыши", возврата в TDW из
WMRButtonUp, и последующей проверки нижней области диалогового
окна View іWindows Messages (ОбзоріСообщения Windows). Здесь нет
сообщений WM_PAINT. По каким-то причинам вызов UpdateWindow не
работает так, как ожидается.
TDeb 3.0 #3-3 = 83 =
Анализ причины ошибки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Эта ошибка требует некоторого понимания того, как Windows
работает с функцией UpdateWindow. Когда программа вызывает данную
функцию, Windows проверяет, является ли какая-либо часть окна не-
допустимой, и требуется ли отображать ее заново. Если это так, то
Windows посылает окну сообщение WM_PAINT. Если же нет, но незачем
попусту тратить системные ресурсы на ненужное сообщение, поэтому
Windows ничего не делает. Но откуда Windows знает, что окно тре-
буется обновить?
Прикладная программа уведомляет Windows, что по крайней мере
часть окна недопустима, с помощью вызова InvalidateRect или
InvalidateRgn. Эти две функции помещают в окно обновленную об-
ласть и уведомляют Windows, что окно следует обновить с помощью
сообщения WM_PAINT. Однако, Windows присваивает сообщению
WM_PAINT, которое оно посылает в ответ на эти вызовы функций,
низкий приоритет, поэтому, если вы хотите, чтобы окно обновлялось
немедленно, следует воздерживаться от вызова UpdateWindow.
Исправление ошибки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Добавление в WMRButtonDown вызова InvalidateRect устранит
проблему. Функция InvalidateRect воспринимает три параметра:
идентифицирующий окно описатель окна, указатель на прямоугольную
область, отмечающий требующий обновления прямоугольник, и пара-
метр типа Boolean, который определяет, следует ли стирать прямоу-
гольную область. В качестве параметра, задающего указатель на
прямоугольную область, вы можете передать значение nil, указав
Windows, что к обновляемому прямоугольнику следует добавить все
окно. В следующем исходном коде показано, как выглядит
WMRButtonDown с несколькими добавленными вызовами функций:
void ScribbleWindow::WMRButtonDown(RTMessages);
{
InvalidateRect(HWindow, NULL, TRUE);
UpdateWindow(HWindow);
}
Проверка исправления
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Запустите программу ColorScribble и выйдите из нее, затем
выйдите в TDW. Когда вы вернетесь в Borland C++, внесите измене-
ния в WMRButtonDown, затем перекомпилируйте программу и запустите
TDeb 3.0 #3-3 = 84 =
Глава 20. Отладка резидентных программ и драйверов устройств
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
С помощью Турбо отладчика вы можете отлаживать не только
обычные выполняемые файлы, но также резидентные в памяти програм-
мы (TSR) и драйверы устройств. Вы можете кроме того выполнять сам
отладчик, как резидентную программу (в то время, как работаете на
уровне DOS или запускаете другие программы).
В Турбо отладчике в меню File (Файл) имеется три новых ко-
манды, которые предназначены специально для отладки резидентных
программ и драйверов устройств. Это команды FileіResident
(ФайліРезидент), FileіSymbol Load (ФайліЗагрузка таблицы иденти-
фикаторов) и FileіTable Relocate (ФайліПеремещение таблицы иден-
тификаторов).
В данной главе вы найдете краткое описание того, что такое
резидентная программа и драйверы устройств, и дается пояснение
того, как отлаживать их с помощью Турбо отладчика.
Что такое резидентная программа?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Резидентными (TSR) называют такие программы,которые остаются
в оперативной памяти после того, как они завершат управление.
Например, SideKick и SuperKey - это резидентные программы, они
все время находятся в памяти и вызываются с помощью специальных
оперативных клавиш. Другие резидентные программы вызываются из
программ, которые выполняют соответствующее программное прерыва-
ние. В Borland Си и С++, например, предусмотрена специальная
функция geninterrupt, которая выдает такое программное прерыва-
ние.
Резидентная программа состоит из двух частей - рабочей части
и резидентной части. Рабочая часть выполняет загрузку резидентной
части в память и устанавливает вектор прерываний, который опреде-
ляет характер вызова резидентной в памяти программы. Если рези-
дентная программа должна вызываться с помощью программного преры-
вания, то рабочая часть программы помещает адрес резидентной час-
ти кода в соответствующий вектор прерывания. Если резидентная
программа должна вызываться с помощью оперативной клавиши, то ре-
зидентная часть должна модифицировать обработчик прерывания DOS
для обработки нажатия соответствующих клавиш (клавиши) на клавиа-
туре.
Когда рабочая часть завершает выполнение, она вызывает функ-
цию DOS, которая позволяет части файла .EXE оставаться резидент-
ной в оперативной памяти после завершения выполнения программы
(то есть программа завершила выполнения и осталась резидентной,
отсюда и название таких программ TSR - terminate and stay
resident). Рабочая часть резидентной программы знает размер рези-
дентной части, а также ее адрес в памяти, и передает эту информа-
цию DOS. Операционная системе DOS при этом резервирует специаль-
TDeb 3.0 #3-3 = 85 =
ный блок памяти, но может свободно записывать информацию в неза-
щищенную часть памяти. Таким образом, резидентная часть остается
в памяти, а рабочая часть может быть "затерта".
Тонкость отладки резидентных программ состоит в том, что вы
должны иметь возможность отлаживать и резидентную, и рабочую
часть программы. Когда выполняется файл .EXE, то выполняется
только код рабочей части TSR. Поэтому, когда вы как обычно запус-
каете Турбо отладчик, задав имя файла, вы видите выполнение толь-
ко рабочей части кода программы: то, как он устанавливает рези-
дентную часть и обработчики прерываний. Чтобы отлаживать рези-
дентную часть, вы должны задать точку останова и сделать
резидентным сам Турбо отладчик. Подробнее мы расскажем об этом
дальше.
Отладка резидентной в памяти программы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Отладка рабочей части резидентной программы эквивалентна от-
ладке любого другого файла. Новое появляется только тогда, когда
вы начинаете отлаживать резидентную часть.
Примечание: С помощью TD вы можете отлаживать драйвер
клавиатуры.
Давайте рассмотрим процесс отладки резидентной программы:
1. При компиляции или ассемблировании резидентной программы
обеспечьте наличие в ней отладочной информации (информа-
ции об идентификаторах). Используйте для этого команды
типа TASM /ZI или BCC -v, либо TPC /V.
2. Если вы выполняете компоновку резидентной программы, для
обеспечения включения информации для отладки используйте
параметр компоновщика /v. Для того, чтобы поместить отла-
дочную информацию в отдельный файл, можно использовать
утилиту TDSTRIP с параметром -s (однако, этого не требу-
ется делать, если программа представляет собой файл
.EXE).
Примечание: Программа TDSTRIP описывается в поставляемом
на диске файле документации. Имя и расположения этого
файла указано в файле README.
3. Теперь загрузите резидентную программу с Турбо отладчиком
и установите точку останова в начале резидентной части
кода (с помощью клавиши F2). Вместо этого вы можете уста-
новить точки останова (если хотите) в других местах рези-
дентной части.
4. После этого можно загрузить резидентную программу с Турбо
отладчиком и выполнить ее рабочую часть с помощью команды
RunіRun (ВыполнениеіВыполнение), как обычно. Дальше можно
TDeb 3.0 #3-3 = 86 =
обычным образом отлаживать рабочую часть. Когда вы закон-
чите выполнять рабочую часть, резидентная часть будет ус-
тановлена в оперативной памяти.
5. Выберите команду FileіResident (ФайліРезидент), чтобы
сделать резидентным сам отладчик. Это не нарушит рези-
дентности вашей программы: когда она будет выполняться в
Турбо отладчике, она сама станет резидентной, как если бы
вы запускали ее из командной строки. Единственная причина
того, что отладчик делается резидентным, заключается в
том, что вы можете перейти обратно в DOS и вызвать вашу
резидентную программу. При этом начнет выполняться ее ре-
зидентная часть.
6. Когда вы вернетесь снова к командной строке DOS, выполни-
те резидентную часть вашей программы TSR, нажав соответс-
твующую оперативную клавишу, или активизировав ее ка-
ким-либо другим образом. Выполняйте вашу программу, как
обычно.
|