| File: System\Windows\InterOp\HwndPanningFeedback.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationCore\PresentationCore.csproj (PresentationCore) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // using System.Runtime.InteropServices; using System.Windows.Threading; using MS.Win32; namespace System.Windows.Interop { /// <summary> /// Helper class to provide window feedback that panning has hit an edge. /// </summary> internal class HwndPanningFeedback { /// <summary> /// Instantiates a new instance of this class. /// </summary> /// <param name="hwndSource">The HWND on which to provide feedback.</param> public HwndPanningFeedback(HwndSource hwndSource) { ArgumentNullException.ThrowIfNull(hwndSource); _hwndSource = hwndSource; } private static bool IsSupported { get { return OperatingSystemVersionCheck.IsVersionOrLater(OperatingSystemVersion.Windows7); } } /// <summary> /// Returns the handle of the current window. /// </summary> private HandleRef Handle { get { if (_hwndSource != null) { IntPtr handle = _hwndSource.Handle; if (handle != IntPtr.Zero) { return new HandleRef(_hwndSource, handle); } } return new HandleRef(); } } /// <summary> /// Moves the window by the offset. /// Used to provide feedback that panning has hit an edge. /// </summary> /// <param name="totalOverpanOffset">The total offset relative to the original location.</param> /// <param name="inInertia">Whether the edge was hit due to inertia or the user panning.</param> public void UpdatePanningFeedback(Vector totalOverpanOffset, bool inInertia) { if ((_hwndSource != null) && IsSupported) { if (!_isProvidingPanningFeedback) { _isProvidingPanningFeedback = UnsafeNativeMethods.BeginPanningFeedback(Handle); } if (_isProvidingPanningFeedback) { var deviceOffset = _hwndSource.TransformToDevice((Point)totalOverpanOffset); _deviceOffsetX = (int)deviceOffset.X; _deviceOffsetY = (int)deviceOffset.Y; _inInertia = inInertia; if (_updatePanningOperation == null) { _updatePanningOperation = _hwndSource.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(OnUpdatePanningFeedback), this); } } } } private object OnUpdatePanningFeedback(object args) { HwndPanningFeedback panningFeedback = (HwndPanningFeedback)args; _updatePanningOperation = null; UnsafeNativeMethods.UpdatePanningFeedback(panningFeedback.Handle, panningFeedback._deviceOffsetX, panningFeedback._deviceOffsetY, panningFeedback._inInertia); return null; } private int _deviceOffsetX; private int _deviceOffsetY; private bool _inInertia; private DispatcherOperation _updatePanningOperation; /// <summary> /// Moves the window back to its original position. /// Used to provide feedback that panning has hit an edge. /// </summary> /// <param name="animateBack">Whether to animate or snap back to the original position</param> public void EndPanningFeedback(bool animateBack) { if (_hwndSource != null && _isProvidingPanningFeedback) { _isProvidingPanningFeedback = false; _updatePanningOperation?.Abort(); _updatePanningOperation = null; UnsafeNativeMethods.EndPanningFeedback(Handle, animateBack); } } /// <summary> /// Whether panning feedback is currently in progress. /// </summary> private bool _isProvidingPanningFeedback; /// <summary> /// The HwndSource being manipulated. /// </summary> private HwndSource _hwndSource; } }