【发布时间】:2018-12-31 17:24:19
【问题描述】:
使用 WPF 的内置 UI 自动化,很容易(虽然相当冗长)向 AutomationElement(例如按钮)发送左键单击事件:
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,
}
}
【问题讨论】:
-
就我而言,我使用了automationElement (automationElement.Current.BoundingRectangle) 的“BoundingRectangle”属性来获取移动光标所需的x、y 坐标。然后我移动光标,并使用 MouseEvent 发送右键单击。此外,听起来移动光标是行不通的;以下内容过去对我有用: [DllImport("user32.dll", EntryPoint = "SetCursorPos")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetCursorPos(int X, int Y);
标签: c# .net wpf testing ui-automation