Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 30 июля 2009 в 09:23.
Категории: Без категории, Основы Delphi.


Помнится года 2 назад попалась мне на глаза программа из разряда "бесполезное, но прикольное" под названием "Мышометр". Соответственно названию, программа измеряет расстояние пройденное мышкой. Причем не только в пикселях, но и в метрах, километрах, дюймах и, как ни странно, в зелёных президентах...

мыша

Помню, что тогда меня заинтересовало то, каким это волшебным образом программа переводит пиксели в метры? < ' ' >По сути пиксель - это условно-безразмерная величина и его размер зависит от многих параметров, например разрешения монитора.  Может и разобрался с этим вопросом, но как-то не хотелось долго заморачиваться, да и нужды особой в этом не было. А вот недавно, при разработке большого программного комплекса для экологов этот вопрос таки всплыл, только в несколько ином виде, а именно:  как при работе со сканированными рисунками с высокой точностью определять размеры реальных объектов, изображенных на схеме/карте и т.д.? Собственно, решение нашлось довольно быстро. Приведу его Вам на заметку. Для того, чтобы сильно не загружать Вас, уважаемые читатели, всякими терминами и определениями из области картографирования и экологии, напишем аналог того самого "Мышометра". Так Вы узнаете ответ на вопрос и, к тому же, узнаете как писать подобные программы-шутки.

1. Пара слов об определении размера пикселя.

В принципе, основных методов определения размера пикселя в миллиметрах в Интернете встречается два.

Первый метод - с использованием масштабного коэффициента, заданного в настройках Windows. При этом перевод длины какого-либо объекта из пикселей в миллиметры будет иметь вид:

width_mm:=width_pixels/PixelsPerInch*25.4

где width_pixels - длина объекта в пикселях, а PixelsPerInch - свойство объекта Screen, определяющее масштабный коэффициент пикселей/дюйм.

Второй способ - более сложный и заключается в определении какого-либо размера монитора (длины или ширины) в физических единицах, т.е., в нашем случае - в миллиметрах.

Для того, чтобы определить размер монитора в физиеских единицах измерения, нам достаточно воспользоваться функцией: GetDeviceCaps (DC: HDC; int:integer). С помощью этой функции можно получить специфическую информацию относительно экранного устройства. Этим устройством может быть как экран монитора, так и принтер с плоттером. В нашем случае, устройством является экран монитора.

Применительно к экрану монитора, параметр int в функции может принимать одно из следующих значений:

HORZSIZE - Ширина физического дисплея (в миллиметрах)
VERTSIZE - Высота дисплея (в миллиметрах)
HORZRES - Ширина дисплея (в пикселях)
VERTRES - Высота дисплея (в линиях растра)
LOGPIXELSX - Число пикселей на горизонтальный логический дюйм
LOGPIXELSY - Число пикселей на вертикальный логический дюйм
ASPECTX - Относительная ширина пикселя устройства, которая используется для линий рисунка
ASPECTY - Относительная высота пикселя устройства, которая используется для линий рисунка
ASPECTXY - Диагональная ширина пикселя устройства, которая используется для линии рисунка.

Как не трудно догадаться, использовать мы будем либо HORZSIZE либо VERTSIZE так как именно они возвращают размеры дисплея в мм.  Зная текущее разрешение монитора будет достаточно просто определить масштабный коэффициент, а именно - количество пикселей в одном милиметре и, исспользуя этот коэффициент, получать размеры объекта в мм.

Ну а теперь переходим к практике. Сравним два этих способа на предмет погрешностей и напишем программу, которая будет считать пробег мыши по экрану монитора.

2. Пишем свой "Мышометр" на Delphi.

Итак, запускаем Delphi, создаем новый проект и располагаем на главной форме приложения элементы, как показано на рисунке:

mishometr_1

Сразу обращу Ваше внимание, что эталонный прямоугольник добавлен просто для того, чтобы можно было визуально определять погрешности методов измерения размера объектов.

Теперь определяем необходимые переменные:

