2009-11-12 99 views
11

我正在向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; 

回答

21

Mouse.CursorPos返回屏幕座標中的鼠標位置。您可以通過調用控件的ScreenToClient方法將其轉換爲「客戶」座標,即相對於控件的座標。

所以你必須代碼是這樣的:

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; 

,將讓你知道,如果它的控制內。

從它的外觀你正在實施與滾輪滾動?如果是這樣,不要忘記調用SystemParametersInfo with SPI_GETWHEELSCROLLLINES或可能,如果它是在您的Delphi版本中,Mouse.WheelScrollLines找出多少行滾動每個鼠標滾輪增量。這對您的應用意味着什麼可能取決於您在滾動框中的內容。

如果您打算實現中間點擊並拖動滾動(我在這裏進行推測,這完全超出了您所問的範圍),您可能想在鼠標離開控件後獲得鼠標事件或者形成,直到用戶放開按鈕爲止。如果是這樣,看看SetCaptureReleaseCapturethis article。 (該文章使用這些來查看鼠標是否超過了控件(那裏,一個表單),儘管我認爲我上面寫的代碼是針對該特定問題的更好的解決方案 - 要點是它們在獲取鼠標信息時非常方便,即使在鼠標是不是在你的窗體或控件)

(編輯:我只注意到德爾福2010中的TMouse有包裝這些API調用,WheelScrollLinesCapture屬性我不知道他們是如何最近增加了 - 我可能只是之前沒有注意到它們 - 但是假設它們是新的,因爲你沒有說你使用的是什麼版本的Delphi,我將離開上面的文本和WinAPI引用。如果你使用的是最新版本看看the TMouse documentation。)

+0

完美,我已經到達ScreenToClient部分,但不知道我是否獲得了正確的值。謝謝您的幫助。 – smartins 2009-11-12 15:42:25

0

我的德爾福知識是有點生疏,但不應該有的MouseEnter,鼠標離開事件?快速谷歌顯示this。這對你有幫助嗎?

+0

我需要使用的程序FormMouseWheel是因爲我需要響應鼠標輪的移動,而不是進入和離開事件。 – smartins 2009-11-12 12:17:14

+0

是的,但是您可以使用這些事件來了解鼠標是否進入或離開(=>在裏面)滾動框。 – 2009-11-12 12:26:22

+0

mouseenter/leave方式的問題在於,這些事件也是針對子控件觸發的。所以David M的解決方案得到了我的投票。 – 2009-11-12 15:23:17

1

我使用相同的方法使用鼠標滾動我的滾動條。

這是表單的MouseWheel事件的事件處理程序。

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; 

您可以使用此功能檢查,如果鼠標的屏幕座標是在你的控制:如果您按下Shift鍵的同時滾動它會水平滾動

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; 
相關問題