Nano Hash - криптовалюты, майнинг, программирование

Регистрация всех нажатий кнопок в приложении WinForms

Я хочу добавить оператор журнала для каждого нажатия кнопки WinForms, которое нажимает пользователь, и, в идеале, идентификатор родительской формы (например, строка заголовка). Я видел сообщения, регистрирующие все щелчки мышью, но меня интересует только регистрация нажатий кнопок. Я прочитал принятый ответ здесь и адаптировал его. :

public class ButtonLogger
{
    private static readonly ILog Logger = LogManager.GetLogger(typeof(ButtonLogger));
    public static void AttachButtonLogging(Control.ControlCollection controls)
    {
        foreach (var button in controls.OfType<Button>())
        {
            button.Click += LogButtonClick;
        }
    }
    private static void LogButtonClick(object sender, EventArgs eventArgs)
    {
        Button button = sender as Button;
        Logger.InfoFormat("Button clicked: {0} ({1})", button.Text, button.Parent.Text);
    }
}

Этот класс используется в конце конструктора в форме, например. :

ButtonLogger.AttachButtonLogging(this.Controls);

Проблема, с которой я столкнулся, заключается в том, что свойство Controls, похоже, не имеет ссылки на мои кнопки. Предположительно, это связано с тем, что кнопки добавляются не непосредственно в форму, а в другой элемент управления, находящийся в свойстве Controls. Однако свойство Controls содержит только один элемент управления ToolStrip.

Есть ли способ использовать все кнопки в форме независимо от их родительского контейнера? Моя конечная цель - добавить оператор журнала к моим кнопкам, поэтому, если это можно сделать каким-то другим способом, помимо методов события нажатия кнопки, я также открыт для этого.

30.07.2013

Ответы:


1

Я считаю, что вам нужно искать кнопки рекурсивно:

public static void AttachButtonLogging(Control.ControlCollection controls)
{
    foreach (var control in controls.Cast<Control>())
    {
        if (control is Button)
        {
           Button button = (Button)control;
           button.Click += LogButtonClick;
        }
        else
        {
            AttachButtonLogging(control.Controls);
        }
    }
}
30.07.2013
  • Есть ситуация, в которой у нас есть TabControl и некоторые Buttons на некоторых TabPage, мы должны искать в TabControl.TabPages. Я столкнулся с этой проблемой, однако, если это не относится к OP, этот код работает нормально. 30.07.2013
  • @KingKing спасибо, очень хорошая заметка. Честно говоря, я думал, что страницы вкладок будут представлены в элементах управления TabControl. Странный дизайн! 30.07.2013
  • Известно ли, что это вызывает какие-либо проблемы с производительностью при построении формы? Хотя это рекурсия, она должна быть довольно легкой, поскольку в конкретной форме есть небольшое количество элементов управления (максимум 20). Кроме того, поскольку они присоединяются после прикрепления реального события к кнопке, это не должно задерживать реальную обработку, которую вы хотите выполнить при нажатии кнопки. 30.07.2013
  • @StealthRabbi Я не думаю, что это вызовет заметную задержку. Я думаю, что здесь можно сделать некоторые улучшения (т.е. избежать инициализации коллекции элементов управления для каждого элемента управления), но вы должны попробовать - может быть, все в порядке и так 30.07.2013
  • Можете ли вы придумать, как это можно расставить по приоритетам перед реальными событиями? Есть несколько проблем с этим подходом к регистрации ПОСЛЕ реальных событий: во-первых, если нажатие кнопки открывает модальное диалоговое окно, а затем некоторые действия в этом диалоговом окне приводят к сбою приложения, нажатие никогда не будет авария исходила от родителя). Точно так же щелчки в модальном диалоговом окне будут появляться до щелчка родителя, то есть не по порядку. Наконец, если нажатие кнопки закрывает родительский диалог, button.Parent будет нулевым. 09.01.2015
  • (В любом случае я не мог понять, как это сделать, не удаляя и не добавляя заново все события, поскольку единственное, что в InitializeComponent() происходит после создания кнопки, но до добавления событий, — это SuspendLayout(), которое нельзя переопределить. , Надеюсь, есть более чистое решение...) 09.01.2015

  • 2

    Одна вещь, которую вы могли бы рассмотреть, — это создать подкласс стандартного класса Button и позволить кнопкам самим вести журнал. Конечно, вам придется обойти и заменить все кнопки в приложении вашей собственной реализацией, но это должно быть возможно сделать с помощью глобального поиска + замены.

    Вот пример реализации:

    public class LoggerButton : Button
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(LoggerButton));
    
        protected override void OnClick(EventArgs e)
        {
            base.OnClick(e);
            Logger.InfoFormat("Button clicked: {0} ({1})", this.Text, this.Parent.Text);
        }
    }
    
    30.07.2013
  • Это усложняет задачу и дизайнеру. Вам нужно будет создать собственную палитру инструментов и использовать собственный класс кнопок вместо встроенного. Это вариант, конечно, но, возможно, немного неправильное использование наследования. 30.07.2013
  • @StealthRabbi Правда? Мне никогда не приходилось делать что-то особенное, чтобы мои пользовательские элементы управления отображались в наборе инструментов Visual Studio. Но да, я соглашусь, что это несколько халтурно. 30.07.2013
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..