65.9K
CodeProject 正在变化。 阅读更多。
Home

Lenovo Horizon Striker

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.27/5 (3投票s)

2013 年 11 月 20 日

CPOL

2分钟阅读

viewsIcon

32850

downloadIcon

189

使用 WPF 应用程序检测 Lenovo Horizon Striker 配件

引言

在本文中,我将提供一个简单的示例,说明如何让 WPF 应用程序检测联想 Striker。联想 Striker 是 联想 Horizon 一体机的配件。通过在触摸屏表面滑动它,Striker 可以用于一些预装的 Horizon 游戏,例如联想空气曲棍球。由于截至撰写本文时,没有关于如何在 WPF 应用程序中使用 Striker 配件的文档,因此希望本文能成为一个有用的和鼓舞人心的指南。以下视频展示了示例应用程序的实际运行情况。

Striker 配件

Striker 本质上充当一个手写笔。在 Striker 的底部有四个圆形垫,其中两个提供手写笔输入。

这两个较大的垫充当手写笔输入的接触点。为了在我的 WPF 示例中使用 Striker,我将找到屏幕上每个接触垫的接触点;使用两组坐标找到 Striker 的“中心”;然后在屏幕上将一个Ellipse直接放置在 Striker 下方。

示例项目的 XAML 标记非常简单,

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="LenovoStriker" Height="514" Width="678" WindowState="Maximized">
    <Grid>
        <Canvas x:Name="StylusCanvas" Background="White" StylusDown="StylusCanvas_StylusDown"
                StylusMove="StylusCanvas_StylusMove" StylusUp="StylusCanvas_StylusUp"/>        
    </Grid>
</Window>

请注意,我将处理一些手写笔事件;特别是StylusDownStylusMoveStylusUp 事件。当 Striker 放置在屏幕上时,将向 Canvas 添加一个 Ellipse,并且当 Striker 在屏幕上移动时,它将跟随 Striker 移动。

Class MainWindow
    Private strikerPads As New Dictionary(Of Integer, Point)()
    Private diameter As Integer = 160
    Private radius As Integer = 80
    Private strikerEllipse As New Ellipse With {.Height = diameter, .Width = diameter,
                                                .Stroke = Brushes.Black, .StrokeThickness = 2,
                                                .Fill = Brushes.Yellow}

    Private Sub StylusCanvas_StylusDown(sender As Object, e As StylusDownEventArgs)
        Dim padPoint As Point = e.GetPosition(StylusCanvas)
        strikerPads.Add(e.StylusDevice.Id, padPoint)

        If (strikerPads.Count = 2) Then
            PositionEllipse()
            StylusCanvas.Children.Add(strikerEllipse)
        End If
    End Sub

    Private Sub StylusCanvas_StylusMove(sender As Object, e As StylusEventArgs)
        Dim padPoint As Point = e.GetPosition(StylusCanvas)
        strikerPads(e.StylusDevice.Id) = padPoint
        PositionEllipse()
    End Sub

    Private Sub PositionEllipse()
        Dim pad_1 As Point = strikerPads.First.Value
        Dim pad_2 As Point = strikerPads.Last.Value

        Dim y1 As Integer = CInt(pad_1.Y)
        Dim y2 As Integer = CInt(pad_2.Y)
        Dim x1 As Integer = CInt(pad_1.X)
        Dim x2 As Integer = CInt(pad_2.X)

        Dim yDiff As Integer = Math.Abs(y1 - y2)
        Dim xDiff As Integer = Math.Abs(x1 - x2)

        Dim x As Integer
        Dim y As Integer

        If (x1 < x2) Then
            x = x1 + (xDiff / 2) - radius
        Else
            x = x2 + (xDiff / 2) - radius
        End If

        If (y1 < y2) Then
            y = y1 + (yDiff / 2) - radius
        Else
            y = y2 + (yDiff / 2) - radius
        End If

        Canvas.SetLeft(strikerEllipse, x)
        Canvas.SetTop(strikerEllipse, y)
    End Sub
  
    Private Sub StylusCanvas_StylusUp(sender As Object, e As StylusEventArgs)
        If (StylusCanvas.Children.Contains(strikerEllipse)) Then
            StylusCanvas.Children.Remove(strikerEllipse)
        End If
        strikerPads.Remove(e.StylusDevice.Id)
    End Sub
End Class
namespace LenovoStriker
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private Dictionary<int, Point> strikerPads = new Dictionary<int,Point>();
        private static int diameter = 160;
        private static int radius = 80;
        private Ellipse strikerEllipse = new Ellipse()
        {
            Height = diameter,
            Width = diameter,
            Stroke = Brushes.Black,
            StrokeThickness = 2,
            Fill = Brushes.Yellow
        };

        private void StylusCanvas_StylusDown(object sender, StylusDownEventArgs e)
        {
            Point padPoint = e.GetPosition(StylusCanvas);
            strikerPads.Add(e.StylusDevice.Id, padPoint);

            if (strikerPads.Count == 2)
            {
                PositionEllipse();
                StylusCanvas.Children.Add(strikerEllipse);
            }
        }

        private void StylusCanvas_StylusMove(object sender, StylusEventArgs e)
        {
            Point padPoint = e.GetPosition(StylusCanvas);
            strikerPads[e.StylusDevice.Id] = padPoint;            
            PositionEllipse();               
        }

        private void PositionEllipse()
        {
            Point pad_1 = strikerPads.First().Value;
            Point pad_2 = strikerPads.Last().Value;

            int y1 = (int)pad_1.Y;
            int y2 = (int)pad_2.Y;
            int x1 = (int)pad_1.X;
            int x2 = (int)pad_2.X;

            int yDiff = Math.Abs(y1 - y2);
            int xDiff = Math.Abs(x1 - x2);

            int x;
            int y;

            if (x1 < x2)
            {
                x = x1 + (xDiff / 2) - radius;
            }
            else
            {
                x = x2 + (xDiff / 2) - radius;
            }

            if (y1 < y2)
            {
                y = y1 + (yDiff / 2) - radius;
            }
            else
            {
                y = y2 + (yDiff / 2) - radius;
            }

            Canvas.SetLeft(strikerEllipse, x);
            Canvas.SetTop(strikerEllipse, y);
        }

        private void StylusCanvas_StylusUp(object sender, StylusEventArgs e)
        {
            if (StylusCanvas.Children.Contains(strikerEllipse))
            {
                StylusCanvas.Children.Remove(strikerEllipse);
            }
            strikerPads.Remove(e.StylusDevice.Id);
        }
    }
}

每个接触垫将具有一个手写笔设备 ID,该 ID 用作 Dictionary 集合中的键,其 Value 是垫的屏幕坐标。现在,如果我将 Ellipse 放置在 Canvas 上,在计算出的 Striker 中心坐标处,Ellipse 将会大大偏移。

请记住,在 WPF 中,Ellipse 的坐标点位于左上角。为了正确对齐,我将在 PositionEllipse() 方法中从计算出的值中减去 Ellipse 的半径。

结论

我希望您发现本文中的信息有用,特别是那些在 Intel AIC 2013 竞赛中获得一体机的人。也许第二轮提交的一些应用程序可以使用这个有趣的配件。

历史

  • 2013 年 11 月 20 日:初始发布
© . All rights reserved.