How to force vertical scrollbar always be visible

2019-01-26 08:37发布

问题:

Using VS2010 and .NET 4.0 with C# and WinForms:

I always want a Vertical Scrollbar to show for my panel as a disabled scrollbar (when it's not needed, and a enabled one when it can be used.

So it's like a hybrid AutoScroll. I've tried using VScrollBars but I can't figure out where to place them to make this work.

Essentially I've got a user control that acts as a "Document" of controls, its size changes so when using auto-scroll it works perfectly. The scrollbar appears when the usercontrol doesn't fit and the user can move it updown.

It's like a web browser essentially. However, redrawing controls takes a long time (it's forms with many fields and buttons etc within groups in a grid within a panel :P

So anyhow, when autoscroll enables the vertical scrollbar, it takes a while to redraw the window. I'd like to ALWAYS show the vertical scrollbar as indicated above (with the enable/disable functionality).

If anyone has some help, i've read many posts on the subject of autoscroll, but noone has asked what I'm asking and I can't come up with a solution.

回答1:

C# Version of competent_Tech's answer

using System.Runtime.InteropServices; 

public class MyUserControl : UserControl
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);

    private enum ScrollBarDirection
    {
        SB_HORZ = 0,
        SB_VERT = 1,
        SB_CTL = 2,
        SB_BOTH = 3
    }

    public MyUserControl()
    {
        InitializeComponent();
        ShowScrollBar(this.Handle, (int) ScrollBarDirection.SB_VERT, true);
    }
}


回答2:

You can use the auto-scroll functionality of the panel, you just need to send it a windows message to show the vertical scrollbar:

<DllImport("user32.dll")> _
Public Shared Function ShowScrollBar(ByVal hWnd As System.IntPtr, ByVal wBar As Integer, ByVal bShow As Boolean) As Boolean
End Function

Private Const SB_VERT As Integer = 1


Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ShowScrollBar(Panel1.Handle, SB_VERT, True)
End Sub

The scrollbar will be displayed and appear as though it can be scrolled, but it won't do anything until it is actually ready to scroll. If you disable it, it won't be automatically re-enabled, so this is probably the best approach.

Also, to improve the performance while resizing, you can call SuspendLayout on the panel before updating and ResumeLayout when done.



回答3:

Here is what solved this for me. My case is that I have a panel sandwiched between another three panels with no degree of liberty in any direction. I needed this panel to be so big that the whole structure would go out of my 1920x1080 screen. The solution is actually very simple. For the panel that needs scroll bars set the AutoScroll property to true. Then, add on it another control in the far right far down position (right-bottom position). The control I choose is a label which I made invisible.... And that is all. Now my panel occupies its restricted area, but I can scroll to the size that I needed and use it for the size I need. If you only need horizontal scroll bars add the invisible control outside left, for vertical only far down bottom.

The actual size of the panel is the one you restrict it to when display it, but the virtual size is dictated by the invisible control.



回答4:

What worked for me was overriding the CreateParams call and enabling the WS_VSCROLL style.

public class VerticalFlowPanel : FlowLayoutPanel
{
    protected override CreateParams CreateParams
    {
        get
        {
            var cp = base.CreateParams;
            cp.Style |= 0x00200000; // WS_VSCROLL
            return cp;
        }
    }
}

The AutoScroll logic will now adjust the scrolling bounds without ever hiding the scrollbar.