C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

パネルとスプリッターを使った時の処理方法について

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■87308 / inTopicNo.1)  パネルとスプリッターを使った時の処理方法について
  
□投稿者/ 夜叉丸 (101回)-(2018/05/09(Wed) 18:27:21)

分類:[.NET 全般] 

2018/05/09(Wed) 18:54:28 編集(投稿者)

フォームにパネル2つとスプリッター2を1つ置きます。

フォームサイズを(546, 359)にして Padding を All=10 にすると
ClientSize が(510, 300)になったので、
panel1 を Size=(200, 300), Dock = Right
splitter1 を Size=(10, 300), Dock = Right
panel2 を を Size=(300, 300), Dock = Fill
で追加しました。

この状態で、フォームのサイズやスプリッターを移動しても
panel1の幅200、panel2の幅300をキープしたかったので、
以下のようにイベントを追加しました。

private void panel1_Resize(object sender, EventArgs e)
{
 if (panel1.Width < 200) panel1.Width = 200;
}

private void panel2_Resize(object sender, EventArgs e)
{
 if (panel2.Width < 300) panel1.Width = this.ClientSize.Width - 300 - splitter1.Width;
}

フォームを大きくして、panel1の幅をSplitter1を使って広げた後、
フォームの右端をドラッグしたままフォームの幅を狭くすると
パネルの表示が壊れたり、Splitter1が消えたりします。
壊れないようにするにはどうすればよいのでしょうか?
引用返信 編集キー/
■87309 / inTopicNo.2)  Re[1]: パネルとスプリッターを使った時の処理方法について
□投稿者/ WebSurfer (1484回)-(2018/05/09(Wed) 18:48:17)
No87308 (夜叉丸 さん) に返信

何を作っているのでしょう? Windows Forms アプリ? WPF アプリ? ASP.NET Web Forms アプリ? その他?

あなたの開発環境(OS, .NET, Visual Studio のバージョンなど)はなんですか?
引用返信 編集キー/
■87310 / inTopicNo.3)  Re[2]: パネルとスプリッターを使った時の処理方法について
□投稿者/ 夜叉丸 (102回)-(2018/05/09(Wed) 18:53:37)
No87309 (WebSurfer さん) に返信
> ■No87308 (夜叉丸 さん) に返信
>
> 何を作っているのでしょう? Windows Forms アプリ? WPF アプリ? ASP.NET Web Forms アプリ? その他?
Windows Forms アプリです
>
> あなたの開発環境(OS, .NET, Visual Studio のバージョンなど)はなんですか?
OS:Windows10
.NET 4.5.1
Visual Studio 2017
です
引用返信 編集キー/
■87311 / inTopicNo.4)  Re[1]: パネルとスプリッターを使った時の処理方法について
□投稿者/ 猫まっしぐら (2回)-(2018/05/09(Wed) 20:52:10)
No87308 (夜叉丸 さん) に返信
ていうかSplitContainerじゃいけない理由は?
引用返信 編集キー/
■87312 / inTopicNo.5)  Re[2]: パネルとスプリッターを使った時の処理方法
□投稿者/ 夜叉丸 (103回)-(2018/05/10(Thu) 08:08:37)
2018/05/10(Thu) 09:07:11 編集(投稿者)
2018/05/10(Thu) 08:53:24 編集(投稿者)

<pre><pre>■No87311 (猫まっしぐら さん) に返信
> ■No87308 (夜叉丸 さん) に返信
> ていうかSplitContainerじゃいけない理由は?

やりたいことはパネルの最小表示できる範囲を固定できれば
SplitContainerでも問題ないです。
ただ、SplitContainerの使い方がわからないです。
また、最終的には以下のようなパネル構成になります。
太線はスプリットの線です。

┌────────────────────┐
│┌────┐┃┌────┐┃┌────┐│
││    │┃│    │┃│┌──┐││
│└────┘┃│    │┃│└──┘││
│━━━━━━┃│    │┃│┌──┐││
│┌────┐┃│    │┃│└──┘││
││    │┃└────┘┃└────┘│
│└────┘┃━━━━━━━━━━━━━│
│━━━━━━┃┌───────────┐│
│┌────┐┃│           ││
││    │┃│           ││
│└────┘┃└───────────┘│
└────────────────────┘
</pre></pre>

