Как определить, находится ли курсор мыши внутри элемента управления
Я добавляю поддержку перемещения колеса мыши к TScrollBox (используя процедуру FormMouseWheel), и мне нужно определить, находится ли мышь внутри компонента.
В основном мне нужно определить, находится ли мышь внутри TScrollBox, чтобы затем обрабатывать код прокрутки.
Любая идея о том, как это сделать?
EDIT: здесь код (включая ответ на этот вопрос), поскольку он может помочь другим:
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;
Ответы
Ответ 1
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
с SPI_GETWHEELSCROLLLINES
или, возможно, если это в вашей версии Delphi, Mouse.WheelScrollLines
, чтобы узнать, сколько строк прокручивается на шаг мыши. Что это значит для вашего приложения, вероятно, зависит от того, что у вас есть в прокрутке.
Если вы планируете также осуществлять прокрутку по середине щелчка и перетаскивания (я размышляю здесь, это далеко не так, как вы просили), вы можете захотеть получить события мыши после того, как мышь оставила элемент управления или пока пользователь не запустит кнопку, например. Если да, взгляните на SetCapture
и ReleaseCapture
и в этой статье. (В этой статье мы видим, что мышь находится над элементом управления (там, форма), хотя я думаю, что код, который я написал выше, является лучшим решением для этой конкретной проблемы, так как они удобны для получения информации о мыши, даже если мышь не над вашей формой или контролем.)
(Edit: Я только заметил, что Delphi 2010 TMouse
имеет свойства, которые обертывают эти вызовы API, WheelScrollLines
и Capture
. Я не уверен, как недавно они были добавлены - я бы просто не заметил их раньше, - но, исходя из предположения, они новы и потому что вы не говорите, какую версию Delphi вы используете. Я оставляю приведенный выше текст и ссылки на WinAPI. Если вы используете недавнюю версию, посмотрите документация TMouse
.)
Ответ 2
Я использую тот же метод для прокрутки моих scrollboxes с помощью мыши.
Это обработчик событий для события 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;
Вы можете использовать эту функцию, чтобы проверить, находится ли координата экрана мыши над вашим контролем:
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;
Ответ 3
Знание My Delphi немного ржавое, но не должно быть событий MouseEnter, MouseLeave? Быстрый google показал этот. Это поможет вам?