public
doUpdate: boolean; //при значении true обновляет значение пройденного расстояния
distance: single; //пройденное расстояние
LastPos: TPoint; //последняя зафиксированная позиция курсора мыши
end;

Теперь напишем процедуру, определяющую все масштабные коэффициенты, а также длину эталонного прямоугольника. Кстати, сказать длина прямоугольника составляет 100 пикселей.

procedure TForm1.Button1Click(Sender: TObject);
var DC: HDC;
begin
GetCursorPos(LastPos);
doUpdate:=true;
DC:=GetDC(Handle);
label2.Caption:=intToStr(PixelsPerInch);
label4.Caption:=CurrToStr(PixelsPerInch/25.4);
label6.Caption:=IntToStr(Screen.Width)+'x'+IntToStr(Screen.Height);
label8.Caption:=CurrToStr(Shape1.Width/PixelsPerInch*25.4);
label10.Caption:=IntToStr(GetDeviceCaps(DC, HORZSIZE));
label12.Caption:=CurrToStr(GetDeviceCaps(DC, HORZSIZE)/Screen.Width);
label14.Caption:=CurrToStr(Shape1.Width*GetDeviceCaps(DC,   HORZSIZE)/Screen.Width);
end;

Запускаем приложение. И что мы видим?

mishometr_2

Получается, что оба метода имеют определенную погрешность, но второй метод более точный. Более того, первый метод никак не отреагирует на изменение разрешения экрана, например с 1024х768 на 800х600, несмотря на то, что при этом размер объекта на экране должен увеличиться. Таким образом, для определения расстояния, пройденного мышкой по экрану монитора, воспользуемся вторым методом.

Пишем процедуру определения пройденного расстояния.

procedure TForm1.Timer1Timer(Sender: TObject);
var curPos: TPoint;
delta:real;
DC: HDC;
begin
DC:=GetDC(Handle);
GetCursorPos(curPos);
if (curPos.X<>LastPos.X)or(curPos.Y<>LastPos.Y) then
begin
if doUpdate then
begin
delta:=Sqrt(sqr(curPos.X-LastPos.X)+sqr(curPos.Y-LastPos.Y));
distance:=distance+delta;
LastPos:=curPos;
label18.Caption:=CurrToStr(distance*GetDeviceCaps(DC,  HORZSIZE)/Screen.Width*0.001);
end;
end;
end;

Интервал срабатывания таймера необходимо ставить наименьшим, но, как показывает практика, сработает максимум 18 раз в секунду, несмотря на то, что параметр Interval можно выставить равным 1, но это уже другой вопрос. Проверяем программу

mishometr_3

После нажатия кнопки "Определить" программа начинает отсчитывать пройденное растояние в метрах. Вот и все решение вопроса. Конечно, представленные методы определения расстояние не самые точные и, на самом деле в ГИС используются более сложные функции для работы со сканами изображений, но и представленные метод имеет право на существование.

Теперь можете модифицировать программу и попробовать определить скорость движения мыши :) Думаете это легко? Ничего подобного - стандартные TTimer Вам в этом вопросе не поможет, уверяю Вас.

Мой блог находят по следующим фразам

--------------------------
Кстати, если для Вас преодоление больших расстоний является ежедневной задачей, а нет машины, то лучший для Вас вариант - это идти учиться в автошколу. Для жителей Киева автошкола киев будет наилучшим из всех вариантов.
--------------------------
Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (2)

WP_Cloudy
  • Кирилл пишет:

    При вет!!! Есть один вопросик. Я работаю немного в друглй отрасли, но приложить мышку можно и там. Для меня более важно, как определить расстояние фактически пройденное оптической мышкой по рабочему столу в метрах. Есть проги?

  • Vlad пишет:

    Проги таковой не писал, но алгоритм будет 1 в 1 как в статье. Без разницы какая мыш — оптика или нет, главное — правильно определить расстояние ;)

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник

   


Недвижимость в Коломне и купить квартиру. Купить квартиру и купить квартиру в Коломне. --|--. Новый редуктор со склада --|--. sdkl.ru