引用返信 編集キー/
■87314 / inTopicNo.6)  Re[3]: パネルとスプリッターを使った時の処理方法
□投稿者/ にゃるら (14回)-(2018/05/10(Thu) 09:39:29)
SplitContainerは以下のプロパティで構成されます。
Orientationプロパティで分割線を垂直か水平にするかを指定できます。
SplitterDistanceプロパティで上(左)側から見ての分割線の位置を指定できます。


期待されているパネル構成なら、

1. まずSplitContainerを配置し、OrientationをHorizontalにする
2. 1で配置したSplitContainerの左側のパネルにSplitContainerを配置
3. 2で配置したSplitContainerのどちらかのパネルにSplitContainerを配置(これで左側の縦並び3つが完成)
4. 1で配置したSplitContainerの右側のパネルにSplitContainerを配置
5. 4で配置したSplitContainerの上側のパネルにSplitContainerを配置し、OrientationをHorizontalにする

てな感じでいかがでしょうか?
引用返信 編集キー/
■87316 / inTopicNo.7)  Re[4]: パネルとスプリッターを使った時の処理方法
□投稿者/ 夜叉丸 (104回)-(2018/05/10(Thu) 12:31:35)
No87314 (にゃるら さん) に返信

ありがとうございます。
SplitContainerを使ってやりたいことができました。

SplitContainerを使わずにすることは不可能ということなのでしょうか?
引用返信 編集キー/
■87319 / inTopicNo.8)  Re[5]: パネルとスプリッターを使った時の処理方法
□投稿者/ 猫まっしぐら (3回)-(2018/05/10(Thu) 13:14:42)
No87316 (夜叉丸 さん) に返信
もちろんSplitterでも出来ますがコントロールを配置する順番とか色々めんどくさいのでSplitContainerで出来るならわざわざ苦労することもないかなと
引用返信 編集キー/
■87323 / inTopicNo.9)  Re[5]: パネルとスプリッターを使った時の処理方法
□投稿者/ 魔界の仮面弁士 (1658回)-(2018/05/10(Thu) 17:24:23)
No87308 (夜叉丸 さん) に返信
> panel1の幅200、panel2の幅300をキープしたかったので、

フォームサイズが (150, 150) になったりすると、最小幅を維持できないので、
Form の MinimumSize もセットしておいた方がよいかと思います。


現状だと、Form サイズが小さすぎた場合、
panel1.Width = 200、panel2.Width = 0 になりえますし、
それよりさらに狭くなると、panel1 に押しやられた splitter1 が
マイナス座標に配置されることになりますよね。


> パネルの表示が壊れたり、Splitter1が消えたりします。
現象を再現できなかったので、状況が読みきれていません…。

> フォームを大きくして、panel1の幅をSplitter1を使って広げた後、
> フォームの右端をドラッグしたままフォームの幅を狭くすると
具体的なサイズが分かると、こちらでも状況を追跡できるかも。

(1) Form の Width を幾つまで広げたのか
(2) panel1 の Width をどこまで広げたのか
(3) その後、Form の Width をどこまで狭めたのか



> 壊れないようにするにはどうすればよいのでしょうか?
もしも再配置が追いついていないようであれば、フォームのリサイズが終了した後で、
ResumeLayout を呼び出してみるのはどうでしょう。
https://dobon.net/vb/dotnet/control/suspendlayout.html


No87314 (にゃるら さん) に返信
> 1. まずSplitContainerを配置し、OrientationをHorizontalにする
> 2. 1で配置したSplitContainerの左側のパネルにSplitContainerを配置

1 が Vertical で、2 が Horizontal では無いでしょうか。

Horizontal (水平線) だと上下配置、
Vertical (垂直線) が左右配置ですよね。



No87316 (夜叉丸 さん) に返信
> SplitContainerを使ってやりたいことができました。

