Нажмите кнопку программно C#

Я ищу способ программно нажать кнопку (Winform). У меня есть форма (скажем, Form2) и кнопка (Button2) моего проекта. Когда я нажимаю кнопку, она должна нажимать кнопку Button1 (которая находится в другом проекте), но оба находятся в одном решении. Вот что я пытался сделать:

private void button2(object sender, EventArgs e)
{

    System.IntPtr hwnd;

    System.IntPtr hwndChild = IntPtr.Zero;

    hwnd = FindWindow(null, "form1");

    if (hwnd.Equals(IntPtr.Zero))
    {
     MessageBox.Show("Couldn't find the form");
    }
    else
    {
    hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, null, "BUTTON1");

    if(!hwndChild.Equals(IntPtr.Zero))
    SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
    }
}

Должен ли я использовать какой-либо другой подход, такой как отражение, вместо этого?

P.S: Button1 является частной и никакие изменения не могут быть внесены в эту функцию/проект.


person sjohnson    schedule 31.01.2017    source источник
comment
button2(null,null); работает?   -  person maksymiuk    schedule 31.01.2017
comment
Кнопка, которую вы хотите нажать, находится в другом процессе? Принадлежит ли BUTTON1 другой программе, отличной от той, которая пытается ее нажать?   -  person 15ee8f99-57ff-4f92-890c-b56153    schedule 31.01.2017
comment
Если это внутри вашего процесса, вы должны вместо этого вызывать свою бизнес-логику, а не через свой пользовательский интерфейс. Если это другой процесс, используйте Microsoft UIA   -  person MickyD    schedule 31.01.2017
comment
Предоставьте другому проекту событие нажатия кнопки на Form1 и запустите его, а не этот небезопасный метод указателя окна.   -  person Chris Pickford    schedule 31.01.2017
comment
Button1 и Button2 находятся в двух разных процессах. Я не должен вносить какие-либо изменения в код, содержащий button1.   -  person sjohnson    schedule 31.01.2017
comment
@sjohnson - скажите тому, кто дал вам эту работу, вернуться к этапу проектирования и уйти   -  person Chris Pickford    schedule 31.01.2017
comment
Если кнопка находится в диалоговом окне, а диалоговое окно неактивно, сообщение BM_CLICK может завершиться ошибкой. Чтобы гарантировать успех в этой ситуации, вызовите функцию SetActiveWindow, чтобы активировать диалоговое окно перед отправкой сообщения BM_CLICK на кнопку. Вы проверили, есть ли у вас правильные идентификаторы и запускаются ли правильные события в Spy++?   -  person Luaan    schedule 31.01.2017
comment
Я бы серьезно прочитал о шаблонах проектирования, чтобы избежать того, что вы пытаетесь сделать здесь. Вместо того, чтобы нажимать кнопку2 в другом проекте, вы пытаетесь выполнить действие, которое выполняет эта кнопка. Вы должны отделить свой код пользовательского интерфейса от своей бизнес-логики. Шаблон проектирования Google MVC или шаблон проектирования MVVM. Любой из них будет работать для того, что вы пытаетесь сделать. Действие вашего контроллера из Project1 может вызывать метод Action на контроллере в Project2 без необходимости имитировать нажатие кнопки.   -  person Jon    schedule 31.01.2017
comment
@Mangist в этом случае вызываемые так называемые действия (методы) являются частными. Как я могу получить к нему доступ? можно ли использовать отражение?   -  person sjohnson    schedule 31.01.2017
comment
@sjohnson, вы бы не вызывали частные методы, но вы можете открыть интерфейс (ваш контроллер может реализовать интерфейс), и эти методы будут общедоступными. Другой вариант — использовать шаблон проектирования брокера событий или издатель/подписка, где ваш контроллер в ProjectB подпишется на сообщение, а ваш ProjectA отправит сообщение. ProjectA -> Отправляет сообщение -> Получено подписчиками -> ProjectB. Подробнее об этом читайте здесь en.wikipedia.org/wiki/Publish%E2%80 %93subscribe_pattern Это скорее слабосвязанное решение.   -  person Jon    schedule 31.01.2017
comment
В дополнение к комментарию Мангиста, по сути, вы могли использовать любое количество методов IPC, но зачем добавлять весь этот код? Просто используйте Windows UIA. Вот что это для   -  person MickyD    schedule 01.02.2017
comment
@MickyD Я не уверен, что этот случай предназначен для UIA. Там, где это применимо Используя автоматизацию пользовательского интерфейса и следуя доступным методам проектирования, разработчики могут сделать приложения, работающие в Windows, более доступными для многих людей с нарушениями зрения, слуха или движений. Кроме того, автоматизация пользовательского интерфейса специально разработана для обеспечения надежной функциональности сценариев автоматизированного тестирования. .... похоже, что это для доступности и тестирования пользовательского интерфейса. Он пытается заставить один проект общаться с другим проектом в том же решении. Если бы один из разработчиков изменил пользовательский интерфейс в ProjectB, UIA сломалась бы.   -  person Jon    schedule 01.02.2017
comment
@Mangist Как я уже сказал, если вы хотите использовать пользовательский интерфейс, используйте UIA. Вы ошибаетесь, думая, что это только для тестирования. Это объектно-ориентированный подход для манипулирования пользовательскими интерфейсами вместо того, чтобы возиться с неудобными дескрипторами управления и отправлять BN_CLICK уведомления, скрестив пальцы в надежде, что это сработает. В противном случае используйте любое количество методов IPC, как я сказал.   -  person MickyD    schedule 01.02.2017


