функции можно, например, удостовериться, что захватом указателя мыши мы не нарушим работу другого приложения (что маловероятно).
Ограничение перемещения указателя
При помощи несложных манипуляций можно также ограничить перемещение указателя мыши определенной областью экрана (прямоугольником). Для этого используется API-функция ClipCursor. Она принимает в качестве параметра структуру TRect с координатами прямоугольника, в пределах которого может перемещаться указатель, и в случае успешной установки ограничения возвращает отличное от нуля значение.
С ClipCursor тесно связана функция GetClipCursor, позволяющая получить координаты прямоугольника, которым в данный момент ограничено перемещение указателя.
Использование функций ClipCursor и GetClipCursor приведено в листинге 3.6.
Листинг 3.6.
Ограничение перемещения указателя
var
lastRect: TRect;
cursorClipped: Boolean = False;
procedure SetCursorRect(newRect: TRect);
begin
if not cursorClipped then
begin
//Сохраняем старую область перемещения указателя
GetClipCursor(lastRect);
//Устанавливаем ограничение на перемещения указателя
cursorClipped := ClipCursor(Addr(newRect)) <> False;
end;
end;
procedure RestoreCursorRect();
begin
if cursorClipped then
begin
//Восстанавливаем область перемещения указателя
cursorClipped := ClipCursor(Addr(lastRect)) = False;
end;
end;
Здесь реализована пара процедур, первая из которых (SetCursorRect) ограничивает перемещение указателя мыши заданной областью экрана (параметр newRect). Перед ограничением на перемещение указателя в процедуре SetCursorRect происходит сохранение области перемещения, установленной ранее, чтобы действие процедуры можно было отменить. Для отмены ограничения перемещения указателя служит вторая процедура – RestoreCursorRect.
Приме чание
Вообще, задание ограничения на перемещение указателя мыши не считается хорошим тоном. Потому для использования такой возможности в реальном приложении должны быть действительно веские причины.
Изменение назначения кнопок мыши
Как известно, операционная система Windows дает возможность работать за компьютером широкому кругу людей. Со стороны разработчиков было бы глупо не предусмотреть возможность простой адаптации манипулятора «мышь» к правше или левше. К тому же мышь адаптировать к таким различиям намного проще: конструкцию изменять не надо, достаточно программно поменять функции кнопок мыши.
Как поменять функции левой и правой кнопок мыши, демонстрирует листинг 3.7.
Листинг 3.7.
Изменение назначения кнопок мыши
procedure TForm1.Button1Click(Sender: TObject);
begin
//Меняем местами функции левой и правой кнопок мыши
SwapMouseButton(True);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//Восстанавливаем функции кнопок мыши
SwapMouseButton (False);
end;
В листинге 3.7 не учитывается тот факт, что инверсия мыши уже может быть установлена при запуске программы (например, если за компьютером работает левша). Чтобы точно знать, была ли ранее применена инверсия к кнопкам мыши, можно использовать значение, возвращаемое функцией SwapMouseButton. Если это значение отлично от нуля, то ранее функции кнопок мыши были инвертированы.
Подсчет расстояния, пройденного указателем мыши
Рассмотрим небольшую программу, которая носит скорее познавательный, чем практический характер. Она умеет подсчитывать, сколько же метров (в буквальном смысле) пробегает указатель мыши за время ее работы. Внешний вид формы приложения показан на рис. 3.1.
Рис. 3.1. Программа измерения пробега указателя мыши
Использование такой программы крайне просто: сразу после запуска она начинает измерять пройденное указателем мыши расстояние в пикселах. Нижняя группа элементов управления нужна для правильного вывода пройденного расстояния в метрах. При нажатии кнопки Изменить масштаб становятся активными два текстовых поля (для ввода ширины и высоты прямоугольника). Чтобы программа правильно преобразовывала пройденное расстояние, нужно линейкой измерить ширину белого прямоугольника и ввести полученное значение (в мм) в текстовое поле. При повторном нажатии этой кнопкивведенные значения принимаются, и с этого момента показания пройденного расстояния переводятся в метры с учетом текущего разрешения и размера монитора.
Теперь приступим к рассмотрению реализации этого приложения. В табл. 3.1 приводятся сведения по настройке элементов управления, не являющихся рамками или статическими надписями.
Таблица 3.1. Параметры элементов управления формы, показанной на рис. 3.1 В листинге 3.8 приводятся объявления переменных (членов класса TForml) и методов, добавленных вручную.Листинг 3.8. Форма для измерения пробега указателя
type
TForm1 = class(TForm)
…
private
isUpdating: Boolean; //Если равен False, то показания
//в txtDistance
//не обновляются
lastPos: TPoint; //Координаты указателя во время
//прошлого замера
distance: Real; //Пройденное расстояние в пикселах
procedure StartUpdating();
procedure StopUpdating();
procedure ShowDistance();
end;
Суммарное расстояние в пикселах, пройденное указателем, сохраняется в переменной distance. Рассмотрим, как осуществляется перевод этого расстояния в метры (листинг 3.9).
Листинг 3.9. Перевод расстояния в метры с учетом масштаба
procedure TForm1.ShowDistance();
var
scale: Real;
distanceMetters: Real;
begin
//Пересчитываем текущий пробег в метры и показываем его
//в текстовом поле
//..определяем масштаб для перевода измерений в метры
scale := 0.001 * StrToInt(txtWidth.Text) / Shape1.Width;
//..подсчитываем расстояние с учетом масштаба
distanceMetters := scale * distance;
//..округляем до трех знаков (мм) и показываем
distanceMetters := Int(distanceMetters * 1000) * 0.001;
txtDistance.Text := FloatToStr(distanceMetters);
end;
В приведенном расчете нет ничего сложного, как, собственно, нет ничего сложного и во всем примере. Главная процедура приложения – обработчик для таймера Timerl. Таймер срабатывает с максимальной для него частотой (не 1 мс, конечно, но где-то 18 раз в секунду). Текст обработчикаТ1тег1Т1тег приводится в листинге 3.10.
Листинг 3.10. Подсчет разницы между положениями указателя мыши
procedure TForm1.Timer1Timer(Sender: TObject);
var
curPos: TPoint;
delta: Real;
begin
if (curPos.X <> lastPos.X) or (curPos.Y <> lastPos.Y) then
begin
GetCursorPos (curPos);
//Вычисляем разницу между текущим и прошлым
//положением мыши
delta := Sqrt(Sqr(curPos.X – lastPos.X) + Sqr(curPos.Y -
lastPos.Y));
distance := distance + delta;
//Не забываем сохранить новые координаты указателя
lastPos := curPos;
if isUpdating then
begin
//Обновим показания в текстовом поле
ShowDistance();
end;
end;
end;
Как можно увидеть при внимательном рассмотрении листинга 3.10, обновление показаний происходит при истинном значении переменной isUpdating. Значение этой переменной устанавливается в False во время задания масштаба, чтобы во время ввода значений в текстовые поля не выводились неправильные цифры (листинг 3.11).
Листинг 3.11.
Активизация/деактивизация режима ввода масштаба
procedure TForm1.cmbScaleClick(Sender: TObject);
begin
if cmbScale.Caption = 'Изменить масштаб' then
begin
//Начинаем изменение масштаба
StopUpdating ();
cmbScale.Caption := 'Принять масштаб
txtWidth.Enabled := True;
end
else
begin
//Заканчиваем изменение масштаба
txtWidth.Enabled := False;
cmbScale.Caption := 'Изменить масштаб
StartUpdating();
end;
end;
Процедуры StartUpdating и StopUpdating скрывают действия, которые необходимо произвести для остановки или