Browse Source

Added mousewheel support to ScrollViewer.

pull/10/head
Steven Kirk 12 years ago
parent
commit
7f90f5c8e6
  1. 18
      Perspex.Controls/Presenters/ScrollContentPresenter.cs
  2. 7
      Perspex.Controls/ScrollViewer.cs
  3. 14
      Perspex.Input/InputElement.cs
  4. 29
      Perspex.Input/MouseDevice.cs
  5. 2
      Perspex.Input/Perspex.Input.csproj
  6. 13
      Perspex.Input/PointerWheelEventArgs.cs
  7. 1
      Perspex.Input/Raw/RawMouseEventArgs.cs
  8. 26
      Perspex.Input/Raw/RawMouseWheelEventArgs.cs
  9. 17
      Windows/Perspex.Win32/WindowImpl.cs

18
Perspex.Controls/Presenters/ScrollContentPresenter.cs

@ -6,7 +6,9 @@
namespace Perspex.Controls.Presenters
{
using System;
using System.Linq;
using Perspex.Input;
using Perspex.Layout;
public class ScrollContentPresenter : ContentPresenter
@ -20,9 +22,9 @@ namespace Perspex.Controls.Presenters
public static readonly PerspexProperty<Size> ViewportProperty =
ScrollViewer.ViewportProperty.AddOwner<ScrollContentPresenter>();
public ScrollContentPresenter()
static ScrollContentPresenter()
{
Control.AffectsRender(OffsetProperty);
Control.AffectsArrange(OffsetProperty);
}
public Size Extent
@ -74,5 +76,17 @@ namespace Perspex.Controls.Presenters
return new Size();
}
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{
if (this.Extent.Height > this.Viewport.Height)
{
var y = this.Offset.Y + (-e.Delta.Y * 50);
y = Math.Max(y, 0);
y = Math.Min(y, Extent.Height - Viewport.Height);
this.Offset = new Vector(this.Offset.X, y);
e.Handled = true;
}
}
}
}

7
Perspex.Controls/ScrollViewer.cs

@ -6,6 +6,7 @@
namespace Perspex.Controls
{
using System;
using System.Reactive.Linq;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
@ -89,6 +90,12 @@ namespace Perspex.Controls
this.verticalScrollBar.GetObservable(ScrollBar.ValueProperty))
.Select(x => new Vector(x[0], x[1]));
this.presenter.GetObservable(ScrollContentPresenter.OffsetProperty).Subscribe(x =>
{
this.horizontalScrollBar.Value = x.X;
this.verticalScrollBar.Value = x.Y;
});
this.Bind(OffsetProperty, offset);
}
}

14
Perspex.Input/InputElement.cs

@ -48,6 +48,9 @@ namespace Perspex.Input
public static readonly RoutedEvent<PointerEventArgs> PointerReleasedEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerReleased", RoutingStrategy.Bubble);
public static readonly RoutedEvent<PointerEventArgs> PointerWheelChangedEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerWheelChanged", RoutingStrategy.Bubble);
public InputElement()
{
this.GotFocus += (_, e) => this.OnGotFocus(e);
@ -59,6 +62,7 @@ namespace Perspex.Input
this.PointerMoved += (_, e) => this.OnPointerMoved(e);
this.PointerPressed += (_, e) => this.OnPointerPressed(e);
this.PointerReleased += (_, e) => this.OnPointerReleased(e);
this.PointerWheelChanged += (_, e) => this.OnPointerWheelChanged(e);
}
public event EventHandler<RoutedEventArgs> GotFocus
@ -115,6 +119,12 @@ namespace Perspex.Input
remove { this.RemoveHandler(PointerReleasedEvent, value); }
}
public event EventHandler<PointerWheelEventArgs> PointerWheelChanged
{
add { this.AddHandler(PointerWheelChangedEvent, value); }
remove { this.RemoveHandler(PointerWheelChangedEvent, value); }
}
public bool Focusable
{
get { return this.GetValue(FocusableProperty); }
@ -177,5 +187,9 @@ namespace Perspex.Input
protected virtual void OnPointerReleased(PointerEventArgs e)
{
}
protected virtual void OnPointerWheelChanged(PointerWheelEventArgs e)
{
}
}
}

