none
イベント処理の親子関係について。 RRS feed

  • 質問

  • いつも参考にしております。
    イベント処理の発生について質問させていただきます。

    【環境】
    ・Visual C# 2008
    ・.NET Framework 3.5 SP1

    【クラス】
    1.オリジナルボタンの作成
    public partial class ImageButton : Control
     protected override void OnMouseEnter()
      protected override void OnMouseLeave()
      protected override void OnMouseUp()
      protected override void OnMouseDown()
    上記4つのイベントにより、ボタン画像を変更しています。

    2.オリジナルボタンを複数使用(Controls.Add)したUserControlの作成
    public partial class ButtonsPanel : UserControl
     pribate int m_selectedID;
     private void ButtonsPanel_MouseDown()
    MouseDown時に、どのボタンが選択されたかを示すボタンIDをメンバ変数に設定する。

    3.ButtonsPanel を使用(Controls.Add)したFormの作成
    public partial class FormTest : Form
     private void FormTest_MouseDown()


    【質問】
    このとき、ButtonsPanel で「MouseDown」イベントを発生させたとき、
    ImageButton 側の「OnMouseDown」が実行され、ButtonsPanel 側の
    「ButtonsPanel_MouseDown」は無反応となります。このため、
    m_selectedIDが設定できません。

    私の理想は、ImageButton のOnMouseDown()で画像変更後、
    続けて、ButtonsPanel の「ButtonsPanel_MouseDown()」の処理を
    実行することです。

    また、将来的にはButtonsPanel はいろいろなFormで使用します。
    FormにButtonsPanelを追加して、FormTest_MouseDown時に
    m_selectedIDを取得したいと考えています。
    ※もちろんこのままでは、FormでのMouseDownも無反応です。


    一般的にはこの場合、どのような設計・コーディングを行うのでしょうか。
    できればMouseUpは使用せずにMouseDownのみでm_selectedIDを
    Form側で取得することは可能でしょうか。
    何卒、よろしくお願い申し上げます。

    2010年2月13日 7:00

回答

  • WinForm では、子コントロールが受け取った入力イベントはそこで完結し、再帰的に親の同じイベントを呼び出すような仕組みは持っていません。Form の子に Panel がいてさらにその子に Button がいたとき、Button 上でマウスボタンを押下しても Panel.MouseDown や Form.MouseDown は発生しません。
    // Panel.OnMouseDown の呼び出しによって Panel.MouseDown が発生するように見せかけることはできますが。
    Panel.MouseDown は Button の領域以外の Panel 領域を押下したときにのみ発生しますし、Form.MouseDown も同様です。

    普通は以下のような構造になるでしょう。
    class ButtonPanel : UserControl {
        private Button button = new Button();
        public event EventHandler ButtonDown;
        public ButtonPanel() {
            this.InitializeComponent();
            this.button.MouseDown += new MouseEventHandler(this.OnButtonDown);
        }
        private void OnButtonDown(object sender, MouseEventArgs e) {
            if (this.ButtonDown != null)
                this.ButtonDown(this, EventArgs.Empty);
        }
    }
    class Form1 : Form {
        public Form1() {
            this.InitializeComponent();
            this.buttonPanel.ButtonDown += new EventHandler(this.OnButtonDown);
        }
    }
    2010年2月13日 9:04

すべての返信

  • ButtonsPanel が、自分に ImageButton を配置するときに、その ImageButton の MouseDown イベントをハンドルして適切な処理をします。
    このとき、自分(ButtonsPanel)の OnMouseDown を呼び出すことも考えられますが、どちらかというと ButtonsPanel は ButtonClick イベントなりの独自イベントを用意し、各 ImageButton のクリック時にこのイベントを発生させるのが自然でしょう。
    Form の方も、Form 自体の MouseDown ではなく、追加したコントロール(ButtonsPanel)のイベントをハンドルします。
    2010年2月13日 7:10
  • Hongliang


    早速のご返事、誠にありがとうございます。
    ”ButtonsPanel は ButtonClick イベントなりの独自イベント”により、イベントを生成することができました。

    同様にForm側でもイベントをハンドルしましたが、無反応となってしまいました。
    以下の様なコードです。
    this.ButtonsPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ButtonsPanel_MouseDown);

    不足部分等ございますでしょうか。
    ご確認のほどよろしくお願い致します。
    2010年2月13日 7:47
  • WinForm では、子コントロールが受け取った入力イベントはそこで完結し、再帰的に親の同じイベントを呼び出すような仕組みは持っていません。Form の子に Panel がいてさらにその子に Button がいたとき、Button 上でマウスボタンを押下しても Panel.MouseDown や Form.MouseDown は発生しません。
    // Panel.OnMouseDown の呼び出しによって Panel.MouseDown が発生するように見せかけることはできますが。
    Panel.MouseDown は Button の領域以外の Panel 領域を押下したときにのみ発生しますし、Form.MouseDown も同様です。

    普通は以下のような構造になるでしょう。
    class ButtonPanel : UserControl {
        private Button button = new Button();
        public event EventHandler ButtonDown;
        public ButtonPanel() {
            this.InitializeComponent();
            this.button.MouseDown += new MouseEventHandler(this.OnButtonDown);
        }
        private void OnButtonDown(object sender, MouseEventArgs e) {
            if (this.ButtonDown != null)
                this.ButtonDown(this, EventArgs.Empty);
        }
    }
    class Form1 : Form {
        public Form1() {
            this.InitializeComponent();
            this.buttonPanel.ButtonDown += new EventHandler(this.OnButtonDown);
        }
    }
    2010年2月13日 9:04
  • Hongliang


    コード例、誠にありがとうございました。無事理想的な動作となりました。
    子のEventHandlerを使用して親側で生成、全く思い浮かびませんでした。
    大変参考になりました。今後とも、よろしくお願い致します。
    2010年2月13日 10:23