当鼠标悬停在已放置在主机控件上的控件上时,我想得到鼠标的绝对坐标。例如。主机控制是面板按钮放置在面板上。当鼠标悬停在按钮上时,我希望相对于面板获得鼠标坐标。
我已经尝试过显而易见的事情,看看我得到了什么:
procedure TfmWorkingScreen.pnlScreenAreaMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
begin
StatusBar1.SimpleText := 'Left ' + IntToStr(X) + ' Right ' + IntToStr(Y);
end;
显然,这仅在鼠标位于面板控件上时才有效。有没有办法获得所需的坐标?
答案 0 :(得分:6)
将OnMouseMove
事件处理程序添加到子控件,即示例中的按钮。在OnMouseMove
事件处理程序中,您会收到与子控件的客户端区域相关的X
和Y
光标坐标。如果主机控件是其OnMouseMove
事件已触发的控件的直接父级,则使用控件的ClientToParent
方法:
var
PosRelParent: TPoint:
....
PosRelParent := (Sender as TControl).ClientToParent(Point(X, Y));
如果父控件可能在父/子关系的进一步向上,则可以将父控件传递给ClientToParent
:
PosRelParent := (Sender as TControl).ClientToParent(Point(X, Y), TheParent);
如果您希望表达相对于某个任意控件客户区的位置,那么您可以通过屏幕坐标转换,这是一个全局参考框架。
var
PosRelScreen, PosRelOtherControl: TPoint:
OtherControl: TWinControl;
....
PosRelScreen := (Sender as TControl).ClientToScreen(Point(X, Y));
PosRelOtherControl := OtherControl.ScreenToClient(PosRelScreen);
作为最终产品,您可以使用GetMessagePos
获取通过调用GetMessage
检索到的最后一条消息的鼠标屏幕相对坐标。
var
MsgPos: TPoint;
....
MsgPos := TSmallPoint(GetMessagePos());
此时,您可以使用SomeControl.ScreenToClient(MsgPos)
获取光标相对于该控件的客户区域的坐标。显然,如果您处于由排队的鼠标消息触发的事件处理程序中,则调用GetMessagePos
才有意义。
答案 1 :(得分:0)
如果你想在你的程序之外听你的鼠标,你需要创建一个鼠标钩。
我早些时候向About.com提交了一篇文章和源代码:http://delphi.about.com/od/windowsshellapi/a/delphi-hooks.htm
如果这有你的兴趣,我很乐意深入研究。