Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有任何工具/库(.Net/WPF)用于测量和存储用于分析的UI导航数据?_.net_Wpf_Usage Tracking - Fatal编程技术网

是否有任何工具/库(.Net/WPF)用于测量和存储用于分析的UI导航数据?

是否有任何工具/库(.Net/WPF)用于测量和存储用于分析的UI导航数据?,.net,wpf,usage-tracking,.net,Wpf,Usage Tracking,我想测量和分析用户界面中的用户动作和手势,以优化应用程序用户体验。我曾想象功能跟踪库(如EQATEC或Preemptive的运行时智能)会允许这样做。然而,情况似乎并非如此 理想情况下,我希望能够在UI中插入仪表,然后捕获鼠标和键盘导航手势,通过热图显示 我的搜索结果是空的。这里有什么OSS或商业软件吗?看看这个应用程序。它并不能满足您的需要,但作为实现所需功能的起点,它可能很有用:试试看 它在鼠标光标移动的地方创建线条,在鼠标光标停止的地方创建圆圈,圆圈越大,它在那里停留的时间越长。我知道它更

我想测量和分析用户界面中的用户动作和手势,以优化应用程序用户体验。我曾想象功能跟踪库(如EQATEC或Preemptive的运行时智能)会允许这样做。然而,情况似乎并非如此

理想情况下,我希望能够在UI中插入仪表,然后捕获鼠标和键盘导航手势,通过热图显示


我的搜索结果是空的。这里有什么OSS或商业软件吗?

看看这个应用程序。它并不能满足您的需要,但作为实现所需功能的起点,它可能很有用:

试试看 它在鼠标光标移动的地方创建线条,在鼠标光标停止的地方创建圆圈,圆圈越大,它在那里停留的时间越长。