Ответы (2)


OP:

Я ищу способ программно нажать кнопку (Winform).

Button1 и Button2 находятся в двух разных процессах. Я не должен вносить какие-либо изменения в код, содержащий button1.

Конечно, проще всего не вносить никаких изменений в целевое приложение с помощью Windows UI Automation. По сути, UIA позволяет вам автоматизировать другое приложение с точки зрения графического интерфейса (вместо того, чтобы, скажем, за кулисами через COM/Ole Automation) независимо от того, хотите ли вы просто управлять другим приложением, скажем, нажать кнопку или выполнить полное автоматизированное тестирование в QA.

MSDN:

Microsoft UI Automation — это платформа специальных возможностей, которая позволяет приложениям Windows предоставлять и использовать программную информацию о пользовательских интерфейсах (UI). подробнее...

...а также:

UIA можно использовать для автоматизации собственных приложений Windows, приложений WPF, а также приложений Silverlight. подробнее...

Этот код будет нажимать кнопку с текстом Click Me в окне с заголовком Target Demo. Примечание. Я не делаю никаких ссылок на какой-либо конкретный тип объекта; технология обратного вызова или графического интерфейса (это работает для нативных, WinForms, WPF и Интернета)

//
// This is the handler in the ButtonClicker app, the app that is doing the clicking
//
private void go_Click(object sender, EventArgs e)
{
    // Look for a top-level window/application called "Target Demo"
    var root = AutomationElement.RootElement;
    var condition1 = new PropertyCondition(AutomationElement.NameProperty, "Target Demo");

    var treeWalker = new TreeWalker(condition1);
    AutomationElement element = treeWalker.GetFirstChild(root);
    
    if (element == null)
    {
        // not found
        return;
    }

    // great!  window found
    var window = element;

    // now look for a button with the text "Click Me"
    var buttonElement =window.FindFirst(TreeScope.Children, 
        new PropertyCondition(AutomationElement.NameProperty, "Click Me"));
    if (buttonElement == null)
    {
        // not found
        return;
    }

    // great! now click the button
    var invokePattern = buttonElement.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
    invokePattern?.Invoke();

}

Преимущества

  • Для целевого приложения не требуется никаких изменений
  • Не гадить о поиске оконных ручек
  • Никаких шуток о попытках отправить уведомления BN_CLICK в сообщения приложения, скрестив пальцы, в надежде, что это сработает.
  • работает с приложениями C++; WinForms; ВПФ; сеть
person MickyD    schedule 02.02.2017

у вас есть несколько вариантов, как показано ниже

1- button1.PerformClick();

2- button1_Click(this, EventArgs.Empty);

3- button1(null, null)

person Saif    schedule 31.01.2017
comment
если обе кнопки одного класса, то должно работать. - person Saif; 31.01.2017
comment
если этот ответ поможет вам, отметьте его как ответ .. спасибо - person Saif; 31.01.2017
comment
он сказал, что кнопки находятся в двух разных проектах - person Patrick; 31.01.2017
comment
сделать его публичным, чтобы быть доступным - person Saif; 31.01.2017
comment
Не рекомендуется, чтобы внешний процесс вызывал эти методы напрямую. Поэтому они не публичны - person MickyD; 01.02.2017