2012年11月30日金曜日

マウスの移動速度をプログレスバーに表示

マウスの移動速度をリアルタイムに測定してプログレスバーを速度メーターに見立てて表示します。
現在時刻から過去0.3秒間のマウスカーソルの移動距離を、20ミリ秒ごとに計算して、プログレスバーを更新します。
マウスを激しく動かすと、プログレスバーの Value プロパティが 100、つまりMAXになり、しばらくマウスを動かさないと0になります。

画面上のマウスの位置を取得するには、User32.dll の GetCursorPos を使います。



MainWindow.xaml

<Window x:Class="ProgressBarTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="80" Width="160" Loaded="Window_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Name="textBlock1" />
        <ProgressBar Grid.Row="1" Width="130" Height="20" Name="progressBar1" />
    </Grid>
</Window>

MainWindow.xaml

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Threading;

namespace ProgressBarTest
{
    public partial class MainWindow Window
    {
        private Queue<double> queue = new Queue<double>();
        private Point prePoint;

        [DllImport("User32.dll")]
        private static extern bool GetCursorPos(ref Win32Point pt);

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DispatcherTimer timer = new DispatcherTimer();
            timer.Tick += timer_Tick;
            timer.Interval = new TimeSpan(0, 0, 0, 0, 20);
            timer.Start();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            Point point = GetMousePosition();
            double x = this.prePoint.X - point.X;
            double y = this.prePoint.Y - point.Y;
            double nextLength = Math.Sqrt(x * x + y * y);
            this.queue.Enqueue(nextLength);
            if (this.queue.Count > 15)
            {
                this.queue.Dequeue();
            }
            this.prePoint = point;
            double total = 0;
            foreach (double length in queue)
            {
                total += length;
            }
            this.progressBar1.Value = total / 30;

            this.textBlock1.Text = point.X + ", " + point.Y;
        }

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

        public static Point GetMousePosition()
        {
            Win32Point win32Point = new Win32Point();
            GetCursorPos(ref win32Point);
            return new Point(win32Point.X, win32Point.Y);
        }
    }
}

0 件のコメント:

コメントを投稿