SplitContainer なら、Resize イベント等のコーディングも不要で、
 splitContainer1.SplitterWidth = 10
 splitContainer1.Panel1MinSize = 300
 splitContainer1.Panel2MinSize = 200
をデザイン時に設定しておくだけで済むはずです。

それに Splitter をドラッグする際の視覚効果も、最小サイズ以下にならないよう調整されるので、
ユーザビリティ的にも画面設計効率的にも、SplitContainer の方がお奨めです。

VS2005/VS2008 時代の MSDN を見てみると「SplitContainer コントロール (Windows フォーム)」の
解説において、下記のように記されていますしね。

》メモ:
》 ツールボックスでは、以前のバージョンの Visual Studio で使用されていた Splitter コントロールが、
》 このコントロールに置き換えられました。SplitContainer コントロールの優先度は、Splitter コントロールよりも
》 かなり高くなります。Splitter クラスは、既存のアプリケーションとの互換性を確保するために、引き続き
》 .NET Framework に含まれていますが、新しいプロジェクトに対しては、SplitContainer コントロールを
》 使用することを強くお勧めします。

※ VS2017 では機械翻訳ヘルプになってしまったので分かり難い…。
https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/splitcontainer-control-windows-forms
引用返信 編集キー/
■87324 / inTopicNo.10)  Re[6]: パネルとスプリッターを使った時の処理方法
□投稿者/ にゃるら (15回)-(2018/05/10(Thu) 18:10:37)
No87323 (魔界の仮面弁士 さん) に返信

> ■No87314 (にゃるら さん) に返信
>>1. まずSplitContainerを配置し、OrientationをHorizontalにする
>>2. 1で配置したSplitContainerの左側のパネルにSplitContainerを配置
>
> 1 が Vertical で、2 が Horizontal では無いでしょうか。
>
> Horizontal (水平線) だと上下配置、
> Vertical (垂直線) が左右配置ですよね。


うわ、間違ってました。ご指摘ありがとうございます!

なので、念のために修正したものをば。

1. まずSplitContainerを配置
2. 1で配置したSplitContainerの左側のパネルにSplitContainerを配置し、OrientationをHorizontalにする
3. 2で配置したSplitContainerのどちらかのパネルにSplitContainerを配置し、OrientationをHorizontalにする(これで左側の縦並び3つが完成)
4. 1で配置したSplitContainerの右側のパネルにSplitContainerを配置し、OrientationをHorizontalにする
5. 4で配置したSplitContainerの上側のパネルにSplitContainerを配置
引用返信 編集キー/
■87325 / inTopicNo.11)  Re[6]: パネルとスプリッターを使った時の処理方法
□投稿者/ 夜叉丸 (106回)-(2018/05/10(Thu) 18:39:06)
2018/05/10(Thu) 18:39:22 編集(投稿者)
No87323 (魔界の仮面弁士 さん) に返信
> ■No87308 (夜叉丸 さん) に返信
>>panel1の幅200、panel2の幅300をキープしたかったので、
> 
> フォームサイズが (150, 150) になったりすると、最小幅を維持できないので、
> Form の MinimumSize もセットしておいた方がよいかと思います。
> 
> 
> 現状だと、Form サイズが小さすぎた場合、
> panel1.Width = 200、panel2.Width = 0 になりえますし、
> それよりさらに狭くなると、panel1 に押しやられた splitter1 が
> マイナス座標に配置されることになりますよね。
> 
MinimumSize はセットしています。

> 具体的なサイズが分かると、こちらでも状況を追跡できるかも。
> 
> (1) Form の Width を幾つまで広げたのか
> (2) panel1 の Width をどこまで広げたのか
> (3) その後、Form の Width をどこまで狭めたのか

新規のフォームサイズを(526,339) で作成します。
フォントはデフォルトの [MSUIGothic, 13pt] を使ってます。
同時に MinimumSize = (526, 339) にします。

