2014-01-02 3 views
0

Мне нужно автоматизировать общие действия для нескольких программ, таких как Microsoft Word. Испытания проводятся не для коммерческого использования, а для регрессионного тестирования.Visual Studio (C#) - Имитация кнопки Win32 Нажмите

До сих пор я просто двигал мышью и посылал левую кнопку мыши над кнопкой. Однако наша программа проверяет, что кнопка находится в состоянии «нажата». Когда автоматизация прижимает кнопку с помощью мыши, кнопка не нажата (кнопка не «утонуть»)

Почему? Как заставить автоматический щелчок мыши вызвать кнопку «Пресса», как обычный щелчок мыши?

В этом случае, BTW, я имею в виду кнопку «Сохранить» на панели быстрого доступа.

Код, который я использую, довольно прост - сначала я нахожу объект, на который я хочу нажать, а затем этот код используется;

public void MouseClick(params string[] args) 
{ 
    AutomationElement automationElement = elementUtils.FindObjectFullPath(args[1], args[4], args[5]); 
    string action = args[args.Length - 1]; 

    if (automationElement == null) 
     return; 

    FocusApplicationExp(automationElement); 

    try 
    { 
     int x = (int)automationElement.GetClickablePoint().X; 
     int y = (int)automationElement.GetClickablePoint().Y; 
     MouseMoveExp(x, y); 
     MouseAction(action, automationElement); 
    } 
    catch (Exception) 
    { 
     Console.WriteLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle"); 
     tl.AddLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle"); 
     res.AddLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle"); 

     int x = (int)(automationElement.Current.BoundingRectangle.Right - automationElement.Current.BoundingRectangle.Width/2); 
     int y = (int)(automationElement.Current.BoundingRectangle.Bottom - automationElement.Current.BoundingRectangle.Height/2); 
     MouseMoveExp(x, y); 
     MouseAction(action, automationElement); 
     return; 
    } 
} 

private void MouseAction(string action, AutomationElement automationElement) 
{ 
    switch (action) 
    { 
     case "Left": 
      Console.WriteLine("Left clicking on: " + automationElement.Current.Name); 
      tl.AddLine("Left clicking on: " + automationElement.Current.Name); 
      AutomationUtility.DoMouseClick(); 
      res.AddLine("Left clicked on: " + automationElement.Current.Name); 
      break; 
     case "Right": 
      Console.WriteLine("Right clicking on: " + automationElement.Current.Name); 
      tl.AddLine("Right clicking on: " + automationElement.Current.Name); 
      AutomationUtility.DoMouseRightClick(); 
      res.AddLine("Right clicked on: " + automationElement.Current.Name); 
      break; 
     case "Double": 
      Console.WriteLine("Double clicking on: " + automationElement.Current.Name); 
      tl.AddLine("Double clicking on: " + automationElement.Current.Name); 
      AutomationUtility.DoMouseDoubleClick(); 
      res.AddLine("Double clicked on: " + automationElement.Current.Name); 
      break; 
     default: 
      break; 
    } 
} 

public static void DoMouseClick() 
{ 
    Mouse.Click(MouseButton.Left); 
} 

И я сделал попробовать несколько вариантов, например, давая некоторую задержку между кнопкой вниз и вверх, в случае произошло событие, но слишком быстро. Но кнопка никогда не входит в состояние «нажата», даже если я держу кнопку нажатой (в автоматическом режиме, конечно)

Просто для того, чтобы быть более ясным - автоматизация работает, она нажата на кнопку, и она вызывает слово сохранить. Проблема здесь заключается в том, чтобы вызвать нажатие кнопки визуально (и программно, изменив ее состояние).

Я не уверен, что это что-то значит, но система, которая идентифицирует состояния и события кнопок, является «UX», а идентификатор на основе Win32 НАХОДИТ «как-то».

EDIT: Я читал на нем последние несколько дней, и все становится яснее. Автоматизация, которую я использую, основана на UIAutomation, но состояние кнопки «Pressed» - это состояние MSAA, которое не перемещалось по генерации UI-объектов UIAutomation, поэтому автоматизация на основе UIAutomation не вызывает это состояние. Другими словами, мне нужно найти способ использования кода UIAutomation для отправки сигналов MSAA в элементы UIAutomation (которые содержат интерфейс IAccessible). Проблема заключается в том, что она поддерживается только в другом направлении (посылают сигналы UIAutomation, маскированные как сигналы MSAA для элементов MSAA, которые не поддерживают сигналы MSAA-Only, такие как «Enter state Pressed»)

+0

Как указано, вы никогда его не увидите, машина просто нажимает слишком быстро. Мы не можем видеть альтернативу, которую вы пробовали. Это не должно иметь значения для тестирования пользовательского интерфейса, все, что имеет значение, - это то, что * Word * видит щелчок мыши. –

+0

Проблема в том, что наша программа (а не автоматизация) собирает события и использует их, чтобы узнать, было ли сделано действие. В этом случае мышь нажимает на кнопку с именем «Сохранить» и родительскую «Панель быстрого инструмента», состояние объекта: нажата, «Фокусируемая». Так что мне нужен автоматический музлик, чтобы работать как человек. –

ответ

0

Ну, я не нашел ответ, который я искал, но это, похоже, работает в любом случае;

[System.Runtime.InteropServices.DllImport("user32.dll")] 
    public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); 

    public const int MOUSEEVENTF_LEFTDOWN = 0x02; 
    public const int MOUSEEVENTF_LEFTUP = 0x04; 
    public const int MOUSEEVENTF_RIGHTDOWN = 0x08; 
    public const int MOUSEEVENTF_RIGHTUP = 0x10; 

    //This simulates a left mouse click 
    public static void LeftMouseClick(int xpos, int ypos) 
    { 
     mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0); 
     Thread.Sleep(100); 
     mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0); 
    } 

    public static void RightMouseClick(int xpos, int ypos) 
    { 
     mouse_event(MOUSEEVENTF_RIGHTDOWN, xpos, ypos, 0, 0); 
     Thread.Sleep(100); 
     mouse_event(MOUSEEVENTF_RIGHTUP, xpos, ypos, 0, 0); 
    } 