29
Perspex.Input/MouseDevice.cs

@ -76,6 +76,13 @@ namespace Perspex.Input
case RawMouseEventType.LeftButtonUp:
this.MouseUp((IMouseDevice)e.Device, (IVisual)e.Root, e.Position);
break;
case RawMouseEventType.Wheel:
this.MouseWheel(
(IMouseDevice)e.Device,
(IVisual)e.Root,
e.Position,
((RawMouseWheelEventArgs)e).Delta);
break;
}
}
@ -162,6 +169,28 @@ namespace Perspex.Input
}
}
private void MouseWheel(IMouseDevice device, IVisual visual, Point p, Vector delta)
{
IVisual hit = visual.GetVisualAt(p);
if (hit != null)
{
IInteractive source = this.GetSource(hit);
if (source != null)
{
source.RaiseEvent(new PointerWheelEventArgs
{
Device = this,
RoutedEvent = InputElement.PointerWheelChangedEvent,
OriginalSource = source,
Source = source,
Delta = delta,
});
}
}
}
private IInputElement GetFocusable(IVisual hit)
{
return this.Captured as IInputElement ??

2
Perspex.Input/Perspex.Input.csproj

@ -68,6 +68,8 @@
<Compile Include="IPointerDevice.cs" />
<Compile Include="Key.cs" />
<Compile Include="KeyboardDevice.cs" />
<Compile Include="PointerWheelEventArgs.cs" />
<Compile Include="Raw\RawMouseWheelEventArgs.cs" />
<Compile Include="Raw\RawSizeEventArgs.cs" />
<Compile Include="VectorEventArgs.cs" />
<Compile Include="KeyEventArgs.cs" />

13
Perspex.Input/PointerWheelEventArgs.cs

@ -0,0 +1,13 @@
// -----------------------------------------------------------------------
// <copyright file="PointerWheelEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
public class PointerWheelEventArgs : PointerEventArgs
{
public Vector Delta { get; set; }
}
}

1
Perspex.Input/Raw/RawMouseEventArgs.cs

@ -14,6 +14,7 @@ namespace Perspex.Input.Raw
Move,
LeftButtonDown,
LeftButtonUp,
Wheel,
}
public class RawMouseEventArgs : RawInputEventArgs

26
Perspex.Input/Raw/RawMouseWheelEventArgs.cs

@ -0,0 +1,26 @@
// -----------------------------------------------------------------------
// <copyright file="RawMouseEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input.Raw
{
using System;
using Perspex.Layout;
public class RawMouseWheelEventArgs : RawMouseEventArgs
{
public RawMouseWheelEventArgs(
IInputDevice device,
ILayoutRoot root,
Point position,
Vector delta)
: base(device, root, RawMouseEventType.Wheel, position)
{
this.Delta = delta;
}
public Vector Delta { get; private set; }
}
}

17
Windows/Perspex.Win32/WindowImpl.cs

@ -134,9 +134,18 @@ namespace Perspex.Win32
this.Handle = new PlatformHandle(this.hwnd, "HWND");
}
private Point ScreenToClient(uint x, uint y)
{
var p = new UnmanagedMethods.POINT { X = (int)x, Y = (int)y };
UnmanagedMethods.ScreenToClient(this.hwnd, ref p);
return new Point(p.X, p.Y);
}
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
const double WheelDelta = 120.0;
RawInputEventArgs e = null;
WindowsMouseDevice.Instance.CurrentWindow = this;
@ -184,6 +193,14 @@ namespace Perspex.Win32
new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
break;
case UnmanagedMethods.WindowsMessage.WM_MOUSEWHEEL:
e = new RawMouseWheelEventArgs(
WindowsMouseDevice.Instance,
this.owner,
this.ScreenToClient((uint)lParam & 0xffff, (uint)lParam >> 16),
new Vector(0, ((int)wParam >> 16) / WheelDelta));
break;
case UnmanagedMethods.WindowsMessage.WM_PAINT:
UnmanagedMethods.PAINTSTRUCT ps;

Loading…
Cancel
Save