我知道它更像是一个检查WPF应用程序可视化树的工具,但它也捕获事件(特别是它捕获了这些事件,并提供了它们发生的元素、它们在可视化树中的移动方式以及它们被处理的位置等信息)。由于它是开源的,您可能希望提取有关跟踪事件的部分,并将这些信息记录到您的需要中

  • 从这里下载
  • 打开解决方案或仅打开Gma.UserActivityMonitor项目,然后盲目地将其转换为.NET 4.0
  • HookManager.Callbacks.cs
    文件中进行以下更改

  • 使用System.Diagnostics添加
  • 更换

    s_MouseHookHandle = SetWindowsHookEx(
        WH_MOUSE_LL,
        s_MouseDelegate,
        Marshal.GetHINSTANCE(
            Assembly.GetExecutingAssembly().GetModules()[0]),
        0);
    
    s_KeyboardHookHandle = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        s_KeyboardDelegate,
        Marshal.GetHINSTANCE(
            Assembly.GetExecutingAssembly().GetModules()[0]),
        0);
    

    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        s_MouseHookHandle = SetWindowsHookEx(
            WH_MOUSE_LL,
            s_MouseDelegate,
           GetModuleHandle(curModule.ModuleName), 0);
    }
    
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        s_KeyboardHookHandle = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        s_KeyboardDelegate, 
        GetModuleHandle(curModule.ModuleName), 0);
    }
    
  • 更换

    s_MouseHookHandle = SetWindowsHookEx(
        WH_MOUSE_LL,
        s_MouseDelegate,
        Marshal.GetHINSTANCE(
            Assembly.GetExecutingAssembly().GetModules()[0]),
        0);
    
    s_KeyboardHookHandle = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        s_KeyboardDelegate,
        Marshal.GetHINSTANCE(
            Assembly.GetExecutingAssembly().GetModules()[0]),
        0);
    

    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        s_MouseHookHandle = SetWindowsHookEx(
            WH_MOUSE_LL,
            s_MouseDelegate,
           GetModuleHandle(curModule.ModuleName), 0);
    }
    
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        s_KeyboardHookHandle = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        s_KeyboardDelegate, 
        GetModuleHandle(curModule.ModuleName), 0);
    }
    
  • HookManager.Windows.cs
    中,在
    HookManager
    类的定义中的任意位置添加以下两行

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);
    
  • 现在,您应该能够构建并保留它。现在开始WPF部分

  • 最好创建名为WPFAApplication1的新WPF项目。添加对步骤1-5中生成的项目/程序集的引用,添加对系统.Windows.Forms的引用
  • 现在用下面的xaml替换
    main window.xaml
    ,确保检查类名和项目名,我刚刚创建了WPFAApplication1进行测试

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="0.30*"/>
                <RowDefinition Height="0.70*"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0" Orientation="Horizontal">
                <StackPanel Orientation="Vertical">
                    <CheckBox Name="MouseMove" Padding="5" Content="Mouse Move" Width="120" Height="30" Click="checkBoxOnMouseMove_CheckedChanged"/>
                    <CheckBox Name="MouseClick" Padding="5" Content="Mouse Click" Width="120" Height="30" Click="checkBoxOnMouseClick_CheckedChanged"/>
                    <CheckBox Name="MouseDown" Padding="5" Content="Mouse Down" Width="120" Height="30" Click="checkBoxOnMouseDown_CheckedChanged"/>
                </StackPanel>
                <StackPanel Orientation="Vertical">
                    <CheckBox Name="MouseUp" Padding="5" Content="Mouse Up" Width="120" Height="30" Click="checkBoxOnMouseUp_CheckedChanged"/>
                    <CheckBox Name="MouseDouble" Padding="5" Content="Mouse Double" Width="120" Height="30" Click="checkBoxMouseDoubleClick_CheckedChanged"/>
                    <CheckBox Name="MouseWheel" Padding="5" Content="Mouse Wheel" Width="120" Height="30" Click="checkBoxMouseWheel_CheckedChanged"/>
                </StackPanel>
                <StackPanel Orientation="Vertical">
                    <CheckBox Name="KeyDown" Padding="5" Content="Key Down" Width="120" Height="30" Click="checkBoxKeyDown_CheckedChanged"/>
                    <CheckBox Name="KeyPress" Padding="5" Content="Key Press" Width="120" Height="30" Click="checkBoxKeyPress_CheckedChanged"/>
                    <CheckBox Name="KeyUp" Padding="5" Content="Key Up" Width="120" Height="30" Click="checkBoxKeyUp_CheckedChanged"/>
                </StackPanel>
                <StackPanel Orientation="Vertical">
                    <TextBlock Name="labelMousePosition" Text="x={0:####}; y={1:####}"/>
                    <TextBlock Name="labelWheel" Text="Wheel={0:####}"/>
                </StackPanel>
            </StackPanel>
            <TextBlock Name="textBoxLog" Text="START" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
        </Grid>
    </Window>
    
  • 9.构建并运行WPF应用程序,您可能需要在主窗口中使用Gma.UserActivityMonitor;指令添加

    10.所有的功劳都归最初创建它的人所有,你可能想给他发一封感谢信,如果你想从中赚钱,还可以查看原始作者的代码发行许可证

    11.我只是做了一些小的修改,使其与WPF一起工作。感谢您关注这篇长文章,我不确定如何共享这段代码,这就是为什么提供这样的说明


    12.我非常热衷于对代码进行良好的格式化,所以,有人能就如何格式化代码、XML以及XML留下评论吗。还有人在这篇文章中帮助我格式化代码片段。谢谢。

    在尝试了许多方法之后,包括这里的方法以及使用和,我决定在WPF中添加一个简单的处理程序附件事件。这使我不仅可以捕获事件数据,还可以捕获用户关注的UIElement,因此更容易跟踪用户的行为和意图。没有这些,我需要捕获屏幕的视觉,并对正在发生的事情进行视觉判断

    以下是一个示例:

    private Int32 _eventCount;
    
    public MainWindow()
    {
        InitializeComponent();
        EventManager.RegisterClassHandler(typeof(UIElement), MouseEnterEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), MouseLeaveEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), MouseMoveEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), MouseUpEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), MouseDownEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), KeyUpEvent, (RoutedEventHandler)handleEvent, true);
        EventManager.RegisterClassHandler(typeof(UIElement), KeyDownEvent, (RoutedEventHandler)handleEvent, true);
    }
    
    private void handleEvent(object sender, RoutedEventArgs e)
    {
        var uiElement = e.Source as UIElement;
    
        if (uiElement == null)
        {
            return;
        }
    
        EventStatusDisplay.Text = e.Source + " " + e.RoutedEvent.Name;
        EventCountDisplay.Text = (++_eventCount).ToString();
        var over = Mouse.DirectlyOver as UIElement;
        MouseIsOverDisplay.Text = over == null ? "" : over.ToString();
    }
    

    虽然这里没有显示,但一旦我获得
    UIElement
    ,我就会执行日志记录,甚至可以使用
    UIElement.DataContext
    来确定驱动视图的ViewModel的状态,这样我们就可以在特定的工作流和数据状态以及视觉状态中找到使用模式。然后,我们可以获得关于此的报告,以及还可以通过工作流和数据值的路径来区分和比较我们的热图。

    谢谢Giorgi-这是一个有趣的项目,但使用我想要捕获的确切输入时,它确实更加不正确。它捕获输入的方式有点侵入性(自定义UIElement和一组附加属性)。我宁愿找到一些我不需要修改代码就可以使用的东西。这看起来像是我想看到的,但是,为了将输出与用户元素相关联,然后与用户故事相关联,我必须捕获屏幕截图以及IOGraphica的输出,然后使用某种分析来确定用户对其inpu的实际操作t、 这将是太多的工作。如果我的编辑被接受,请查看修订历史记录,看看如何设置此格式,好吧,但这相当麻烦。我已经想出了一些类似的方法,但没有那么重。同意,但我想不出任何替代方法:(