Поскольку в приложении, содержащем нестандартное окно, как правило, заголовок скрыт, то переместить его на новое место оказывается невозможным. Поэтому возникает задача реализации перемещения окна мышью за любую область внутри окна: необходимо дополнить функциональность стандартной процедуры TControl.DragDrop, отвечающей за обработку положения указателя мыши над формой.
Создадим описание этой процедуры в объявлении класса формы TfmFigura (добавленная строка выделена жирно в листинге):
type
TfmFigura = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure DragDrop(var dr: TWMNCHitTest); message wm_NCHitTest;
Тип TWMNCHitTest — это структура, содержащая информацию о положении указателя мыши. Не вдаваясь более в технические детали, создадим тело процедуры в разделе implementation:
procedure TfmFigura.DragDrop(var dr:TWMNCHitTest);
Begin
inherited; //наследует реализацию стандартной
//процедуры DragDrop
//Проверим, был ли щелчок мыши над областью формы
if dr.Result=htClient
then dr.Result:=HTCAPTION;//перенаправляем щелчок
//на заголовок
end;
Запустив приложение, можно убедиться, что окно перемещается за любую область внутри окна.
|
|
Обработка щелчков мышью
Теперь осталось только каким-то образом обработать щелчки мышью на изображении сундука. Предположим, мы хотим, чтобы щелчок на изображении замка использовался для закрытия окна. Для того чтобы обработать щелчок мышью, разместим на форме компонент Shape категории Additional и установим значения его свойствам согласно табл. 1.3.
Таблица 1.3. Свойства компонента Shape
Свойство | Установленное значение | Назначение изменения |
Name | shpExit | Новое имя компонента |
Shape | stEllipse | Вид геометрической фигуры |
Height | 54 | Высота фигуры |
Width | 54 | Ширина фигуры |
Left | 153 | Отступ от левого края формы |
Top | 184 | Отступ сверху |
Hint | Закрыть | Текст всплывающей подсказки |
ShowHint | true | Отображать всплывающую подсказку |
Cursor | crHandPoint | Вид курсора при прохождении компонента |
Brush.Style | bsClear | Заливка фигуры прозрачная |
Pen.Style | psClear | У фигуры нет контура |
Теперь создадим обработчик события shpExit.OnMouseDown, которое возникает при щелчке на компоненте какой-либо кнопкой мыши:
procedure TfmFigura.shpExitMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Begin
if Button=mbLeft then Close;
end;
Откомпилируем и запустим приложение на выполнение. Пробуем нажать кнопку выключения (т.е. щелкнуть левой кнопкой мыши на изображении замка), но ничего не произойдет. Дело в том, что мы изменили стандартную процедуру DragDrop, и теперь указатель мыши всегда перенаправляется на заголовок формы. Необходимо сделать так, чтобы при размещении указателя над "кнопкой выключения" это перенаправление не происходило. Для этого закроем запущенное приложение и внесем следующие дополнения в процедуру (добавленный фрагмент выделен жирнож):
|
|
procedure TfmFigura.DragDrop(var dr:TWMNCHitTest);
begin
inherited;
if dr.Result=htClient
then if not(((dr.XPos-Left)>=shpExit.Left) and ((dr.XPos-Left)<=shpExit.Left+shpExit.Width) and ((dr.YPos-Top)>=shpExit.Left) and ((dr.YPos-Top)<=shpExit.Left+shpExit.Height))
then dr.Result:=HTCAPTION;
end;
Координаты, передаваемые в параметре dr, откладываются относительно верхнего левого угла экрана, поэтому для получения координат относительно левого верхнего угла формы необходимо вычесть из dr.XPos значение свойства fmFigura.Left, а из значения dr.YPos значение свойства fmFigura.Top. Полученные координаты указателя сопоставляются с координатами размещения компонента shpExit, и перенаправление происходит только в том случае, если указатель находится над "кнопкой выключения".
После повторного запуска приложения, "кнопка выключения" уже распознается, а щелчок на ней приводит к завершению работы приложения.
Перетаскивание компонентов в окне приложения
Часто возникает задача перемещения некоторого объекта (одного или нескольких) по форме. Технология перетаскивания (drag and drop – перетащи и оставь) позволяет зацепить мышью визуальный объект на экране и перетащить его в другое место. Решить задачу перемещения можно несколькими способами.
Способ первый. Его суть заключается в том, что свойства Left и Top объекта изменяются на разницу между начальными и конечными координатами (нажатия и отпускания мыши соответственно, рис. 1.3). Этот способ самый простой и надежный, но у него есть один недостаток: Left и Top изменяются по очереди, что приводит к заметному мерцанию.
Рис. 1.3. Положение курсора мыши в координатной системе объекта
Начнем создавать приложение, в котором будем перемещать два объекта Image по форме.
Разместим на форме два компонента Image и вставим в них разные картинки (рис. 1.4). Для адекватного отображения картинок свойство Proportional компонентов Image установим в значение true.
Рис. 1.4. Два компонента Image размещены на форме
Для начала необходимо объявить глобальные переменные (они объявляются в разделе Implementation) x0, y0: integer - они будут запоминать координаты начального положения перемещаемой картинки. И еще нам понадобится переменная drag типа boolean, чтобы нам отличать перемещение мыши над картинкой, от попытки ее сдвинуть: