276______________________________________________Глава 4

void _fastcall TFormI:: PanellMouseMove(TObject *Sender,

TShiftState Shift, int X, int Y)
(
if (move)

Panell->SetBounds(Panell->Left + X - XO,

Panell->Top + Y - YO, Panell->Width, Panell->Height);

}

Он изменяет с помощью метода SetBounds координаты левого верхнего угла
на величину сдвига курсора мыши (X — XO для координаты Х и Y — YO для коор-
динаты Y). Тем самым поддерживается постоянное расположение точки курсора в
системе координат компонента, т.е. компонент смещается вслед за курсором. Из-
менение координат можно было бы задавать непосредственным изменением
свойств Left и Тор :

Panell->Left += X - XO;

Panell->Top += Y - YO;

Но поскольку эти операторы выполняются поочередно, то компонент будет де-
лать каждый раз два перемещения: сначала по горизонтали, а потом по вертикали.
Это приведет к заметному на глаз дрожанию изображения.

По окончании буксировки, когда пользователь отпустит кнопку мыши, насту-
пит событие OnMouseUp. Обработчик этого события должен содержать всего один
оператор:

move = false;

указывающий приложению на окончание буксировки. Тогда при последующих со-
бытиях OnMouseMove их обработчик, приведенный ранее, перестанет изменять   j
координаты панели.

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

Теперь остановимся на другом варианте, заключающемся в букировке не са-
мого компонента, а его контура. При этом никаких отмеченных выше неприятных
явлений не наблюдается, поскольку сам компонент перемещается только один
раз — в момент окончания буксировки, когда требуемое положение уже выбрано.
В этом варианте используются методы рисования на канве, которые подробно рас-
сматриваются в главе 5. Начинается этот процесс, как и ранее, с события OnMou-
seDown, которое обрабатывается процедурой вида:

void _fastcall TFormI:: PanellMouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)
(

if (Button '.= mbLeft) return;

XO = X;

YO = Y;

Panell->BringToFront();

rec = Panell->BoundsRect;

move = true;

}

Эта процедура отличается от рассмотренной ранее только оператором
rec = Panell->BoundsRect;

который запоминает в переменной rec (ее объявление приведено в предыдущем
разделе) исходное положение компонента.

При дальнейшем перемещении курсора мыши срабатывает обработчик собы-
тия OnMouseMove, имеющий вид:

i