DOBON.NETプログラミング道掲示板

■35312 / 2階層)  継承元フォームで各フォームのボタン動作を検知したい
□投稿者/ 魔界の仮面弁士 大御所(1511回)-(2022/12/30(Fri) 15:10:57)
  • アイコン
    解決済みチェックはそのままにしておきます。
    
    
    ■No35309に追記(魔界の仮面弁士の記事)
    > 別にマウス操作に限る必要は無いのなら、継承フォーム側で OnControlAdded を
    > オーバーライドして Button の追加を追跡しておき、そのボタンに対して
    > GotFocus/Enter/MouseDown/Click イベントを追跡するのが良いと思います。
    
    Button の Click イベントと Enter イベントを継承元フォームで捉えて
    独自の ControlClick / ControlEnter イベントとして発生させてみました。
    
    イベント引数 e.Control から、対象の Button オブジェクトを得られます。
    
    private void Form1_ControlClick(object sender, ControlEventArgs e)
    {
        listBox1.Items.Insert(0, $"{DateTime.Now:HH:mm:ss.ffff}/Click: {e.Control.Text}");
    }
    private void Form1_ControlEnter(object sender, ControlEventArgs e)
    {
        listBox1.Items.Insert(0, $"{DateTime.Now:HH:mm:ss.ffff}/Enter: {e.Control.Text}");
    }
    
    
    ベースクラスの実装はこんな感じ。
    
    
    // ---> SakuFormBase.cs --->
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Forms;
    using System.Collections;
    
    [DefaultEvent(nameof(SakuFormBase.ControlClick))]
    public class SakuFormBase : Form
    {
        // 実際には InitializeComponent(); の呼び出し等も記述
        public SakuFormBase() { }
    
        #region 公開イベント
        // ControlClick イベントという名に反して、Button にしか反応させていなかったりする
        [Category("Action"), Description("フォーム上の Button がクリックされた時に発生します。")]
        public event ControlEventHandler ControlClick;
        [Category("Focus"), Description("フォーム上の Button がアクティブになった時に発生します。")]
        public event ControlEventHandler ControlEnter;
        /// <summary><see cref="ControlClick"/> イベントを発生させます。</summary>
        protected virtual void OnControlClick(ControlEventArgs e) => ControlClick?.Invoke(this, e);
        /// <summary><see cref="ControlEnter"/> イベントを発生させます。</summary>
        protected virtual void OnControlEnter(ControlEventArgs e) => ControlEnter?.Invoke(this, e);
        #endregion
    
        #region 内部処理
        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            // 子コントロールが追加されたら、Click/Enter イベントを捉える
            AttachEvents(e.Control);
        }
        private void AttachEvents(Control control)
        {
            if (control is Button button)
            {
                // Button が追加された時はイベントを追跡
                if (subscribes.Add(control))
                {
                    var a = new ControlEventArgs(control);
                    button.Click += (sender, e) => OnControlClick(a);
                    button.Enter += (sender, e) => OnControlEnter(a);
                }
            }
            else
            {
                // Button で無ければ、さらにその配下のコントロールに対して再帰的に追跡
                if (subscribes.Add(control))
                {
                    control.ControlAdded += (sender, e) => AttachEvents(control);
                }
                foreach (var c in control.GetControls<Control>())
                {
                    AttachEvents(c);
                }
            }
        }
        // イベントを追跡済みかどうかを管理
        private HashSet<Control> subscribes = new HashSet<Control>();
        #endregion
    }
    internal static class ControlExtensions
    {
        /// <summary>
        /// 指定した型の子孫コントロールを列挙する
        /// </summary>
        public static IEnumerable<T> GetControls<T>(this Control control) where T : Control
        {
            var controls = control.Controls.OfType<Control>();
            return controls.OfType<T>().Concat(controls.SelectMany(c => GetControls<T>(c)));
        }
    }
    // <--- SakuFormBase.cs ---
    
    
    ControlAdded イベント(OnControlAdded メソッド)を用いているのは、
    Button の追加が実行時に動的に行われた場合に備えるためのものです。
    (今回、ControlRemoved イベントの追跡は省略しています)
    
    デザイン時の画面構成のままで、ボタン数の増減が無いような場合は、
    Load 完了後に全 Button を列挙して捉えるだけでも十分かと思います。

解決み!
違反を報告
削除キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[1]: 継承元フォームで各フォームのボタン動作を検知したい /魔界の仮面弁士 返信無し
 
上記関連ツリー

Nomalアイコン 継承元フォームで各フォームのボタン動作を検知したい / saku (22/12/30(Fri) 08:33) #35308
Nomalアイコン Re[1]: 継承元フォームで各フォームのボタン動作を検知したい / 魔界の仮面弁士 (22/12/30(Fri) 10:19) #35309
  ├Nomalアイコン Re[2]: 継承元フォームで各フォームのボタン動作を検知したい / saku (22/12/30(Fri) 12:13) #35310 解決み!
  └Nomalアイコン 継承元フォームで各フォームのボタン動作を検知したい / 魔界の仮面弁士 (22/12/30(Fri) 15:10) #35312 解決み! ←Now

All 上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信

Mode/  Pass/


- Child Tree -