Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - Scroll without Focus

I want to scroll a ScrollViewer control while the application window isn't focused. I found some solutions in Windows Forms, but not in WPF because some of the things I need are not available.

Perhaps someone here could help me solve my problem?

Thanks in advance.

EDIT:

I want to scroll the ScrollViewer control with the mouse wheel while the mouse is over the ScrollViewer, but also while the application window isn't focused.

like image 769
Werewolve Avatar asked Feb 28 '11 08:02

Werewolve


1 Answers

I found a solution. Here an example:

XAML

<Window x:Class="Project.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="500">
    <ScrollViewer x:Name="ScrollViewer">
        <StackPanel>
            <Border Background="Blue" Width="100" Height="100" />
            <Border Background="Red" Width="100" Height="100" />
            <Border Background="Blue" Width="100" Height="100" />
            <Border Background="Red" Width="100" Height="100" />
            <Border Background="Blue" Width="100" Height="100" />
            <Border Background="Red" Width="100" Height="100" />
        </StackPanel>
    </ScrollViewer>
</Window>

Code Behind

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace Project
{
    public partial class MainWindow : Window
    {
        private const int WH_MOUSE_LL = 14;
        private const int WM_MOUSEWHEEL = 0x020A;
        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

        private IntPtr _handle;

        public MainWindow()
        {
            InitializeComponent();

            _handle = new WindowInteropHelper(this).Handle;
            SetWindowsHookEx(WH_MOUSE_LL, MouseChanged, _handle, 0);

            ScrollViewer.PreviewMouseWheel += ScrollViewer_MouseWheel;
            Unloaded += MainWindow_Unloaded;
        }

        private void MainWindow_Unloaded(object sender, RoutedEventArgs e)
        {
            UnhookWindowsHookEx(_handle);
        }

        private void ScrollViewer_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            e.Handled = true;
        }

        private IntPtr MouseChanged(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (ScrollViewer.IsMouseOver && WM_MOUSEWHEEL == (int)wParam)
            {
                MouseData mouseData = (MouseData)Marshal.PtrToStructure(lParam, typeof(MouseData));
                ScrollViewer.ScrollToVerticalOffset(ScrollViewer.VerticalOffset - mouseData.Z / 200000.0);
            }
            return CallNextHookEx(_handle, nCode, wParam, lParam);
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MouseData
        {
            public int X;
            public int Y;
            public int Z;
        }

        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    }
}
like image 107
Jotrius Avatar answered Oct 16 '22 11:10

Jotrius