English 中文(简体)
How to resize controls seperated by a splitter beyond their container panel size?
原标题:

I ve got a few UserControls on a panel separated by splitters. The containing panel is set to AutoScroll.

Since the Splitter control takes its parent s size into consideration when it resizes the controls it splits , the resizing of the UserControls inside it is limited by the panel s size.

I want to be able to move the splitter down to wherever the mouse was (even beyond the bounds of the container/form) when the user release it, and have the container panel resize accordingly (and show the scrollbars if necessary) .

I ve tried all sorts of combinations with wrapping it with different panels, playing with the MinSize etc.. This is the best I came up with so far, but it s not what I want:

alt text

Does anyone have any ideas?

最佳回答

You could set a mouse hook when the mouse button is pressed and unhook it when the mouse button is released. In the hook callback, you can watch the mouse position and resize the control as appropriate.

Edit:

You could instead use a special control which the user can drag to hold the scroll position in the bottom right-hand corner of the parent container. The user could drag the control to make the area bigger and, if you are not using anchor or dock settings, you can manually adjust the size of your controls to fill the parent area.

I implemented something like this a while back for a project I did. I made it triangular and look like similar to the "grip" on a ToolStrip. Here s some code fragments from the ScrollHolder control:

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);
}

As far as the actual behavior implementation goes, you will probably want to:

  • Scroll to the scroll holder when it is moved outside the visible area:
  • When scrolling to the scroll holder, slow it down by calling Thread.Sleep for a short time (such as 50 ms).
问题回答

You need to set the MinExtra property of the Splitter to a large negative number. While the property itself doesn t allow this you could alter the field through reflection:

typeof(Splitter).GetField("minExtra", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(mySplitter, -10000);




相关问题
Bring window to foreground after Mutex fails

I was wondering if someone can tell me what would be the best way to bring my application to the foreground if a mutex was not able to be created for a new instance. E.g.: Application X is running ...

How to start WinForm app minimized to tray?

I ve successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

Handle DataTable.DataRow cell change event

I have a DataTable that has several DataColumns and DataRow. Now i would like to handle an event when cell of this DataRow is changed. How to do this in c#?

Apparent Memory Leak in DataGridView

How do you force a DataGridView to release its reference to a bound DataSet? We have a rather large dataset being displayed in a DataGridView and noticed that resources were not being freed after the ...

ALT Key Shortcuts Hidden

I am using VS2008 and creating forms. By default, the underscore of the character in a textbox when using an ampersand is not shown when I run the application. ex. "&Goto Here" is not ...

WPF-XAML window in Winforms Application

I have a Winforms application coded in VS C# 2008 and want to insert a WPF window into the window pane of Winforms application. Could you explain me how this is done.

热门标签