パネル(panel1)を貼り付け サイズを(200, 300)で、Dock = Right にします。
スプリッター(splitter1)を貼り付け サイズを(10, 300)で、Dock = Right にします。
パネル(panel1)を貼り付け サイズを(200, 300)で、Dock = Fill にします。
すると以下のようになります。
┌─────────────┐
│┌───┐┌─┐┌───┐│
││   ││S ││   ││
││   ││pt││   ││
││Panel1││le││Panel2││
││   ││ir││   ││
││   ││t1││   ││
│└───┘└─┘└───┘│
└─────────────┘
わかりやすく Panel1 の上に ListBox1 を、
Panel2 の上に ListBox2 を貼り付けて、どちらも DOCK=Fillにしました。
Panel1, Panel2 のリサイズイベントに以下のコードを追加します。

private void panel1_Resize(object sender, EventArgs e)
{
 if (panel1.Width < 200) panel1.Width = 200;
}

private void panel2_Resize(object sender, EventArgs e)
{
 if (panel2.Width < 300) panel1.Width = this.ClientSize.Width - 300 - splitter1.Width;
}

スプリッターの移動だけなら問題なく動きます。
ところが、フォームを広げ、panel2 の横幅を広げた状態にして
┌───────────────────┐
│┌───┐┌─┐┌─────────┐│
││   ││S ││         ││
││   ││pt││         ││ form (526,339) →(1500,339)
││Panel1││le││   Panel2   ││ panel1 (200,300) →(1000,300)
││   ││ir││         ││ panel2 (526,339) →(474,300)
││   ││t1││         ││
│└───┘└─┘└─────────┘│
└───────────────────┘
フォームの右端をドラッグしてフォームのサイズを素早く小さく
(フォームの右端をドラッグしたままマウスを左にすばやく移動)します。
ゆっくり動かすとならない、またはなりにくいです。
本来 panel1 と panel2 の幅の合計は 1078-26=1052 なのに
752+280=1032 になっている。その差 20 がグレー部分で表示されていると思います。
というより画面キャプチャ―して調べるとグレー部分が20増えていました。
┌───────────────┐
│┌───┐┌─┐┌───┐  │
││   ││S ││   │  │
││   ││pt││   │  │ form (1078,339)
││Panel1││le││Panel2│  │ panel1 (752,300)
││   ││ir││   │  │ panel2 (280,300)
││   ││t1││   │  │
│└───┘└─┘└───┘  │
└───────────────┘
              ↑
            グレー(Control色)の部分が表示される。

現状 ListBox が Panel2 の上に張り付けているので
フォームの内側が真っ白になることもありました。

>>壊れないようにするにはどうすればよいのでしょうか?
> もしも再配置が追いついていないようであれば、フォームのリサイズが終了した後で、
> ResumeLayout を呼び出してみるのはどうでしょう。
> https://dobon.net/vb/dotnet/control/suspendlayout.html
> 
 ResumeLayout を呼びましたが表示は変わりません。
 UpDate, Refresh も表示は変わりません。
 処理途中で強制終了されているような感じです。

> 
> SplitContainer なら、Resize イベント等のコーディングも不要で、
>  splitContainer1.SplitterWidth = 10
>  splitContainer1.Panel1MinSize = 300
>  splitContainer1.Panel2MinSize = 200
> をデザイン時に設定しておくだけで済むはずです。

はい、設定しました。

> それに Splitter をドラッグする際の視覚効果も、最小サイズ以下にならないよう調整されるので、
> ユーザビリティ的にも画面設計効率的にも、SplitContainer の方がお奨めです。
> 
> VS2005/VS2008 時代の MSDN を見てみると「SplitContainer コントロール (Windows フォーム)」の
> 解説において、下記のように記されていますしね。
> 
> 》メモ:
> 》 ツールボックスでは、以前のバージョンの Visual Studio で使用されていた Splitter コントロールが、
> 》 このコントロールに置き換えられました。SplitContainer コントロールの優先度は、Splitter コントロールよりも
> 》 かなり高くなります。Splitter クラスは、既存のアプリケーションとの互換性を確保するために、引き続き
> 》 .NET Framework に含まれていますが、新しいプロジェクトに対しては、SplitContainer コントロールを
> 》 使用することを強くお勧めします。 
> 
> ※ VS2017 では機械翻訳ヘルプになってしまったので分かり難い…。
> https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/splitcontainer-control-windows-forms

