views:

246

answers:

1

I can't get scrolling working in my custom control. Currently it draws it's own content (at the moment just grid) and should be treated as having a large area to work in. However, I can't get scrolling to work.

With AutoScroll on, I can't get it to start of at the center of the workable area.

With AutoScroll off, I can't get the values of the scrollbars to stick whether I set them in code or you actually scroll.

To top it all off, when using individual HScroll and VScroll controls no scrollbars show at all.

The current state the code is trying with AutoScroll off, but I'm at the point where I concede I can't make it do what I want without help.

So please help!

Here's the code so far:

public partial class TwoDimensionViewport : ScrollableControl
{
    private readonly Point MinOffset = new Point(-4000000, -4000000);
    private readonly Point MaxOffset = new Point(4000000, 4000000);

    private Point viewOffset;

    public TwoDimensionViewport()
    {
        InitializeComponent();
        DoubleBuffered = true;
        GridSize = 16;
        AutoScroll = false;            
        AdjustFormScrollbars(true);
    }

    protected override void AdjustFormScrollbars(bool displayScrollbars)
    {            
        VerticalScroll.Minimum = 0;
        VerticalScroll.Maximum = 8000000;
        HorizontalScroll.Minimum = 0;
        HorizontalScroll.Maximum = 8000000;
        HorizontalScroll.Enabled = true;
        VerticalScroll.Enabled = true;            
        HorizontalScroll.Visible = true;
        VerticalScroll.Visible = true;

        HorizontalScroll.Value = viewOffset.X + 4000000;
        VerticalScroll.Value = viewOffset.Y + 4000000;            
    }        

    private ViewSettingsProvider viewSettingsProvider;
    public ViewSettingsProvider ViewSettingsProvider
    {
        get
        {
            return viewSettingsProvider;
        }
        set
        {
            UnbindViewSettingsProvider();
            viewSettingsProvider = value;
            BindViewSettingsProvider();
        }
    }

    public int GridSize { get; private set; }

    protected override void OnScroll(ScrollEventArgs se)
    {
        base.OnScroll(se);

        if (se.ScrollOrientation == ScrollOrientation.HorizontalScroll)
        {
            viewOffset.X = se.NewValue - 4000000;                
        }
        else if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
        {
            viewOffset.Y = se.NewValue - 4000000;
        }                        

        Invalidate();                        
    }

    protected override void OnPaint(PaintEventArgs pe)
    {            
        pe.Graphics.FillRectangle(Brushes.Black, pe.ClipRectangle);

        DrawGrid(pe.Graphics);            

        base.OnPaint(pe);
    }

    private void DrawGrid(Graphics graphics)
    {
        for (int i = 0, count = 0; i < ClientRectangle.Width; i++)
        {
            bool increaseCount = false;

            if ((i - viewOffset.X) % GridSize == 0)
            {
                graphics.DrawLine(
                    count % 5 == 0 ? Pens.White : Pens.DarkGray,
                    i, 0,
                    i, ClientRectangle.Height);

                increaseCount = true;
            }

            if ((i - viewOffset.Y) % GridSize == 0)
            {
                graphics.DrawLine(
                    count % 5 == 0 ? Pens.White : Pens.DarkGray,
                    0, i,
                    ClientRectangle.Width, i);

                increaseCount = true;
            }

            if (increaseCount)
                count++;
        }
    }

    private void BindViewSettingsProvider()
    {

    }

    private void UnbindViewSettingsProvider()
    {

    }
}
+2  A: 

Yeah, that looks like trouble. Derive your class from Panel instead. Set its AutoScroll to true, AutoMinSize property to the size of the scrollable grid. That automatically makes the scrollbars appear. Use the OnPaintBackground() method to draw the background and grid. You'll need to offset the drawing of the grid by the AutoScrollPosition property:

  protected override void OnPaintBackground(PaintEventArgs e) {
    e.Graphics.FillRectangle(Brushes.Black, this.ClientRectangle);
    e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
    for (int x = 0; x < this.AutoScrollMinSize.Width; x += GridSize) 
      e.Graphics.DrawLine(Pens.White, x, 0, x, this.AutoScrollMinSize.Height);
    for (int y = 0; y < this.AutoScrollMinSize.Height; y += GridSize)
      e.Graphics.DrawLine(Pens.White, 0, y, this.AutoScrollMinSize.Width, y);
  }
Hans Passant