c# - 如何使用 WPF 的 UI 自动化将右键单击事件发送到 AutomationElement?

标签 c# .net wpf testing ui-automation

使用 WPF 的内置 UI 自动化,很容易(尽管非常冗长)将左键单击事件发送到 AutomationElement(例如 Button):

InvokePattern invokePattern = (InvokePattern) element.GetCurrentPattern(InvokePattern.Pattern);
invokePattern.Invoke();

但是,似乎没有内置方法可以将右键单击发送到同一元素。我已经辞职使用 P/Invoke 来调用 SendInput ,但我无法让它工作。使用下面的代码,当我调用 RightClick() 时,上下文菜单会在光标所在的位置弹出,而不是在我希望被右键单击的元素处弹出。所以它似乎忽略了我提交的坐标,只使用当前光标位置。

public static void RightClick(this AutomationElement element)
{
    Point p = element.GetClickablePoint();

    NativeStructs.Input input = new NativeStructs.Input
    {
        type = NativeEnums.SendInputEventType.Mouse,
        mouseInput = new NativeStructs.MouseInput
        {
            dx = (int) p.X,
            dy = (int) p.Y,
            mouseData = 0,
            dwFlags = NativeEnums.MouseEventFlags.Absolute | NativeEnums.MouseEventFlags.RightDown,
            time = 0,
            dwExtraInfo = IntPtr.Zero,
        },
    };

    NativeMethods.SendInput(1, ref input, Marshal.SizeOf(input));

    input.mouseInput.dwFlags = NativeEnums.MouseEventFlags.Absolute | NativeEnums.MouseEventFlags.RightUp;

    NativeMethods.SendInput(1, ref input, Marshal.SizeOf(input));
}

internal static class NativeMethods
{
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern uint SendInput(uint nInputs, ref NativeStructs.Input pInputs, int cbSize);
}

internal static class NativeStructs
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct Input
    {
        public NativeEnums.SendInputEventType type;
        public MouseInput mouseInput;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct MouseInput
    {
        public int dx;
        public int dy;
        public uint mouseData;
        public NativeEnums.MouseEventFlags dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }
}

internal static class NativeEnums
{
    internal enum SendInputEventType : int
    {
        Mouse = 0,
        Keyboard = 1,
        Hardware = 2,
    }

    [Flags]
    internal enum MouseEventFlags : uint
    {
        Move = 0x0001,
        LeftDown = 0x0002,
        LeftUp = 0x0004,
        RightDown = 0x0008,
        RightUp = 0x0010,
        MiddleDown = 0x0020,
        MiddleUp = 0x0040,
        XDown = 0x0080,
        XUp = 0x0100,
        Wheel = 0x0800,
        Absolute = 0x8000,
    }
}

最佳答案

据我了解,您关于模拟 UIA 元素上的右键单击所必需的 SendInput 是正确的。

至于如何在右键单击之前强制光标移动到您的元素,您可以尝试将 MOUSEEVENTF_MOVE 标志添加到您的 dwFlags。

如果仍然不起作用,也许可以尝试调用 SendInput 两次 - 一次移动鼠标(使用“dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE”),第二次以您现在的方式执行右键单击。

还有,你见过这个项目吗?

http://inputsimulator.codeplex.com/

目前不确定它的鼠标输入支持有多完整,但它可能很有用。

此外,这个问题也可能有用:

using mouse with sendInput in C

关于c# - 如何使用 WPF 的 UI 自动化将右键单击事件发送到 AutomationElement?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6554494/

相关文章:

.net - 在 Label 的内容中明确使用 TextBlock 会使 ContentPresenter 行为异常

c# - 如何将 IQueryable 列表中的值存储到字符串变量?

c# - 程序集版本 ".001"变为 ".1"

c# - Linq To XML、yield 等

c# - 方法 'ExecuteAsync' 没有实现。带有 .NET 4.6.1 的 EF6

c# - wpf 菜单项的键盘快捷键

c# - 如何连接到 Visual Web Developer 2010 中的 mysql 数据库?

c# - 使用 SignalR 2 和 MVC 4.0 从服务器向特定客户端发送消息不起作用

.NET ClickOnce 和 Vista 启动

c# - 如何等待表单加载,然后启动方法?