Solved

is there a way to find out how many centimeters was a mouse moved...

Posted on 2002-06-19
18
191 Views
Last Modified: 2010-04-04
from on elocation to another? I just want to write a simple program to see how many cms. a mouse is moved during a typical user session. I know this is just fun stuff... (or do you think is there any application for that?)...

best regards,
Manuel Lopez (lopem)
0
Comment
Question by:lopem
  • 6
  • 4
  • 3
  • +3
18 Comments
 
LVL 3

Expert Comment

by:tongalite
ID: 7093584
Hi Manuel,
Interesting idea! You want to track the mouse and calculate the distance it traveled during a certain time (or user session)?
Hm.... I don't have a clue :-)

Listening:)
tongalite
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7093600
Do you mean cm on desk or cursor on screen?
Both are impossible. The relation of pixels to cm on screen is inaccurate or outright wrong.
The mouse only emits mickeys which have no constant relation to cm for different mice. Not to mention acceleration.
0
 
LVL 3

Author Comment

by:lopem
ID: 7093631
Tongalite,

yes, i want to track the mouse and calculate the distance travelled...

Robert,

So you think there is no way at all to do this, right?

best regards
Manuel Lopez (lopem)

Ps. BTW, check

   http://www.experts-exchange.com/delphi/Q_20311250.html

you will find some of my code around word and OLE automation.
0
 
LVL 3

Author Comment

by:lopem
ID: 7094001
I forgot... I was thinking... How software like photoshop can handle rulers for example? How it knows the mouse is moving few cms?

On the other hand, how I can keep track of how many click a user have done (not only in my application)? Any ideas?

best regards,
Manuel Lopez (lopem)

0
 
LVL 9

Expert Comment

by:ginsonic
ID: 7094731
For the second question is easy . Just write a mouse hook and count the click. If need a sample project that work in XP platform too ( here is a modification ) ...
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7094736
Photoshop rulers show cm in relation to the pictures. Each picture has a dpi value (at least implicitly). So the cm of the rulers need not correlate to physical cm on screen.
0
 
LVL 3

Author Comment

by:lopem
ID: 7094766
Ginsonic,

Have any sample project to show me? Can it work on win98?
best regards,
Manuel Lopez (lopem)
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 7096614
Go to http://www.q3.nu/trucomania/fting.html and look for
tip 414 - Hooks: Mouse hook at system level by Radikal (Q3 Team)
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 7096617
A good sample with codes for dll hook and sample project.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 2

Expert Comment

by:Griffon
ID: 7098727
surely you could have an active program running at the bottom of the screen that would record the number of pixels up and the number of pixels across that the mouse moves. this pixel information could then be cross correlated with the number of pixels traveled by a physical mouse move of 1cm (although this would need calibration for each machine as the sensitivity varies with settings and mouse type) and it would probably take up a fair bit of processing power but I dont see why it is not possable.

No of pixels traveled do relate to CMs because the exact same distance moved by an identical physical mouse with the same settings will move the same number of pixels.

if you meant movements of the cursor then CMs then you should be able to do that by defining areas on the screen and when the mouse moves into a new one increment by a cm.

when you have the correllation of either methods you simply have a timer that when it reaches a certain number it will calculate the distance traveled over that time and thus the KPH.

Now I am not saying that I would like to write it but I Believe that I could if I had to.
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 20 total points
ID: 7100037
if you can get some user input as to the size of their monitor screen you could get the distance the cursor moves. I used this code to get mouse movement, and it seemed real accuate. I used a Journal hook, but you could use a .DLL mouse hook if you wanted to




var
  Form1: TForm1;
  JHook: THandle;
  Track: Boolean;
  PixDist: Int64;
  EndPos, StartPos: TPoint;

implementation

{$R *.DFM}

uses Math;

function JHookProc(Code:integer; wParam: Longint; var EventStrut: TEVENTMSG): Longint; stdcall;
begin
{this is the JournalRecordProc}
Result := CallNextHookEx(JHook, Code, wParam, Longint(@EventStrut) );
if Code < 0 then Exit;

if Code = HC_ACTION then
  begin
  if EventStrut.message = WM_MOUSEMOVE then
    begin
    EndPos.x := EventStrut.paramL;
    EndPos.y := EventStrut.paramH;
    Form1.Label1.Caption := 'X '+IntToStr(EventStrut.paramL)+' Y '+IntToStr(EventStrut.paramH);
    PixDist := PixDist+Round(Sqrt(SumOfSquares([abs(EndPos.y-StartPos.y),abs(EndPos.x-StartPos.x)])));
    StartPos.x := EndPos.x;
    StartPos.y := EndPos.y;
    end;
  end;
