2011-07-02 101 views
4

使用WPF的內置UI自動化,很容易(雖然很詳細)發送左擊事件的AutomationElement(如Button):如何使用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, 
    } 
} 
+0

檢查此代碼。它工作http://kadenautomationtestingplatform.googlecode.com/svn-history/r11/ATP/ATP/ATP.CoreLibs/Common/NativeMethods.cs – user958539

+0

在我的例子中,我已經使用automationElement(automationElement的「BoundingRectangle」屬性.Current.BoundingRectangle)來獲得移動光標所需的x,y座標。然後我移動光標,並使用MouseEvent發送一個右鍵單擊。另外,這聽起來像移動光標是什麼不工作;以下對我有用:[DllImport(「user32.dll」,EntryPoint =「SetCursorPos」)] [return:MarshalAs(UnmanagedType.Bool)] private static extern bool SetCursorPos(int X,int Y) ; –

回答

0

根據我的理解,您對SendInput是模擬右鍵單擊UIA元素所需的正確信息。

至於如何強制光標移動到你的元素之前,右鍵點擊,你可以嘗試添加MOUSEEVENTF_MOVE標誌到你的dwFlags。

如果仍然不起作用,可能嘗試調用SendInput兩次 - 一次移動鼠標(使用「dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE」),然後第二次執行右鍵單擊您現在執行的操作。

另外,你見過這個項目嗎?

http://inputsimulator.codeplex.com/

不知道它的鼠標輸入的支持如何完成在此刻,但它可能是有用的。

而且,這個問題可能是太有用:

using mouse with sendInput in C

0

如果從控制派生,你可以使用以下命令:

var e = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Right); 
e.RoutedEvent = Mouse.MouseDownEvent; 
this.OnMouseDown(e); 
0

MSDN說:

如果指定了MOUSEEVENTF_ABSOLUTE值,則dx和dy包含歸一化的絕對座標,介於0和65,535之間。事件過程將這些座標映射到顯示錶面上。座標(0,0)映射到顯示錶面的左上角;座標(65535,65535)映射到右下角。在多監視器系統中,座標映射到主監視器。

這意味着你不能只使用p.X和p.Y.你需要規範化像這樣的例子:

var virtualScreen = System.Windows.Forms.SystemInformation.VirtualScreen; 
Int32 x = Convert.ToInt32((p.X - virtualScreen.Left) * 65536/virtualScreen.Width); 
Int32 y = Convert.ToInt32((p.Y - virtualScreen.Top) * 65536/virtualScreen.Height); 

,你將需要或將其與MOUSEEVENTF_VIRTUALDESK標誌了。

相關問題