tmytのらくがき

個人の日記レベルです

Windows8のスタートスクリーンみたいに、画面端のマウス操作でスクロールしたい

Windows8のスタート画面というかスタートスクリーンというかって、画面外にマウスを動かそうとするとマウスを動かした方向にスクロールしていきます。あれを普通のアプリのなかでもやりたいので調べてみたらできました。

まずこういうXAMLがあります。

<Page
    x:Class="App33.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App33"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer HorizontalScrollMode="Auto" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden"
                      HorizontalScrollBarVisibility="Auto" x:Name="ScrollViewer">
            <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                <TextBlock Text="Hoge"/>
                <!-- 100個ぐらい -->
                <TextBlock Text="Hoge"/>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Page>

これを普通に実行するとこういう結果になります。

f:id:tmyt:20140828203335p:plain

画面端でマウスを動かしても反応しません。これを反応させるようにしてみます。

using System;
using Windows.Devices.Input;
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;

namespace App33
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            MouseDevice.GetForCurrentView().MouseMoved += MainPage_MouseMoved;
        }

        void MainPage_MouseMoved(MouseDevice sender, MouseEventArgs args)
        {
            var window = CoreWindow.GetForCurrentThread();
            var bounds = window.Bounds;
            var point = window.PointerPosition;
            if ((bounds.Width <= (point.X + 1) && args.MouseDelta.X > 0) ||
                (point.X <= 0 && args.MouseDelta.X < 0))
            {
                ScrollViewer.ScrollToHorizontalOffset(ScrollViewer.HorizontalOffset + 2 * args.MouseDelta.X);
            }
        }
    }
}

これでできあがり。マウスを画面の外に動かそうとするとスクロールします。

ちょっとだけ解説書いておくと、MouseDeviceクラスのイベントをハンドリングすると、マウスの生の移動データをハンドリングできるみたいです。いちおうMSDNにはマウスポインタが移動すると発生します。と書いてますが、実際には画面端で移動できない場合でも本来移動したかった量が検出できます。その値を使ってScrollViewerをスクロールさせています。

今回はC#だけで書けたし簡単でした。