今後は SplitContainer を使用するようにします。



引用返信 編集キー/
■87359 / inTopicNo.12)  Re[7]: パネルとスプリッターを使った時の処理方法
□投稿者/ 魔界の仮面弁士 (1665回)-(2018/05/15(Tue) 11:40:37)
No87325 (夜叉丸 さん) に返信
> 新規のフォームサイズを(526,339) で作成します。
> 同時に MinimumSize = (526, 339) にします。
今回は Padding を調整していない(ゼロのまま)のですね?

当方環境だと、高さを 338 にしないと、内側の高さが 300 になりませんでしたが、
今回は気にしないでおきます。(タイトルバーや枠線の高さは環境依存ですし)


> フォントはデフォルトの [MSUIGothic, 13pt] を使ってます。
日本語環境での既定のフォントは、
[MS UI Gothic, 9pt]
だと思いますよ。

また、Form の AutoScaleMode が None 以外の場合、
実行時のサイズが、デザイン時とは異なるサイズに
自動調整される可能性があります。


> パネル(panel1)を貼り付け サイズを(200, 300)で、Dock = Right にします。
> スプリッター(splitter1)を貼り付け サイズを(10, 300)で、Dock = Right にします。
> パネル(panel1)を貼り付け サイズを(200, 300)で、Dock = Fill にします。
どちらも panel1 とかかれていますが、順番からすると、後者が panel2 ですよね。
だとすると
> すると以下のようになります。
とはならないハズ。左右が逆になっているのでは無いでしょうか。


> わかりやすく Panel1 の上に ListBox1 を、
> Panel2 の上に ListBox2 を貼り付けて、どちらも DOCK=Fillにしました。
IntegralHeight は True のままでしょうか。それとも False でしょうか。
True の場合、ListBox の高さは項目の倍数単位に設定されるため、
フォームサイズによっては、下部に余白が生まれる可能性があります。


> スプリッターの移動だけなら問題なく動きます。
> ところが、フォームを広げ、panel2 の横幅を広げた状態にして
>  form (526,339) →(1500,339)
>  panel1 (200,300) →(1000,300)
>  panel2 (526,339) →(474,300)
上記のリサイズは、デザイン時に行ったということでしょうか。

座標的には、panel1 の方が幅が広く設定されていますが、
図では右側 (Panel2) の方が広く描かれていますね。
やはり、罫線描画された図の左右が逆になっているようです。


> グレー(Control色)の部分が表示される。
とりあえず対処療法として、
 private void Form1_ResizeEnd(object sender, EventArgs e)
 {
  PerformLayout();
 }
あたりを仕込んでおくと、多少はマシになるかもしれません。



> フォームの右端をドラッグしてフォームのサイズを素早く小さく
> (フォームの右端をドラッグしたままマウスを左にすばやく移動)します。
> ゆっくり動かすとならない、またはなりにくいです。

幾らやっても再現させられなかったので、マウスの分解能スイッチと、
コントロールパネルのポインター速度設定の両方を変更したところ
こちらの環境でも再現させることができました。

(1) ポインター速度:最速、マウス分解能:2000 ※こうすると再現しやすかった
(2) ポインター速度:最速、マウス分解能:1000
(3) ポインター速度:最速、マウス分解能:200
(4) ポインター速度:中間、マウス分解能:2000
(5) ポインター速度:中間、マウス分解能:1000 ※私は普段これで利用
(6) ポインター速度:中間、マウス分解能:200
(7) ポインター速度:最遅、マウス分解能:2000
(8) ポインター速度:最遅、マウス分解能:1000
(9) ポインター速度:最遅、マウス分解能:200
引用返信 編集キー/
■87360 / inTopicNo.13)  Re[8]: パネルとスプリッターを使った時の処理方法
□投稿者/ 夜叉丸 (107回)-(2018/05/15(Tue) 12:12:27)
No87359 (魔界の仮面弁士 さん) に返信

panel サイズの表示を間違っていたにも関わらず。
詳細まで調べていただき本当にありがとうございました。




解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