Vertical & Horizontal scrollbars in a panel

2013-10-07 vb.net scrollbar panels

Scenario:

  • Put a panel on a form.
  • Set the panel's BorderStyle to FixedSingle. (Just so you can see it when you run it.)
  • Set the panel's AutoScroll=True
  • Set the panel's Anchor to Top, Left, Bottom, Right
  • Inside the panel, place any sizable control (button, picturebox or whatever).
  • Adjust the control's bottom edge to be just a few pixels above the bottom of the panel.
  • Adjust the control's right edge should be a few pixels more narrow than the panel MINUS the width of a vertical scrollbar. (That is, it should be just narrow enough to leave room for a vertical scrollbar to may appear.)

Now run it, and vertically resize the form a little shorter so that you'd expect a VERTICAL scrollbar to appear.

Problem: BOTH scrollbars appear, because the very existence of the vertical scrollbar reduces the width of the client area, thus forcing a horizontal scrollbar to appear.

Apparently .NET evaluates whether a vertical scrollbar is necessary first, then evaluates whether the horizontal should appear, which is dependent upon whether the client size is reduced by the presence of a vertical scxrollbar. (i.e. the same experiment doesn't cause unnecessary VERTICAL scrollbars to appear... only horizontal ones.)

I'm using VB2008 Express but I'm guessing this carries over to later versions.

THE SOLUTION I NEED: I need either of: A) A "vertical autoscroll only" panel. B) I need a way to tell the panel to "rethink" whether the horizontal scrollbar is actually necessary. (Refreshes don't seem to do it.)

Answers

I ran into something that sounds like what you describe. I wanted just a Vertical scroll because it was going to contain many many things eventually, but not a Horizontal scroll. I used a table layout panel; set the Panel's Vertical size so that the VScroll shows; set the width to accommodate what will go in there plus whatever margin or gutter your code will use.

Then, in the TableLayoutPanel set the width of the scrolling panel's to absolute (I used 2 pixels more than the panel.width). If/when the user resizes, all the extra size gets distributed to everything else. Basically dont let the scrolling panel's width change. Might have to/want to set a minimum form size too.

The things I was adding were all the same width, if yours vary, you might have to set it to accommodate the widest.

Not sure if you are encountering the same thing, but sure sounds like it.

The AutoScroll property does not allow you to have too much control on the scrollbars (even though you have VerticalScroll and HorizontalScroll properties).

Out of the proposed alternatives, I go for option A; the marked answer in this post gives a quite effective solution to an equivalent problem. Converted & adapted code (where Panel1 is the panel referred in your question):

Private Declare Function ShowScrollBar Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal wBar As Integer, ByVal bShow As Boolean) As Boolean
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Try
        ShowScrollBar(Panel1.Handle, 0, False)
    Catch ex As Exception
    End Try
    MyBase.WndProc(m)
End Sub

If you set the AutoScroll property of your panel to true and add this code, you would get what you are looking for.

NOTE: the proposed code works but at certain price: I personally intend to avoid Protected Overrides Sub WndProc codes as much as possible. If getting exactly this functionality is important for you, rely on the proposed methodology; otherwise, you might have to consider other alternatives (e.g., AutoScroll = False and adding a VScrollBar to the panel, which will always be there).

In order to use panel autoscroll property I do that:

  1. panel.AutoScroll = False (is inverse I know :D)
  2. panel.VerticalScroll.Visible = False or panel.HorizontalScroll.Visible = False

In order to know the dimensions of the scroolbars use

SystemInformation.HorizontalScrollBarHeight
SystemInformation.VerticalScrollBarWidth

So you can change the dimension of the panel when the scroolbar is shown.

Related