Delphi 如何确定鼠标光标是否位于控件内

Delphi 如何确定鼠标光标是否位于控件内,delphi,Delphi,我正在将鼠标滚轮移动支持添加到TScrollBox(使用FormMouseWheel过程),我需要确定鼠标是否位于组件内部 基本上,我需要确定鼠标是否在TScrollBox中,这样我就可以相应地处理滚动代码 你知道怎么做吗 编辑:以下是代码(包括此问题的答案),因为它可能会帮助其他人: procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: T

我正在将鼠标滚轮移动支持添加到TScrollBox(使用FormMouseWheel过程),我需要确定鼠标是否位于组件内部

基本上,我需要确定鼠标是否在TScrollBox中,这样我就可以相应地处理滚动代码

你知道怎么做吗

编辑:以下是代码(包括此问题的答案),因为它可能会帮助其他人:

   procedure TForm1.FormMouseWheel(Sender: TObject;
  Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
  var Handled: Boolean);
var
  Msg: Cardinal;
  Code: Cardinal;
  I, ScrollLines: Integer;

  ScrollBoxCursosPos: TPoint;
begin
  //position of the mouse cursor related to TScrollBox
  ScrollBoxCursosPos := ScrollBox1.ScreenToClient(Mouse.CursorPos);

  if (PtInRect(ScrollBox1.ClientRect, ScrollBoxCursosPos)) then
  begin
    Handled := True;
    If ssShift In Shift Then
      msg := WM_HSCROLL
    Else
      msg := WM_VSCROLL;

    If WheelDelta < 0 Then
      code := SB_LINEDOWN
    Else
      code := SB_LINEUP;

    ScrollLines:= Mouse.WheelScrollLines * 3;
    for I:= 1 to ScrollLines do
      ScrollBox1.Perform(Msg, Code, 0);
    ScrollBox1.Perform(Msg, SB_ENDSCROLL, 0);
  end;
end;
程序TForm1.FormMouseWheel(发送方:ToObject;
Shift:tShift状态;WheelDelta:Integer;鼠标点:t点;
变量:布尔值);
变量
Msg:红衣主教;
代码:红衣主教;
一、 滚动线:整数;
ScrollBoxCursorPos:TPoint;
开始
//与滚动框相关的鼠标光标位置
ScrollBoxCursorPos:=ScrollBox1.ScreenToClient(Mouse.CursorPos);
如果(PtInRect(ScrollBox1.ClientRect,ScrollBoxCursorsPos)),则
开始
已处理:=真;
如果是轮班制,那么
msg:=wmhscroll
其他的
msg:=WM_VSCROLL;
如果WheelDelta<0,则
代码:=SB\u下线
其他的
代码:=SB_排列;
滚动线:=鼠标滚轮滚动线*3;
对于I:=1的滚动行
ScrollBox1.Perform(消息,代码,0);
ScrollBox1.Perform(Msg,SB_ENDSCROLL,0);
结束;
结束;

我的Delphi知识有些生疏,但不应该有MouseEnter、MouseLeave事件吗?一个快速的谷歌显示。这对您有帮助吗?

返回屏幕坐标中的鼠标位置。您可以通过调用控件的方法将其转换为“客户端”坐标,即相对于控件的坐标

因此,您将获得如下代码:

var
  MyPoint : TPoint;
begin
  MyPoint := ScrollBox1.ScreenToClient(Mouse.CursorPos);
  if PtInRect(ScrollBox1.ClientRect, MyPoint) then
  begin
    // Mouse is inside the control, do something here
  end;
end;
这会让你知道它是否在控制范围内

从外观上看,您正在使用鼠标滚轮实现滚动?如果是这样,请不要忘记调用,或者如果是在您的Delphi版本中,也可以调用,以了解每个鼠标滚轮增量要滚动多少行。这对你的应用程序意味着什么可能取决于你在滚动框中拥有什么

如果您还计划实现鼠标中键点击和拖动滚动(我在这里猜测,这已经远远超出了您的要求),您可能希望在鼠标离开控件或窗体后获取鼠标事件,直到用户松开按钮为止,例如。如果是,请查看和。(那篇文章使用这些工具来查看鼠标是否在控件(那里,一个窗体)上,尽管我认为我上面写的代码是解决这个特定问题的更好的方法——重点是即使鼠标不在窗体或控件上,它们也能方便地获取鼠标信息。)


(编辑:我刚刚注意到Delphi 2010的
TMouse
具有包装这些API调用的属性。我不确定它们是最近添加的-我以前可能没有注意到它们-但假设它们是新版本,因为您没有说明您使用的是什么版本的Delphi,所以我保留了上面的文本和WinAPI引用。如果您使用的是最新版本,请查看。)

我使用相同的方法使用鼠标滚动滚动框

这是窗体MouseWheel事件的事件处理程序。如果在滚动时按shift键,它将水平滚动:

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  Msg: Cardinal;
  Code: Cardinal;
  I, ScrollLines: Integer;    
begin
  if IsCoordinateOverControl(MousePos, ScrollBox1) then
  begin
    Handled := True;
    If ssShift In Shift Then
      Msg := WM_HSCROLL
    Else
      Msg := WM_VSCROLL;

    If WheelDelta < 0 Then
      Code := SB_LINEDOWN
    Else
      Code := SB_LINEUP;

    ScrollLines := Mouse.WheelScrollLines * 3;
    for I := 1 to ScrollLines do
      ScrollBox1.Perform(Msg, Code, 0);
    ScrollBox1.Perform(Msg, SB_ENDSCROLL, 0);
  end;
end;

我需要使用的过程是FormMouseWheel,因为我需要响应鼠标滚轮的移动,而不是进入和离开事件。是的,但您可以使用这些事件来了解鼠标是进入还是离开(=>在内部)滚动框。mouseenter/leave way的问题是,这些事件也会为子控件触发。因此,David M的解决方案得到了我的投票。很好,我已经到达ScreenToClient部分,但不确定我是否得到了正确的值。感谢帮助。
function IsCoordinateOverControl(screenCoordinate: TPoint; control: TControl): Boolean;
var
  p: TPoint;
  r: TRect;
begin
  Result := False;
  p := control.ScreenToClient(screenCoordinate);
  r := Rect(0, 0, control.Width, control.Height);
  if PtInRect(r, p) then
    Result := True;
end;