C#, ソフトウェア開発

MouseDown・MouseMove・MouseDown等のマウスイベントは、各コントロールで発生する為、
親フォームで一括して受信するには、明示的にイベントハンドラを設定する必要がある。

        public Form1()
        {
            InitializeComponent();

            // 親フォームのマウスイベントハンドラの割り当て
            SetEventHandler(this);
        }

        /// <summary>
        /// 子コントロールにMouseイベントハンドラを設定(再帰)
        /// </summary>
        private void SetEventHandler(Control objControl)
        {
            // イベントの設定
            // (親フォームにはすでにデザイナでマウスのイベントハンドラが割り当ててあるので除外)
            if(objControl != this)
            {
                objControl.MouseDown += (sender, e) => this.OnMouseDown(e);
                objControl.MouseMove += (sender, e) => this.OnMouseMove(e);
                objControl.MouseUp += (sender, e) => this.OnMouseUp(e);
            }

            // さらに子コントロールを検出する
            if(objControl.Controls.Count > 0)
            {
                foreach(Control objChildControl in objControl.Controls)
                {
                    SetEventHandler(objChildControl);
                }
            }
        }

        #region FormのMouseイベント受信部

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            // senderは常にFormだが、eの座標は各コントロールを基準とした座標が入る為、
            // スクリーン座標からクライアント座標を計算すること
            Point pntScreen = Control.MousePosition;
            Point pntForm = this.PointToClient(pntScreen);

            this.Text = "X=" + pntForm.X + " Y=" + pntForm.Y;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            Point pntScreen = Control.MousePosition;
            Point pntForm = this.PointToClient(pntScreen);

            this.Text = "X=" + pntForm.X + " Y=" + pntForm.Y;
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            Point pntScreen = Control.MousePosition;
            Point pntForm = this.PointToClient(pntScreen);

            this.Text = "X=" + pntForm.X + " Y=" + pntForm.Y;
        }

        #endregion

 

キーボードのイベントも各コントロールで発生するが、
こちらは親フォームでイベントを発生させるプロパティが用意されている。

            // 子・孫問わず、すべてのコントロールで発生したキーイベントが親フォームで取得できる
            this.KeyPreview = true;

 

C#, ソフトウェア開発

VisualStudioのデザインモードを判定する方法として、DesignModeプロパティがあるが、
継承コントロールやユーザコントロールの場合、正しく値が取得できない。

EndInit後に全ての親コントロールのDesignModeを確認することで、
デザインモードの判定を行う。

internal class uctlControl : PictureBox, ISupportInitialize // ISupportInitializeを継承し、EndInitイベントを受信する
{
        /// <summary>
        /// Init後処理
        /// </summary>
        public void EndInit()
        {
            // 自身のデザインモードを取得
            bool bolDesignMode = base.DesignMode;

            // 親コントロールを再帰取得
            Control objParent = this.Parent;
            while (objParent != null)
            {
                ISite objSite = objParent.Site;
                if (objSite != null)
                    bolDesignMode |= objSite.DesignMode;

                objParent = objParent.Parent;
            }

            // デザインモードの場合は処理を抜ける
            if (bolDesignMode == true)
                return;

            // デザインモードではないときに行う初期化処理
        }
}