スプリッターで区切られたコントロールをコンテナーパネルサイズを超えてサイズ変更する方法は?
質問
スプリッターで区切られたパネルにいくつかのユーザーコントロールがあります。 含まれているパネルはAutoScrollに設定されています。
Splitterコントロールは、コントロールのサイズを「分割」するときに親のサイズを考慮するため、内部のUserControlのサイズ変更はパネルのサイズによって制限されます。
ユーザーがマウスを離したときにスプリッターをマウスのある場所(コンテナー/フォームの境界を超えて)に移動し、それに応じてコンテナーパネルのサイズを変更できるようにします(必要に応じてスクロールバーを表示します) 。
さまざまなパネルでラップしたり、MinSizeなどで遊んだりして、あらゆる組み合わせを試しました。 これは私がこれまでに思いついた最高のものですが、それは私が望むものではありません:
アイデアはありますか?
解決
マウスフックを設定できるのはマウスボタンを押して、マウスボタンを放したときにフックを外します。フックコールバックでは、マウスの位置を監視し、必要に応じてコントロールのサイズを変更できます。
編集:
代わりに、ユーザーがドラッグして親コンテナの右下隅にスクロール位置を保持できる特別なコントロールを使用できます。ユーザーはコントロールをドラッグして領域を大きくすることができます。アンカーまたはドックの設定を使用していない場合は、コントロールのサイズを手動で調整して親領域を埋めることができます。
私がやったプロジェクトのためにしばらく前にこのようなものを実装しました。三角形にし、「グリップ」に似ているように見えました。 ToolStrip
で。以下に、 ScrollHolder
コントロールのコードの一部を示します。
public ScrollHolder()
{
this.Size = new Size(21, 21);
this.BackColor = SystemColors.Control;
}
protected override void OnPaint(PaintEventArgs e)
{
Point bottomLeft = new Point(0, this.Height);
Point topRight = new Point(this.Width, 0);
Pen controlDark = SystemPens.ControlDark;
Pen controlLightLight = SystemPens.ControlLightLight;
Pen controlDark2Px = new Pen(SystemColors.ControlDark, 2);
Point bottomRight = new Point(this.Width, this.Height);
e.Graphics.DrawLine(
controlLightLight,
bottomLeft.X,
bottomLeft.Y - 2,
bottomRight.X,
bottomRight.Y - 2);
e.Graphics.DrawLine(controlDark, bottomLeft, topRight);
e.Graphics.DrawLine(
controlLightLight,
bottomLeft.X + 1,
bottomLeft.Y,
topRight.X,
topRight.Y + 1);
e.Graphics.DrawLine(controlDark2Px, bottomLeft, bottomRight);
e.Graphics.DrawLine(controlDark2Px, bottomRight, topRight);
int xNumberOfGripDots = this.Width / 4;
for (int x = 1; x < xNumberOfGripDots; x++)
{
for (int y = 1; y < 5 - x; y++)
{
DrawGripDot(e.Graphics, new Point(
this.Width - (y * 4), this.Height - (x * 4) - 1));
}
}
}
private static void DrawGripDot(Graphics g, Point location)
{
g.FillRectangle(
SystemBrushes.ControlLightLight, location.X + 1, location.Y + 1, 2, 2);
g.FillRectangle(SystemBrushes.ControlDark, location.X, location.Y, 2, 2);
}
protected override void OnResize(EventArgs e)
{
this.SetRegion();
base.OnResize(e);
}
private void SetRegion()
{
GraphicsPath path = new GraphicsPath();
path.AddPolygon(new Point[]
{
new Point(this.Width, 0),
new Point(this.Width, this.Height),
new Point(0, this.Height)
});
this.Region = new Region(path);
}
実際の動作の実装に関する限り、おそらく次のことが必要になります。
- スクロールホルダーが表示領域外に移動したら、スクロールホルダーまでスクロールします。
- スクロールホルダーまでスクロールする場合、
Thread.Sleep
を短時間(50ミリ秒など)呼び出して速度を下げます。
他のヒント
Splitter
の MinExtra
プロパティを大きな負の数に設定する必要があります。プロパティ自体はこれを許可していませんが、リフレクションによってフィールドを変更できます:
typeof(Splitter).GetField("minExtra", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(mySplitter, -10000);