none
WinsowsFormアプリケーションにおいて、カスタムコントロール中のpanelにコントロールを追加する方法 RRS feed

  • 質問

  • [環境]
    --Windows10 pro
    --Visual Studio 2019
    --C#

    [目的]

    pictureBoxの領域外でMoveイベントMouseMoveイベントを取得したい。

    その解決として、panelの領域内でイベントを発火させるという方法を取った取る予定

    [行ったこと]

    クラスライブラリ(.Net Framework)プロジェクトを新規作成して、

    Form中でpanelにpictureBoxを追加するコードを、カスタムコントロールのデザイナーコードにCustomControl.Designer.csに移植した。

    右クリックしてアイテム選択>参照をクリック>クラスライブラリプロジェクトのbin\Debugの中の.dllを開く

    以上の操作で、カスタムコントロールが追加される

    [解決したいこと]

    Formでカスタムコントロールを貼り付けたら、panelにpictureboxが表示されるようにしたい。

    カスタムコントロール内でpanelにコントロールを追加する方法が知りたいです。

    解答お願い致します。



    • 編集済み NPK_exc 2020年11月4日 10:29
    2020年11月3日 13:30

回答

  • ユーザーコントロールであればフォームとおなじようにデザイナで配置できます。

    カスタムコードでやりたいのであればコードで親コントロールのControls.Addで追加します。

    namespace WindowsFormsControlLibrary1
    {
        using System.Drawing;
        using System.Windows.Forms;
    
        public partial class CustomControl1 : Control
        {
            //private System.Windows.Forms.Panel panel1 =new Panel() ;
            //private System.Windows.Forms.PictureBox pictureBox1= new PictureBox();
    
            public CustomControl1()
            {
                InitializeComponent();
    
                this.pictureBox1.Dock = DockStyle.Fill;
                this.pictureBox1.BackColor = Color.White;
    
                this.panel1.Dock = DockStyle.Fill;
                this.panel1.BackColor = Color.DarkGray;
                this.panel1.Padding = new Padding(10);
    
                this.panel1.Controls.Add(this.pictureBox1);
                this.Controls.Add(this.panel1);
            }
    
            public Panel Panel
            {
                get
                {
                    return this.panel1;
                }
            }
    
            public PictureBox PictureBox
            {
                get
                {
                    return this.pictureBox1;
                }
            }
    
        }
    }
    

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク NPK_exc 2020年11月5日 9:37
    2020年11月3日 14:41