Я не уверен, как это разные ответы Дерека или Za7ef, так как я попробовал их обоих. Я несколько раз менял код, поэтому у него могла быть другая причина. В любом случае, спасибо!

1

Я не знаю, если вы можете использовать этот способ, но это может помочь на участке с щелчком.

public void ClickOnPoint(IntPtr wndHandle) 
{ 
//for handle you can use (this.Handle) 
//you can assign point directly or recalibrate as you did already 
Point buttonPoint(100, 500) 
// store old pos if needed 
POINT oldPoint; 
GetCursorPos(out oldPoint); 
// get screen coordinates 
ClientToScreen(wndHandle, ref buttonPoint); 
// set cursor on coords, and press mouse 
SetCursorPos(buttonPoint.X, buttonPoint.Y); 
//you can change the timing 
mouse_event(0x00000002, 0, 0, 0, UIntPtr.Zero); // left mouse button down 
mouse_event(0x00000004, 0, 0, 0, UIntPtr.Zero); // left mouse button up 
// return mouse 
SetCursorPos(oldPoint.X, oldPoint.Y); 
} 
1

Возможно, воспользуйтесь функцией SendInput.

В приведенном ниже сообщении я разместил несколько классов для использования SendInput.

How to move the cursor or simulate clicks for other applications?

ПРИМЕЧАНИЕ: Я мог видеть кнопку сохранить идти оранжевым, если я ставлю в задержке. Я не видел, чтобы он шел оранжевым без промедления.

public static void LeftClick() 
    { 
    DoMouse(NativeMethods.MOUSEEVENTF.LEFTDOWN, new Point(0, 0)); 
    System.Threading.Thread.Sleep(200); 
    DoMouse(NativeMethods.MOUSEEVENTF.LEFTUP, new Point(0, 0)); 
    } 
+0

Я попробовал. Он работает в некотором смысле, что он посылает вход только справа, но все же не вызывает кнопку изменения состояния. В любом случае, спасибо! –

+0

Нет проблем. Думал, что стоит попробовать. :) – Derek

+0

Я обновил ответ. Используя SendInput с задержкой, кажется, что кнопка немного оранжевая. – Derek

Смежные вопросы