7. Programm: MouseSpeed
Das nächste Programm soll die Geschwindigkeit der Mausbewegung in m/s messen und diese auf einem "Speed-o-Meter" anzeigen. Das Speed-o-Meter soll außerdem die Maximalgeschwindigkeit in der letzten Sekunde durch einen zweiten Zeiger anzeigen. Dieser Maximalwertzeiger soll nach einer Sekunde beginnen, langsam auf die aktuelle Maximalgeschwindigkeit zurückzugehen. Zusätzlich soll die Skala des Speed-o-Meters von 1 bis 10 m/s einstellbar sein.
Um die Geschwindigkeit der Maus zu messen, müssen wir die Position der Maus verfolgen und aus der Änderung der Position und der dazwischen liegenden Zeit die Geschwindigkeit berechnen. Möchten wir die Mausgeschwindigkeit in m/s angeben, benötigen wir außerdem entsprechende Angaben zur Auflösung des Bildschirms und der Größe des Bildschirms. Man kann diese Angaben zwar von Windows übernehmen, wir gehen aber hier einen anderen Weg, um die Programmieraufgabe nicht zu vielfältig zu gestalten - wir definieren die entsprechenden Größen als Konstanten.
Eine Besonderheit ist die Forderung, dass eine zweite Nadel die Maximalgeschwindigkeit anzeigen muss und außerdem nach einer Sekunde beginnt, sich der Hauptnadel zu nähern. Dies lässt sich relativ leicht durch einen timergesteuerten Zähler erreichen, der bei jedem neuen Maximalwert auf einen bestimmten Wert gesetzt wird und durch einen Timer in regelmäßigen Abständen erniedrigt wird. Unterschreitet der Zähler einen bestimmten Wert, so wird im Timer-Event auch noch der Wert der zweiten Nadel erniedrigt.
Wie kann man nun die Geschwindigkeit der Maus messen? Am einfachsten, indem man den OnMouseMove Event des Formulars benützt. Immer wenn sich die Maus bewegt, wird dieser ausgelöst. Die Positionsänderung bestimmen wir, indem wir die Differenz zur Position beim letzten OnMouseMove Event berechnen. Dazu wird unmittelbar bevor die Routine zur Abarbeitung des Events beendet wird, die aktuelle Position in zwei globalen Variablen LastPosX und LastPosY gespeichert.
Was jetzt noch fehlt, ist eine entsprechende Zeitmessung. Im Prinzip könnte man dazu die Zeit aus der Funktion Time benützen. Allerdings hat diese Zeitangabe nur eine Auflösung von 55 ms, was für die Bestimmung der Mausgeschwindigkeit zu grob ist. Wir verwenden deshalb die Windows-Funktion GetTickCount, die die Zeit seit dem Einschalten des Computers in ms zurück gibt.
Schritt |
Aktivität |
Anmerkungen |
1. |
Erzeugen Sie eine neue Applikation und bringen Sie ein Meter, einen Scrollbar und einen Timer auf das Formular. |
Das Meter ist Teil der SDL Component Suite. |
2. |
Definieren der Konstanten und Variablen |
const
SCRWID = 0.30; // screen width in m
SCRHGT = 0.23; // screen height in m
SCRPIXX = 1400; // screen width in pixel
SCRPIXY = 1024; // screen height in pixel
MAXTIMCNT = 100; // down counter for delayed max. needle
THRESHOLD = 90; // threshold for delayed max. needle
DECAY = 0.05; // amount of decrease of max. needle
var
LastMPosX : integer;
LastMPosY : integer;
LastTime : integer;
MaxSpeed : double;
TimerCnt : integer;
|
3. |
OnMouseMove-Event programmieren |
Im OnMouseMove-Event wird zum einen die Geschwindigkeit berechnet und ausgegeben, und zum anderen der Maximalwert gesetzt und ausgegeben. Immer wenn die aktuelle Geschwindigkeit größer als der momentan gespeicherte Maximalwert ist, wird die zweite Nadel auf diesen gesetzt. Außerdem werden am Ende des Events die aktuelle Position und die Zeit gespeichert, um beim nächsten Auftreten des Events die Differenz berechnen zu können:
procedure TForm1.FormMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
var
Speed : double; // in m/s
tim : integer;
begin
tim := GetTickCount;
if tim <> LastTime then
begin
Speed := 1000*sqrt(sqr((x-LastMPosX)*SCRWID/SCRPIXX)+
sqr((y-LastMPosY)*SCRHGT/SCRPIXY))
/(tim-LastTime);
SpeedoMeter.Value := Speed;
end;
if Speed > SpeedoMeter.ValueSec then
begin
SpeedoMeter.ValueSec := Speed;
TimerCnt := MAXTIMCNT;
end;
LastMPosX := X;
LastMPosY := Y;
LastTime := tim;
end;
|
4. |
Programm versuchsweise compilieren und starten. |
Startet man jetzt das Programm, so wird die Geschwindigkeit der Maus schon angezeigt, allerdings geht der Maximalzeiger nicht mehr zurück. |
5. |
Timer-Event programmieren. |
Im Timer-Event wird der Zähler TimerCnt erniedrigt und, falls diese die Schwelle THRESHOLD unterschreitet die zweite Nadel des Meters ebenfalls erniedrigt:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if TimerCnt > 0 then
dec(TimerCnt);
if TimerCnt < THRESHOLD then
begin
if SpeedoMeter.ValueSec > 0 then
SpeedoMeter.ValueSec := SpeedoMeter.ValueSec - DECAY;
end;
end;
|
6. |
OnChange-Event des Scrollbars programmieren.
|
Zum Schluss wird noch der OnChange-Event des Scrollbars benützt, um die Skala des Meters zu verstellen:
procedure TForm1.SbarScaleChange(Sender: TObject);
begin
SpeedoMeter.MeterMaxValue := SBarScale.Position/10;
end;
|
|