お世話になります。
C#を使ってFormプログラミングを行っています。
お絵かき系ソフトでよくあるような、フローティングしているウインドウを造りたいと思うのですが(メインウインドウにドッキングする予定は今のところ無い)、これはどうやって実装するのが良いでしょうか
検索したのですが、各サイトで紹介されている内容に一貫性が無いというか・・・↓の疑問が解決されないので質問させていただきました。
やはり、新たにフォームを新規作成して、それをForm.Show(this);という風にするしかないでしょうか
となると、フローティングウインドウの数だけフォームが追加され、ソースコードがガンガン増えていくことになりますよね・・・?
そういうものなのでしょうか
今作っているアプリが初心者ながらにそこそこの規模になってきており、こんなにガンガン増えるならもっときれいな階層構造にしておけばよかったなぁ、なんて思ったりもしています。
※ドッキングする予定は今のところ無いと書きましたが、追加でドッキングする方法も教えていただけるとありがたいです。
また、ひとつのcsファイルに複数のフォームのクラスを記述することはできますか? hoge.Designer.csにあるInithializeComponents()メソッドなるものを直接書いたらだめでしょうか
よろしくお願いいたします。
※※補足
たとえばですが、こんな感じのウインドウです(赤丸内)
こんな感じでメインのウインドウから浮いて、メインのウインドウに対して操作を行うためのウインドウを作りたいと考えています。
たとえばこのCADではほとんどの操作項目に対してこのようなウインドウが出てきます。ということは、その操作項目の数だけフォームが実装されていると考えてよいのでしょうか(このCADが何の言語で製作されているかはわからないですが例として・・・)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
MDI以外のアプローチです。
C#
1public partial class Form1 : Form 2{ 3 public Form1() 4 { 5 InitializeComponent(); 6 this.Width = 500; 7 this.Height = 500; 8 var btn = new Button(); 9 btn.Click += button1_Click; 10 this.Controls.Add(btn); 11 } 12 13 private void button1_Click(object sender, EventArgs e) 14 { 15 //自分より常に全面の子ウインドウを生成 16 var sub = new SubForm(); 17 sub.Owner = this; 18 sub.Show(); 19 } 20 21 private class SubForm : Form 22 { 23 public SubForm() 24 { 25 InitializeComponent(); 26 } 27 28 private void InitializeComponent() 29 { 30 this.Text = "SubForm"; 31 var btn = new Button(); 32 btn.Text = "Dock"; 33 btn.Click += (s, be) => 34 { 35 //ドッキング 36 btn.Text = "Release"; 37 this.TopLevel = false; 38 this.Width = 30; 39 this.Owner.Controls.Add(this); 40 this.Dock = DockStyle.Right; 41 }; 42 this.Controls.Add(btn); 43 } 44 } 45}
FormのOwner設定で親子関係とともにフォームの表示位置をコントロールできます。
これによって要望の動作を実現することが出来ると思います。
またドッキングについてはFormをControlとして扱いつつDockプロパティを制御すればドッキングは可能です。(解除や再表示など考慮すべき点は多々あります)
hoge.Designer.csにあるInithializeComponents()メソッドなるものを直接書いたらだめでしょうか
結局のところInitializeComponentsで行っていることはデザイナをコード反映したものです。
ですので自前でロジック実装できるのであればInitializeComponentを直接用意しても良いです。
サンプルは意図的にそうしました。
このようにひとつの主なウインドウが複数のファイルから成り立っている場合、フォルダ分けはどうするのがベターでしょうか。
フォルダの複数階層化は一般的でしょう。
Microsoftの.NET Frameworkもそうですし、GitHubなどを参考にされても良いと思います。
ただ、物理的なフォルダ階層と論理的な名前空間(パッケージ)の階層が必ずしも同じではないということは理解されたほうが良いと思います。
投稿2015/12/12 02:29
編集2015/12/12 02:45総合スコア4791
0
ベストアンサー
やはり、新たにフォームを新規作成して、それをForm.Show(this);という風にするしかないでしょうか
そうするのが一番簡単だと思います。
となると、フローティングウインドウの数だけフォームが追加され、ソースコードがガンガン増えていくことになりますよね・・・? そういうものなのでしょうか
そういうものです。ガンガン増えます。
フォームのように目に見えるものならまだいいです。実際のシステム・製品開発では、機能毎にクラスを作って何十ファイルにもなったりします。メニューから呼び出せる機能一つ一つがそれぞれ別ファイルに書かれているかもしれません。
当然規模が大きくなればそれだけファイルの数も増えます。数百ファイルあるいはそれ以上というものも珍しくはないでしょう。
また、ひとつのcsファイルに複数のフォームのクラスを記述することはできますか?
もちろん可能ですが、そうするメリットはないように思います。フォームデザイナーで編集できないため、フォームのレイアウトは全て自前で書くことになり、とても面倒くさいです。
hoge.Designer.csにあるInithializeComponents()メソッドなるものを直接書いたらだめでしょうか
○○.Designer.csは、VisualStudioが自動的に生成するファイルなので、いじってはいけません。
C#
1/// <summary> 2/// デザイナー サポートに必要なメソッドです。このメソッドの内容を 3/// コード エディターで変更しないでください。 4/// </summary>
こんな感じでInithializeComponentsメソッドにコメントが書かれているはずです。守りましょう。
どうもソースコードが増えることに抵抗感を感じているように思えるのですが、「必要であればソースコードを増やすことをためらわない」ことが肝要かと思います。
こんなにガンガン増えるならもっときれいな階層構造にしておけばよかったなぁ、なんて思ったりもしています。
それは重要です。設計を見直すことも、時には必要です。
投稿2015/12/11 16:58
総合スコア5944
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
表示される内容が違うのであればそれぞれでフォームを定義しないと無理です
たとえば、ぱっと見える表示されている「押し出し」の小窓とその隣のメニューの「回転」で表示される小窓は中身は同じ内容でしょうか?
おそらくは違うものになっていると思います
であれば同じフォームの定義では「回転」で設定したい内容(多分角度とか回転方向とかそういった内容があると思います)が表示されずに「押し出し」の設定項目が表示されてしまい意味がないものとなってしまうかと思います
一応呼び出し元のメニューに合わせてどの中身を表示させるかを切り分けることも可能ですが、その場合は切り替えがうまくいくかどうかの検証の手間が増えるのと、無駄に重くなるフォームの定義から表示する際に遅くなるのと、処理を変更(修正や追加など)の際に探すのが手間になり違うメニューの同じ見出しの設定を消してしまったり変更してしまったりする危険性があるといったあたりからおすすめしません
ちなみに画像のウィンドウはMDIではなさそうですが、その裏にある3Dの物体が表示されている領域はMDIだと思われます(領域の右上に_□×があるので)
MDIとは、実態は違いますが、ソフトのウィンドウの表示領域をデスクトップとして中に複数のウィンドウがあるかのような振る舞いをするものです
2010までのExcelがそうですね
Excelというアプリケーションの枠の中をデスクトップ(のようなもの)としてブックごとにソフトが起動しているかのように見える感じです
投稿2015/12/11 12:43
総合スコア1367
0
こんにちは。
フローティングしているウインドウってなんでしょうか。
MDIウインドウのことでしょうか?
もしそれで良ければドッキングを含めて以下のように実装できます。
C#
1public partial class Form1 : Form 2{ 3 public Form1() 4 { 5 InitializeComponent(); 6 this.IsMdiContainer = true; 7 } 8 9 private void Form1_Load(object sender, EventArgs e) 10 { 11 var hoge = new Form2(); 12 hoge.MdiParent = this; 13 hoge.Show(); 14 } 15} 16 17public partial class Form2 : Form 18{ 19 public Form2() 20 { 21 InitializeComponent(); 22 } 23 24 private void button1_Click(object sender, EventArgs e) 25 { 26 this.Dock = DockStyle.Left; 27 this.Width = 100; 28 } 29}
フローティングウインドウごとに振る舞いがことなるのであればその分だけ実装は必要でしょう。
クラスの分割については可能ではありますが、VisualStudioデザイナとの連携などを考慮するとあまりお勧めは出来ません。
投稿2015/12/11 11:26
総合スコア4791
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/11 16:43

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/20 08:09