I want to know the position of the cursor on a TCustomControl. How does one go about finding the coordinates?
Asked
Active
Viewed 4.0k times
3 Answers
17
GetCursorPos can be helpful if you can't handle a mouse event:
function GetCursorPosForControl(AControl: TWinControl): TPoint;
var
P: TPoint;
begin
Windows.GetCursorPos(P);
Windows.ScreenToClient(AControl.Handle, P );
result := P;
end;

splash
- 13,037
- 1
- 44
- 67
-
8FWIW, GetCursorPos doesn't work correctly on 64 bit XP/Vista when the TPoint instance is located at a memory address >2MB. MS fixed this in Windows 7. Myself, I always use GetCursorInfo to sidestep the bug. – David Heffernan Jul 11 '11 at 12:40
7
You can use MouseMove event:
procedure TCustomControl.MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Label1.Caption := IntToStr(x) + ' ' + IntToStr(y);
end;

Cosmin Prund
- 25,498
- 2
- 60
- 104

TheHorse
- 2,787
- 1
- 23
- 32
-
I am using this: procedure WMMouseMove(var message: TWMMouseMove); message WM_MOUSEMOVE; – Little Helper Jul 11 '11 at 09:08
-
1@Robrok, why handle `WM_MOUSEMOVE` directly when you can assign an `OnMouseMove` Delphi-style event handler and be done with it? If you insist on using `WM_MOUSEMOVE`, the coordinates are in `msg.Lparam`, according to [the documentation](http://msdn.microsoft.com/en-us/library/ms645616(v=vs.85).aspx) – Cosmin Prund Jul 11 '11 at 09:11
-
1+1, and I took the liberty to remove the `ShowMessage` and replace it with a `Label1.Caption := X Y`, because setting the Caption is non-modal, you can move the mouse over the control and see it update. `ShowMessage` is modal, as soon as the mouse is over the control the message pops and nothing else happens until you click "Ok" – Cosmin Prund Jul 11 '11 at 09:15
-
Sorry, i didnt see that OnMouseMove is defined in TCustomControl. :) – Little Helper Jul 11 '11 at 09:19
-
2@Robrok, if you're *writing* the control, then you shouldn't use `OnMouseMove`. That's for *users* of the control. *Writers* of controls should override the `MouseMove` method, as demonstrated here. – Rob Kennedy Jul 11 '11 at 12:59
5
If you want the cursor position when they click on the control, then use Mouse.CursorPos
to get the mouse position, and Control.ScreenToClient
to convert this to the position relative to the Control.
procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
pt: TPoint;
begin
pt := Mouse.CursorPos;
pt := Memo1.ScreenToClient(pt);
Memo1.Lines.Add(Format('x=%d, y=%d', [pt.X, pt.y]));
end;
EDIT:
As various people have pointed out, this is pointless on a mouse down event. However as TCustomControl.OnMouseDown
is protected, it may not always be readily available on third-party controls - mind you I would probably not use a control with such a flaw.
A better example might be an OnDblClick event, where no co-ordinate information is given:
procedure TForm1.DodgyControl1DblClick(Sender: TObject);
var
pt: TPoint;
begin
pt := Mouse.CursorPos;
pt := DodgyControl1.ScreenToClient(pt);
Memo1.Lines.Add(Format('x=%d, y=%d', [pt.X, pt.y]));
end;

Gerry Coll
- 5,867
- 1
- 27
- 36
-
4You get the X and Y coordinates as parameters to the event handler, relative to the control. Your code to grab the coordinates from `Mouse.CursorPos` and convert them to "control coordinates" is redundant! – Cosmin Prund Jul 11 '11 at 09:18
-
-
You say: `"If you want the cursor position when they click on the control, then use Mouse.CursorPos to get the mouse position, and Control.ScreenToClient to convert this to the position relative to the Control."`: I disagree. Use the **received** X and Y coordinates if you need to know where the user clicked. – Cosmin Prund Jul 11 '11 at 09:42
-
@Cosmin - I meant for a control that for whatever reason didn't promote OnMouseDown from protected to public. The code here could be used from OnClick or OnDblClick event. I just choose a bad event handler to call it from. From memory, the OnMouse* events weren't in early versions (maybe introduced in D5 or 6 - they are definitely in D6) – Gerry Coll Jul 11 '11 at 12:22
-
FWIW, Mouse.CursorPos is subject to the same bug that I describe in @splash's answer. – David Heffernan Jul 11 '11 at 12:41
-
methinks - **excessive surplus redundancy**, coordinates already ready to use – Premature Optimization Jul 11 '11 at 16:14
-
@Gerry This makes it a poor demo then. A good demo would suggest the use of the X and Y parameters. – David Heffernan Jul 11 '11 at 16:47