すべての返信

  • ユーザーコントロールであればフォームとおなじようにデザイナで配置できます。

    カスタムコードでやりたいのであればコードで親コントロールのControls.Addで追加します。

    namespace WindowsFormsControlLibrary1
    {
        using System.Drawing;
        using System.Windows.Forms;
    
        public partial class CustomControl1 : Control
        {
            //private System.Windows.Forms.Panel panel1 =new Panel() ;
            //private System.Windows.Forms.PictureBox pictureBox1= new PictureBox();
    
            public CustomControl1()
            {
                InitializeComponent();
    
                this.pictureBox1.Dock = DockStyle.Fill;
                this.pictureBox1.BackColor = Color.White;
    
                this.panel1.Dock = DockStyle.Fill;
                this.panel1.BackColor = Color.DarkGray;
                this.panel1.Padding = new Padding(10);
    
                this.panel1.Controls.Add(this.pictureBox1);
                this.Controls.Add(this.panel1);
            }
    
            public Panel Panel
            {
                get
                {
                    return this.panel1;
                }
            }
    
            public PictureBox PictureBox
            {
                get
                {
                    return this.pictureBox1;
                }
            }
    
        }
    }
    

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク NPK_exc 2020年11月5日 9:37
    2020年11月3日 14:41
  • ごめんなさい、ちょっと質問の背景を理解しきれず、状況を把握できていません…。

    pictureBoxの領域外でMoveイベントを取得したい。

    (MouseMove イベントではなく) Move イベントを捉えられれば良いのですね。
    捉える対象は、(Form や Panel ではなく) PictureBox のイベント、ということで良いでしょうか。
    ここでいう「PictureBox の領域」の内外というのは、何を意味していますか?

    とりあえず、pictureBox1.Left += 10; というコードを実行すると、pictureBox1 の Move イベントが発生することは確認できましたが…何が問題なのかが読み解けませんでした。

    private void button1_Click(object sender, EventArgs e)
    {
        this.pictureBox1.Left += 10;
    }
    
    private void pictureBox1_Move(object sender, EventArgs e)
    {
        this.Text = this.pictureBox1.Location.ToString();
    }

    さて、解決策にある「イベントを発火させる」とは、具体的にどのように行いましたか?
    PictureBox の SetBounds メソッドを呼び出すとか、Location/Left/Top プロパティ を変更するなどすれば、Move イベントが発生するはずですが、意図的にイベント単体で発火させるということは、protected な OnMove メソッド を呼び出した、ということでしょうか?

    Formでカスタムコントロールを貼り付けたら、panelにpictureboxが表示されるようにしたい。

    Form というのは呼び出し元の EXE ですよね。
    そしてカスタムコントロールが作成した DLL のコントロールだとして…
    Panel が EXE 側と DLL 側のどちらに所属するものなのかも分かりませんでした。

    そもそも、ここでいう「カスタムコントロール」が何を指しているのかもよく分かりませんでした。

    質問文では、『Form中でpanelにpictureBoxを追加するコードを、カスタムコントロールのデザイナーコードに移植した』とありますので、DLL 側に「Panel を継承したコントロール」を作成しており、かつ、それをフォームに貼った時に、その Panel 自身の上に PictureBox を貼りたい…ということでしょうか。

    だとしたらその場合、その PictureBox の管理権は Form 側とカスタムコントロール側、どちらに所属させたいのでしょうか?

    普通に考えれば、カスタムコントロールに内包されたコントロールは非公開とするのが一般的なので、DLL の作成時点で、最初から Panel 内に PictureBox を配置しておけば済む話であろうかと思います。

    // クラスライブラリ [CustomPanel.cs]
    namespace ClassLibrary1
    {
        public partial class CustomPaenl : System.Windows.Forms.Panel
        {
            public CustomPaenl()
            {
                InitializeComponent();
            }
        }
    }
    
    
    // クラスライブラリ [CustomPanel.Designer.cs]
    namespace ClassLibrary1
    {
        partial class CustomPaenl
        {
            /// <summary>
            /// 必要なデザイナー変数です。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 使用中のリソースをすべてクリーンアップします。
            /// </summary>
            /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region コンポーネント デザイナーで生成されたコード
    
            /// <summary>
            /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 
            /// コード エディターで変更しないでください。
            /// </summary>
            private void InitializeComponent()
            {
                this.pictureBox1 = new System.Windows.Forms.PictureBox();
                ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
                this.SuspendLayout();
                // 
                // pictureBox1
                // 
                this.pictureBox1.Location = new System.Drawing.Point(0, 0);
                this.pictureBox1.Name = "pictureBox1";
                this.pictureBox1.Size = new System.Drawing.Size(100, 50);
                this.pictureBox1.BackColor = System.Drawing.Color.Red;
                this.pictureBox1.TabIndex = 0;
                this.pictureBox1.TabStop = false;
                this.Controls.Add(this.pictureBox1);
                ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
                this.ResumeLayout(false);
            }
            #endregion
    
            private System.Windows.Forms.PictureBox pictureBox1;
        }
    }
    

    そうではなく、PictureBox の管理権は Form に置いておきたいのだとしたら、何故カスタムコントロールを作成する必要があったのかがそもそも分かりませんでした。

    2020年11月3日 15:22
  • Question
    自分の投稿に投票することはできません
    0

    カスタムコントロールにpictureboxも表示されるようになりました。

    困っていた事は解決しました。pictureBoxのサイズモードで調整すれば、MouseMoveイベントの取得ができるようになりそうです。

    namespace cllib
    {
        public partial class CustomControl1 : Control
        {
            public CustomControl1()
            {
                InitializeComponent();
                this.pictureBox1.Dock = DockStyle.Fill;
                this.pictureBox1.BackColor = Color.White;
                this.pictureBox1.Padding = new Padding(10);
    
                this.panel1.Dock = DockStyle.Fill;
                this.panel1.BackColor = Color.DarkGray;
                
    
                this.panel1.Controls.Add(this.pictureBox1);
                this.Controls.Add(this.panel1);
            }
    }

    2020年11月4日 10:36
  • ごめんなさい、ちょっと質問の背景を理解しきれず、状況を把握できていません…。

    pictureBoxの領域外でMoveイベントを取得したい。

    (MouseMove イベントではなく) Move イベントを捉えられれば良いのですね。
    捉える対象は、(Form や Panel ではなく) PictureBox のイベント、ということで良いでしょうか。
    ここでいう「PictureBox の領域」の内外というのは、何を意味していますか?

    とりあえず、pictureBox1.Left += 10; というコードを実行すると、pictureBox1 の Move イベントが発生することは確認できましたが…何が問題なのかが読み解けませんでした。

    private void button1_Click(object sender, EventArgs e)
    {
        this.pictureBox1.Left += 10;
    }
    
    private void pictureBox1_Move(object sender, EventArgs e)
    {
        this.Text = this.pictureBox1.Location.ToString();
    }

    さて、解決策にある「イベントを発火させる」とは、具体的にどのように行いましたか?
    PictureBox の SetBounds メソッドを呼び出すとか、Location/Left/Top プロパティ を変更するなどすれば、Move イベントが発生するはずですが、意図的にイベント単体で発火させるということは、protected な OnMove メソッド を呼び出した、ということでしょうか?

    Formでカスタムコントロールを貼り付けたら、panelにpictureboxが表示されるようにしたい。

    Form というのは呼び出し元の EXE ですよね。
    そしてカスタムコントロールが作成した DLL のコントロールだとして…
    Panel が EXE 側と DLL 側のどちらに所属するものなのかも分かりませんでした。

    そもそも、ここでいう「カスタムコントロール」が何を指しているのかもよく分かりませんでした。

    質問文では、『Form中でpanelにpictureBoxを追加するコードを、カスタムコントロールのデザイナーコードに移植した』とありますので、DLL 側に「Panel を継承したコントロール」を作成しており、かつ、それをフォームに貼った時に、その Panel 自身の上に PictureBox を貼りたい…ということでしょうか。

    だとしたらその場合、その PictureBox の管理権は Form 側とカスタムコントロール側、どちらに所属させたいのでしょうか?

    普通に考えれば、カスタムコントロールに内包されたコントロールは非公開とするのが一般的なので、DLL の作成時点で、最初から Panel 内に PictureBox を配置しておけば済む話であろうかと思います。

    // クラスライブラリ [CustomPanel.cs]
    namespace ClassLibrary1
    {
        public partial class CustomPaenl : System.Windows.Forms.Panel
        {
            public CustomPaenl()
            {
                InitializeComponent();
            }
        }
    }
    
    
    // クラスライブラリ [CustomPanel.Designer.cs]
    namespace ClassLibrary1
    {
        partial class CustomPaenl
        {
            /// <summary>
            /// 必要なデザイナー変数です。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 使用中のリソースをすべてクリーンアップします。
            /// </summary>
            /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region コンポーネント デザイナーで生成されたコード
    
            /// <summary>
            /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 
            /// コード エディターで変更しないでください。
            /// </summary>
            private void InitializeComponent()
            {
                this.pictureBox1 = new System.Windows.Forms.PictureBox();
                ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
                this.SuspendLayout();
                // 
                // pictureBox1
                // 
                this.pictureBox1.Location = new System.Drawing.Point(0, 0);
                this.pictureBox1.Name = "pictureBox1";
                this.pictureBox1.Size = new System.Drawing.Size(100, 50);
                this.pictureBox1.BackColor = System.Drawing.Color.Red;
                this.pictureBox1.TabIndex = 0;
                this.pictureBox1.TabStop = false;
                this.Controls.Add(this.pictureBox1);
                ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
                this.ResumeLayout(false);
            }
            #endregion
    
            private System.Windows.Forms.PictureBox pictureBox1;
        }
    }

    そうではなく、PictureBox の管理権は Form に置いておきたいのだとしたら、何故カスタムコントロールを作成する必要があったのかがそもそも分かりませんでした。

    >>(MouseMove イベントではなく) Move イベントを捉えられれば良いのですね。

    MouseMoveイベントでした。すみません。

     PictureBox の管理権は Form 側とカスタムコントロール側、どちらに所属させたいのでしょうか?

    おそらく、DLL側に属すると思います。Panelは必要ないみたいですね。ありがとうございます。

    画像用のカスタムコントロールを使って、画像を任意のサイズにトリミングするのを最終的にはやりたいかなと思っていました。


    • 編集済み NPK_exc 2020年11月4日 11:00
    2020年11月4日 10:59