end;

procedure TForm1.sbut_JHookClick(Sender: TObject);
begin
if Track then Exit;

GetCursorPos(StartPos);
PixDist := 0;
JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JHookProc, 0, 0);
if JHook > 0 then
  begin
  Track := True;
  end else
  ShowMessage('No Journal Hook availible');
end;


procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
Handled := False;
if (Msg.message = WM_CANCELJOURNAL) and Track then
  JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JHookProc, 0, 0);
end;


procedure TForm1.sbut_EndHookClick(Sender: TObject);
begin
Track := False;
UnhookWindowsHookEx(JHook);
JHook := 0;
Label2.Caption := IntTostr(Round(PixDist/3.555))+' Millimeters';
{I measured my monitor screen and it was 324 millimeters wide
resolution was 1152x864 so 1152 / 324 is 3.555}
end;
0
 
LVL 3

Author Comment

by:lopem
ID: 7100834
Hi Slick812,

I feel dumb. I dont really understand the hook code but I guess with it you can control what the mouse is doing in all windows and not only in the delphi application.

In any case, I had two labesl in my form and copied your code. I defined the hook procedures inside the form class... Now tell me, how I use the hook procedures? I cant find it by myself...

This is my code (of course, with your code added). What else do I need?

best regards
Manuel Lopez (lopem)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    procedure sbut_JHookClick(sender: TObject);
    procedure sbut_EndHookClick(Sender: TObject);
    procedure ApplicationEvents1Message(var Msg: tagMSG;
                                        var Handled: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
    Form1: TForm1;
    JHook: THandle;
    Track: Boolean;
    PixDist: Int64;
    EndPos, StartPos: TPoint;

implementation

{$R *.DFM}

uses Math;

function JHookProc(Code:integer; wParam: Longint; var EventStrut: TEVENTMSG): Longint; stdcall;
begin
  {this is the JournalRecordProc}
  Result := CallNextHookEx(JHook, Code, wParam, Longint(@EventStrut) );
  if Code < 0 then Exit;
  if Code = HC_ACTION then
  begin
    if EventStrut.message = WM_MOUSEMOVE then
    begin
      EndPos.x := EventStrut.paramL;
      EndPos.y := EventStrut.paramH;
      Form1.Label1.Caption := 'X '+IntToStr(EventStrut.paramL)+' Y '+IntToStr(EventStrut.paramH);
      PixDist := PixDist+Round(Sqrt(SumOfSquares([abs(EndPos.y-StartPos.y),abs(EndPos.x-StartPos.x)])));
      StartPos.x := EndPos.x;
      StartPos.y := EndPos.y;
    end;
  end;
end;

procedure TForm1.sbut_JHookClick(Sender: TObject);
begin
  if Track then Exit;
  GetCursorPos(StartPos);
  PixDist := 0;
  JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JHookProc, 0, 0);
  if JHook > 0 then
  begin
    Track := True;
  end else
    ShowMessage('No Journal Hook availible');
end;


procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
  Handled := False;
  if (Msg.message = WM_CANCELJOURNAL) and Track then
  JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JHookProc, 0, 0);
end;


procedure TForm1.sbut_EndHookClick(Sender: TObject);
begin
  Track := False;
  UnhookWindowsHookEx(JHook);
  JHook := 0;
  Label2.Caption := IntTostr(Round(PixDist/3.555))+' Millimeters';
  {I measured my monitor screen and it was 324 millimeters wide
  resolution was 1152x864 so 1152 / 324 is 3.555}
end;

end.




0
 
LVL 33

Expert Comment

by:Slick812
ID: 7100857
added mouse clicks count



var
  LMouseClicks, RMouseClks, BTime: Cardinal;




in the function JHookProc

  if EventStrut.message = WM_LBUTTONDOWN then
    BTime := EventStrut.time;

  if EventStrut.message = WM_LBUTTONUP then
    begin
    if EventStrut.time - BTime < 333 then
    Inc(LMouseClicks);
    Form1.Label3.Caption := IntToStr(LMouseClicks)+' Left Mouse Clicks';
    end;
  if EventStrut.message = WM_RBUTTONDOWN then
    BTime := EventStrut.time;

  if EventStrut.message = WM_RBUTTONUP then
    begin
    if EventStrut.time - BTime < 333 then
    Inc(RMouseClks);
    Form1.Label4.Caption := IntToStr(RMouseClks)+' Right Mouse Clicks';
    end;


- - - - -  - - - - - - - -

