views:

48

answers:

1

I'm writing a custom control which consists of a FlowLayoutPanel nested in a normal Panel. The FlowLayoutPanel is internal to the class, and shouldn't be able to be viewed by the designer (unlike a Tab, which has its individual properties exposed.) Any control the designer adds to the Panel should instead be added to the FlowLayoutPanel. Here's what I have so far:

public class SlidePanel : Panel
{
    private FlowLayoutPanel _panel;

    public SlidePanel()
        : base()
    {
        _panel = new FlowLayoutPanel();
        Controls.Add(_panel);
        _panel.Location = new Point(0, 0);
        _panel.Size = base.Size;
        _panel.Anchor = AnchorStyles.Bottom | AnchorStyles.Top;

        ControlAdded += new ControlEventHandler(SlidePanel_ControlAdded);
    }

    void SlidePanel_ControlAdded(object sender, ControlEventArgs e)
    {
        Controls.Remove(e.Control);
        _panel.Controls.Add(e.Control);
    }
}

This works for controls added during runtime, but when I try to add a control during design time, it either says 'child' is not a child control of this parent. or adds the control the the form instead. I'm assuming there's a cleaner, nicer way to accomplish this?


Test of Flynn1179's suggestion:

public class SlideControl : FlowLayoutPanel
{
    private const int SB_HORZ = 0x0;
    private const int SB_VERT = 0x1;

    [DllImport("user32.dll")]
    private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
    [DllImport("user32.dll")]
    private static extern int GetScrollPos(IntPtr hWnd, int nBar);

    public SlideControl()
        : base()
    {
        this.MouseMove += new MouseEventHandler(SlideControl_MouseMove);
    }

    void SlideControl_MouseMove(object sender, MouseEventArgs e)
    {
        HScrollPos = e.X;
        VScrollPos = e.Y;
    }

    protected int HScrollPos
    {
        get { return GetScrollPos((IntPtr)this.Handle, SB_HORZ); }
        set { SetScrollPos((IntPtr)this.Handle, SB_HORZ, value, true); }
    }

    protected int VScrollPos
    {
        get { return GetScrollPos((IntPtr)this.Handle, SB_VERT); }
        set { SetScrollPos((IntPtr)this.Handle, SB_VERT, value, true); }
    }
}
A: 

Have you considered having SlidePanel inherit directly from FlowLayoutPanel rather than contain one?

Flynn1179
`SlidePanel` is going to move the `FlowLayoutPanel` back and forth (hence `Slide`,) so it needs to be a separate container.
Daniel Rasmussen
In what way? You may be able to manipulate the position of the contents using the padding settings
Flynn1179
Similarly to the way a scroll bar works, but done automatically on mouseover, with no scroll bar. The point is to allow the user to drag and drop onto a long list of controls.
Daniel Rasmussen
Ah, I see.. I think this should still work; if you set the `WrapContents` property to false, the contents will just arrange in a long horizontal line. You'll still need to set the scroll position manually using your mouse-over mechanism though.
Flynn1179
I'm still not sure how I'm supposed to move them back and forth... Obviously, I'm not trying to move the entire *control* back and forth, just the children of the control, which, in an FLP, are laid out automatically.
Daniel Rasmussen
This might be useful: http://www.pinvoke.net/default.aspx/user32.setscrollpos
Flynn1179
It looked good, but does absolutely nothing. =/ I'll add what I tried to the question.
Daniel Rasmussen
Yeah, that's confusing me too; curiously enough, if you add scrollbars in temporarily, they DO move, but the contents of the control don't. I'm scratching my head over that one. There is a `HorizontalScroll.Value` property that can be set, but that doesn't seem to work if the scroll bar's not visible.
Flynn1179