質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

4回答

12874閲覧

C# フローティングウインドウ(ツールバー)の作り方

ElecDove

総合スコア254

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2015/12/11 11:03

編集2015/12/11 12:16

お世話になります。

C#を使ってFormプログラミングを行っています。
お絵かき系ソフトでよくあるような、フローティングしているウインドウを造りたいと思うのですが(メインウインドウにドッキングする予定は今のところ無い)、これはどうやって実装するのが良いでしょうか

検索したのですが、各サイトで紹介されている内容に一貫性が無いというか・・・↓の疑問が解決されないので質問させていただきました。

やはり、新たにフォームを新規作成して、それをForm.Show(this);という風にするしかないでしょうか
となると、フローティングウインドウの数だけフォームが追加され、ソースコードがガンガン増えていくことになりますよね・・・?
そういうものなのでしょうか

今作っているアプリが初心者ながらにそこそこの規模になってきており、こんなにガンガン増えるならもっときれいな階層構造にしておけばよかったなぁ、なんて思ったりもしています。

※ドッキングする予定は今のところ無いと書きましたが、追加でドッキングする方法も教えていただけるとありがたいです。

また、ひとつのcsファイルに複数のフォームのクラスを記述することはできますか? hoge.Designer.csにあるInithializeComponents()メソッドなるものを直接書いたらだめでしょうか

よろしくお願いいたします。



※※補足

たとえばですが、こんな感じのウインドウです(赤丸内)
こんな感じでメインのウインドウから浮いて、メインのウインドウに対して操作を行うためのウインドウを作りたいと考えています。

たとえばこのCADではほとんどの操作項目に対してこのようなウインドウが出てきます。ということは、その操作項目の数だけフォームが実装されていると考えてよいのでしょうか(このCADが何の言語で製作されているかはわからないですが例として・・・)

フローティングしているウインドウ例

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2015/12/20 08:09

コメント遅くなり申し訳ありません。 >物理的なフォルダ階層と論理的な名前空間(パッケージ)の階層が必ずしも同じではないということは理解されたほうが良いと思います。 階層が異になることもあるのですね・・・ 逆に言えば実階層にとらわれずに名前空間を設定しても良いということを聞き安心いたしました。 MDI以外のアプローチのサンプルもありがとうございます。
guest

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

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2015/12/11 22:35

回答ありがとうございます >そういうものです。ガンガン増えます。 これを聞いて安心しました。 往生際が悪いですが、一つの機能はできれば1ファイルにしたいなぁ、とも思ったりするのでこういう疑問が生まれた次第であります。 もちろん再利用が必要なコードについては別ファイルにするだとか、そういうわけ方はするのですが、どう考えてもMainFormにしか使わない子ウインドウをまた新たにファイルを作って・・・というのが違和感がありました。そういうものならそういうものとして受け止めることにします さて、本来別の質問として投稿すべきなのかもしれませんが、こちらにも回答いただけますと幸いです。 このようにひとつの主なウインドウが複数のファイルから成り立っている場合、フォルダ分けはどうするのがベターでしょうか。 フォルダ分けをすると、クラスがnamespace AppProject.Hoge.Fuga....という風にどんどん深くなっていくと思いますが、これもやはりガンガン深くなっても良いのでしょうか(私の場合はせいぜい3~4階層程度だとは思いますが)
catsforepaw

2015/12/12 00:19

階層構造というのがどういうことかあまり深く考えませんでしたが、実際のフォルダー分けやnamespaceの階層構造でしたか。 別ファイルにしたからといって無理にフォルダー分けをする必要はありません。判りやすいクラス名を付ければよろしいかと思います。 もちろん、整理しやすいように機能毎にフォルダー分けをするということはよくやります。ただし、その場合でも階層を掘る(フォルダーの中にフォルダーを作る)ということはやったことがありませんし、VisualStudioが勝手にnamespaceの後ろに付けたフォルダー名は削除します。
guest

0

表示される内容が違うのであればそれぞれでフォームを定義しないと無理です
たとえば、ぱっと見える表示されている「押し出し」の小窓とその隣のメニューの「回転」で表示される小窓は中身は同じ内容でしょうか?
おそらくは違うものになっていると思います
であれば同じフォームの定義では「回転」で設定したい内容(多分角度とか回転方向とかそういった内容があると思います)が表示されずに「押し出し」の設定項目が表示されてしまい意味がないものとなってしまうかと思います
一応呼び出し元のメニューに合わせてどの中身を表示させるかを切り分けることも可能ですが、その場合は切り替えがうまくいくかどうかの検証の手間が増えるのと、無駄に重くなるフォームの定義から表示する際に遅くなるのと、処理を変更(修正や追加など)の際に探すのが手間になり違うメニューの同じ見出しの設定を消してしまったり変更してしまったりする危険性があるといったあたりからおすすめしません

ちなみに画像のウィンドウはMDIではなさそうですが、その裏にある3Dの物体が表示されている領域はMDIだと思われます(領域の右上に_□×があるので)
MDIとは、実態は違いますが、ソフトのウィンドウの表示領域をデスクトップとして中に複数のウィンドウがあるかのような振る舞いをするものです
2010までのExcelがそうですね
Excelというアプリケーションの枠の中をデスクトップ(のようなもの)としてブックごとにソフトが起動しているかのように見える感じです

投稿2015/12/11 12:43

len_souko

総合スコア1348

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2015/12/11 22:29

回答ありがとうございます。 やはり、一つ一つ定義する必要があるのですね 「切り替え」については考えたのですが、手間が恐ろしそうだったのですぐに排除しました 個人的にMDIはそこまで好きではない(子ウインドウの移動が親ウインドウに制限されるから)、と思いました(昔使った作曲ソフトがMDIでした)
guest

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

Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2015/12/11 12:17

回答ありがとうございます MDIではなく、補足で添付した画像のような感じです(こういうもののことをMDIというのでしたらごめんなさい) よろしくお願いいたします
Tak1wa

2015/12/11 15:08

すみません、MDIについて確認された上でコメントを頂けているのでしょうか。 追加で提示くださった画像のようなフォームもMDIにて作成できると思います。(MDIかどうかは不明ですが) どのあたりがダメだったのか回答をお願いします。 代替案があれば提案しますので。
catsforepaw

2015/12/11 16:43

横から失礼します。 フローティングウィンドウは、MDIとは違い、親ウィンドウの範囲にとどまらずに画面上に自由に(マルチモニターなら別のモニターにも)移動できる子ウィンドウのことです。Visual Studioのドッキングウィンドウの▼メニューで「フローティング(F)」を選択すると分離して現れるやつです。
ElecDove

2015/12/11 22:26

catsforepawさんありがとうございます MDIについては確認しました catsforepawさんのおっしゃるとおりでございます 疑問なのは、こういう小さなウインドウ一つ一つも新たなフォームでやるのか、それとも、フローティングウインドウ向けの(TabGroupやPanelのような別のコントロールを載せることのできる)コントロールがあり、その上に配置していくのかな、と思った次第であります
Tak1wa

2015/12/12 02:20

catsforepawさん解説ありがとうございます。一般的な用語だったとは勉強不足でお恥ずかしいです。 さて、MDI以外のアプローチで別途回答いたします。誤った回答として本回答は残しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問