 |
то выбор черного пера будет работать корректно. Когда вы сделаете
это изменение, описание констант в начале программы должно быть
следующим:
#define PenWidth 1
#define MenuID 100
#define IconID 100
#define CM_RED 101
#define CM_GREEN 102
#define CM_BLUE 103
#define CM_CLACK 204
TDeb 3.0 #3-3 = 78 =
Проверка исправления
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Запустите ColorScribble и выйдите оттуда, затем выйдите в
TDW. Когда вы вернетесь в Borland C++, загрузите файл заголовка
TDODEMOB.H, измените определение константы CM_BLACK, затем пере-
компилируйте программу (проект) и запустите ее по TDW.
Теперь когда вы рисуете в окне, то можете заметить другую
проблему. Если при рисовании вы смещаете "мышь" за пределы окна,
то при возврате в окно в другом месте вы увидите, что программа
рисует линию, соединяющую то место, где вы вышли из окна, с тем
местом, где вы в него вернулись.
Все, что здесь должна делать программа - это прекращение ри-
сования при выходе из окна и возобновление рисование при возврате
в него. Итак, вы обнаружили еще одну ошибку.
Поиск ошибки рисования за пределом экрана
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Поиск этой ошибки неплохо начать с сообщение Windows, кото-
рые получает данное окно. Выйдите из программы ColorScribble и
загрузите в TDW (в окне Module) программу TDODEMOB.CPP.
TDeb 3.0 #3-3 = 79 =
Регистрация сообщений Windows
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
В зависимости от того, запрещена или разрешена поддержка со-
общений ObjectWindows, для инициализации окна используйте один из
двух описанных выше методов. Затем укажите в верхней левой облас-
ти окна Windows Messages (Сообщений Windows), для какого окна
нужно отслеживать сообщения (используя объект окна или описа-
тель).
Далее переместите курсор в правую верхнюю область и добавьте
в качестве точки останова по сообщению WM_LBUTTONUP. Это позволит
TDW вновь получить управление, когда вы закончите рисовать.
Желательно также просматривать все поступающие сообщения, но
установка WM_LBUTTONUP стирает установку Log All Messages (Ре-
гистрация всех сообщений). Чтобы восстановить установки, нажмите
для вывода диалогового окна Set Message Filter (Установка фильтра
сообщения) клавиши Ctrl-A.
Обнаружение ошибки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Возобновите выполнение программы TDODEMOB, нажав клавишу F9.
Начните рисовать, затем выведите "мышь" за пределы области поль-
зователя и вернитесь в нее в другом месте. Чтобы уменьшить число
сообщений, просто переместитесь вовне и снова вернитесь назад,
затем освободите левую кнопку "мыши", чтобы управление вернулось
в TDW.
Перед тем, как взглянуть на окно Windows Messages (Сообщения
Windows), увеличьте его до полного размера (клавишей F5), благо-
даря чему вы сможете видеть больше сообщений. Когда вы посмотрите
на нижнюю область окна Windows Messages, то увидите множество со-
общений WM_NCHITEST и WM_SETCURSOR, среди которых будет сообщение
WM_LBUTTONDOWN, WM_MOUSEMOVE, после них будет несколько сообщений
WM_NCMOUSEMOVE, далее еще сообщения WM_MOUSEMOVE и, наконец, зак-
лючительное сообщение WM_LBUTTONUP.
Похоже, что когда курсор не находится в области пользовате-
ля, то сообщения WM_MOUSEMOVE не поступают, а поступают только
сообщения WM_NCMOUSEMOVE.
Теперь яcно, что представляет собой ошибка. Программа рисует
от точки последнего сообщения WM_MOUSEMOVE до точки текущего со-
общения WM_MOUSEMOVE. Когда "мышь" выходит из области пользовате-
ля, программа не получает сообщений WM_MOUSEMOVE. Таким образом,
когда "мышь" возвращается в область пользователя, последней точ-
кой будет та точка, где она покинула экран, и программа ошибочно
рисует линию от точки выхода за пределы экрана до текущей точки.
Исправление ошибки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
TDeb 3.0 #3-3 = 80 =
Одним из возможных решений могло бы быть определение того
места, где "мышь" выходит за область пользователя, благодаря чему
программа сможет игнорировать последнюю позицию "мыши" и снова
начать рисование, когда "мышь" возвращается в область пользова-
теля. Но это потребовало бы сложной логики определения позиции,
где "мышь" покидает пределы экрана и где она возвращается в об-
ласть пользователя. К счастью, есть более простой способ.
Функция Windows SetCapture делает как раз то, что требуется.
Данная функция указывает Windows, что до вызова ReleaseCapture
нужно посылать все сообщения Windows, связанные с "мышью", в ука-
занное окно, что приводит к получению окном вместо сообщений
WM_NCMOUSEBUTTON ("вне области пользователя") сообщений
WM_MOUSEMOVE.
Если вы поместите в ScribbleWindow::WMButtonDown вызов
SetCapture, а в WMLButtonUp - ReleaseCapture, WMMouseMove будет
на самом деле рисовать вне окна, но Windows будет отсекать этот
вывод программы, что будет давать нужный результат.
Эти изменения отражены в следующем исходном коде:
void ScribbleWindow::WMLButtonDown(RTMessage Msg);
{
if ( ButtonDown )
{
ButtonDown = True; // пометить кнопку "мыши"
// как нажатую, благодаря чему
// при перемещении "мыши" будет
// рисоваться линия
SetCapture(HWindow); // сообщить Windows, что в окно
// нужно посылать все сообщения
// от "мыши"; отменять этот
// перехват будет вызов
// WMLButtonUp
TDeb 3.0 #3-3 = 81 =
HandleDC = GetDC(HWindow); // создать контекст
// изображения для вывода
MoveTo(HandleDC, Msg.LP.LO, // переместить точку
Msg.LP.Hi); // рисования в ту
// точку, где была нажата
// кнопка "мыши"
}
}
void Scribblewindow::WMLButtonUp(RTMessage)
{
if ( Buttondown )
{
ReleaseCapture();
ReleaseDC(HWindow,handleDC);
ButtonDown = False;
}
}
TDeb 3.0 #3-3 = 82 =
Проверка исправлений
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Запустите программу ColorScribble и выйдите из нее, затем
выйдите в TDW. Когда вы вернетесь в Borland C++, внесите измене-
ния в две подпрограммы, затем перекомпилируйте программу и запус-
тите ее. Теперь,когда вы рисуете в окне, все будет работать прек-
расно, но когда вы попытаетесь стереть экран, используя правую
кнопку "мыши", то ничего не произойдет. Вы нашли еще одну ошибку.
Поиск ошибки стирания экрана
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Поскольку нажатие правой кнопки "мыши" обрабатывается
WMRButtonDown, то возможно ошибка как то связана с данной подп-
рограммой. Либо WMRButtonDown не вызывается, либо в ней ошибка.
Выйдите из ColorScrible и загрузите в TDW программу
TDODEMOB. Чтобы выполнить ее до подпрограммы WMRButtonDown, в ко-
торой возможно содержится ошибка, нажмите клавиши Alt-F9 и набе-
рите WMRButtonDown. Порисуйте немного в окне, затем нажмите пра-
вую кнопку "мыши". TDW останавливает программу в начале
функции WMRButtonDown, откуда видно, что она вызывается..
Используя клавишу F7, войдите в WRMButtonDown и остановитесь
на вызове UpdateWindow. Единственным параметром является HWindow.
Вы можете предположить, что параметр HWindow установлен правиль-
но, поскольку другие методы успешно используются. Поскольку ниче-
го очевидно неверного здесь нет, вы можете проверить следующее:
принимается ли действительно окном сообщение WM_PAINT, которое
должно посылаться в окно при вызове UpdateWindow?
Теперь вы наверное знаете, как установить точку останова по
сообщению WM_PAINT. Если нет, то прочтите выше описание установки
точки останова по сообщению WM_COMMAND.
|