guess to be sure hook is gone

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnhookWindowsHookEx(JHook);
end;
0
 
LVL 33

Expert Comment

by:Slick812
ID: 7101315
Now tell me, how I use the hook procedures?
I learned alot about hooks by reading the windows API Help, look up Hooks in the index.
Hooks are used to tap into the windows Messaging transfers and get info (the messages). Windows has many different types of hooks, each type provides access to a different portion of the Windows message-handling mechanism. A hook procedure can be global, monitoring messages for all threads in the system, or it can be thread specific, monitoring messages for only an individual thread. The Journaling hook I have used is unique, unlike any other type of hook. It is meant to be used for recording mouse and keyboard events in to an array of TEVENTMSG and then played back later with a JournalPlayBack hook (to make macros). When you hook it with the
JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JHookProc, 0, 0)
then the JHookProc function is sent the three parameters
(Code:integer; wParam: Longint; var EventStrut: TEVENTMSG)
the Code is not useful in a journaling hook since all code will be HC_ACTION, but you do use it in other hooks. To use the J Hook function you read the fields of the  TEVENTMSG record -

tagEVENTMSG = packed record
    message: UINT;
    paramL: UINT;
    paramH: UINT;
    time: DWORD;
    hwnd: HWND;
  end;

the message will be a mouse or keboard message like WM_MOUSEMOVE or WM_KEYUP and the paramL and paramH will vary depending on the message. With the a mouse messages like WM_MOUSEMOVE the paramL is the X screen corordinate of the cursor and the paramH is the Y. The time is the tick count and the hwnd is the Handle of the window the message is sent to. With the WM_KEYDOWN message the paramL has some info about which key was pressed the LOWORD LOWBYTE has the Char and the LOWORD HIBYTE has the physical location of the key so you could use
if Chr(LOBYTE(LOWORD(EventStrut.paramL)))='S' then
to test for S.

What else do you need- - - - you need 2 buttons, I used speed buttons (sbut_) and a TApplicationEvents, you click the sbut_JHook button to start the jhook and you click the sbut_EndHook button to end it. Here is the top half of the code



unit JHook1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, AppEvnts;

type
  TForm1 = class(TForm)
    sbut_JHook: TSpeedButton;
    sbut_EndHook: TSpeedButton;
    ApplicationEvents1: TApplicationEvents;
    Label1: TLabel;
    Label2: TLabel;
    procedure sbut_JHookClick(Sender: TObject);
    procedure sbut_EndHookClick(Sender: TObject);
    procedure ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
  private
    { Private declarations }
    Track: Boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  JHook: THandle;
  PixDist: Int64;
  EndPos, StartPos: TPoint;

implementation

- - - - - - - - - - - - - -  - - -

hope this helps
0
 
LVL 3

Author Comment

by:lopem
ID: 7101317
Hi Slick812,

I found more info about hooks in the about.com site. Thansk a lot for the info, I didnt know about this sort of functions...  

On  the other hand, I guess I can have a table with size of monitor, size of screen resolution and the equivalent in cms for a mouse pixel move. That way I can finally get this JFF ("just for fun") application running. Am I right?

Thanks a lot!... Great job. In fact I learned a lot...

Bets regards
manuel Lopez (lopem)
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7101320
The correlation of pixels (mickeys to be precise) to cm on screen will always be inaccurate even with calibration.
The speed and acceleration settings of the system and maybe also the drivers will produce rounding errors.
Nowadays you can also have USB mice which are allowed to generate 16 bit deltas instead of the usual 8 bit deltas. This makes the calculations even more problematic.
0
 
LVL 3

Author Comment

by:lopem
ID: 7101744
Hi Robert,

I guess you are right... Strictly speaking probably there is no way to make a real calculation for how many cms a mouse moved form one location to other, but anyway, I think a gross approximation can be enough. Do you think there is an application for this kind of stuff?

best regards
Manuel Lopez (lopem)
0
 
LVL 33

Expert Comment

by:Slick812
ID: 7102254
This measures pixel distances from the cursor position when a mouse move message is generated, I can't correlate that to the mouse type or mouse driver or acceleration. I tried several measuements, following a right triangle with my cursor, and measured the distance on screen with a ruler, it seemed to be within a couple of millimeters for a 400 mm move, but my cursor move ment was not machine precision. But I can't see how any accuacy variation would matter anyway since it's only for curiosity, I doubt if I would try to charge a fee per meter of  movement of a mouse cursor on a rental computer. So no I can not think of any application for this except to let some one know the approximate distance and number of mouse clicks and keystroks, to let them know how much it is.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now