将VS2010和.NET 4.0与C#和WinForms一起使用:
我总是希望将一个垂直滚动条显示为我的面板作为禁用滚动条(当不需要时,以及启用它时可以使用它。
所以它就像一个混合的AutoScroll。我已经尝试过使用VScrollBars,但我无法弄清楚将它们放在哪里以使其工作。
基本上我有一个用户控件充当控件的“文档”,它的大小会发生变化,因此在使用自动滚动时它可以很好地工作。当用户控件不适合并且用户可以将其向上移动时,会出现滚动条。
它本质上就像一个网络浏览器。但是,重绘控件需要很长时间(它是在面板中的网格中的组内具有许多字段和按钮等的形式:P
所以无论如何,当autoscroll启用垂直滚动条时,重绘窗口需要一段时间。我想总是如上所示显示垂直滚动条(启用/禁用功能)。
如果有人有一些帮助,我已经阅读了很多关于autoscroll主题的帖子,但是没有人问我在问什么,我无法提出解决方案。
答案 0 :(得分:8)
C#版本的competent_Tech回答
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);
}
}
答案 1 :(得分:4)
您可以使用面板的自动滚动功能,只需向其发送一条Windows消息即可显示垂直滚动条:
<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
滚动条将显示并显示为可滚动,但在实际准备滚动之前不会执行任何操作。如果禁用它,它将不会自动重新启用,因此这可能是最好的方法。
另外,为了在调整大小时提高效果,您可以在更新前调用面板上的SuspendLayout,并在完成后调用ResumeLayout。
答案 2 :(得分:2)
对我有用的是覆盖CreateParams
来电和启用WS_VSCROLL
风格。
public class VerticalFlowPanel : FlowLayoutPanel
{
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.Style |= 0x00200000; // WS_VSCROLL
return cp;
}
}
}
AutoScroll
逻辑现在将调整滚动边界,而不会隐藏滚动条。
答案 3 :(得分:1)
这是为我解决这个问题的原因。我的情况是,我有一个夹在另外三个面板之间的面板,在任何方向都没有自由度。我需要这个面板这么大,以至于整个结构都会超出我的1920x1080屏幕。 解决方案实际上非常简单。 对于需要滚动条的面板,将AutoScroll属性设置为true。然后,在最右下方的位置(右下方位置)添加另一个控件。我选择的控件是一个我看不见的标签....这就是全部。 现在我的面板占据了它的限制区域,但是我可以滚动到我需要的尺寸并将其用于我需要的尺寸。 如果您只需要水平滚动条,请在左侧外部添加隐形控件,仅在垂直方向下方向下添加。
面板的实际尺寸是在显示时限制它的尺寸,但虚拟尺寸由不可见控件决定。
答案 4 :(得分:0)
每当面板的内置滚动条不可见时,此代码将绘制一个禁用的垂直滚动条。该代码假定
AutoScroll = true;
AutoSize = false;
下面的代码是速度优化的。它在OnPaint()中做的越少越好。
从Panel派生一个类。 添加以下成员变量:
// NOTE: static variables are not thread safe.
// But as we have only one GUI thread this does not matter.
static IntPtr mh_ScrollTheme = IntPtr.Zero;
static int ms32_ScrollWidth = SystemInformation.VerticalScrollBarWidth;
Win32.RECT mk_ScrollTop;
Win32.RECT mk_ScrollBot; // coordinates of top scrollbar button
Win32.RECT mk_ScrollShaft; // coordinates of bottom scrollbar button
然后覆盖OnSizeChanged:
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
Win32.RECT k_ScrollBar = new Win32.RECT(ClientRectangle);
k_ScrollBar.Left = k_ScrollBar.Right - ms32_ScrollWidth;
mk_ScrollTop = new Win32.RECT(k_ScrollBar);
mk_ScrollBot = new Win32.RECT(k_ScrollBar);
mk_ScrollShaft = new Win32.RECT(k_ScrollBar);
int s32_Upper = k_ScrollBar.Top + ms32_ScrollWidth;
int s32_Lower = k_ScrollBar.Bottom - ms32_ScrollWidth;
mk_ScrollTop .Bottom = s32_Upper;
mk_ScrollBot .Top = s32_Lower;
mk_ScrollShaft.Top = s32_Upper;
mk_ScrollShaft.Bottom = s32_Lower;
}
并在需要时绘制滚动条:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (VScroll)
return; // The 'real' scrollbar is visible
if (mh_ScrollTheme == IntPtr.Zero)
mh_ScrollTheme = Win32.OpenThemeData(Handle, "SCROLLBAR");
if (mh_ScrollTheme == IntPtr.Zero)
return; // The user has disabled themes
// Draw the disabled vertical scrollbar.
IntPtr h_DC = e.Graphics.GetHdc();
// Draw shaft
const int SBP_UPPERTRACKVERT = 7;
const int SCRBS_DISABLED = 4;
Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_UPPERTRACKVERT, SCRBS_DISABLED, ref mk_ScrollShaft, IntPtr.Zero);
// Draw top button
const int SBP_ARROWBTN = 1;
const int ABS_UPDISABLED = 4;
Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_ARROWBTN, ABS_UPDISABLED, ref mk_ScrollTop, IntPtr.Zero);
// Draw lower button
const int ABS_DOWNDISABLED = 8;
Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_ARROWBTN, ABS_DOWNDISABLED, ref mk_ScrollBot, IntPtr.Zero);
e.Graphics.ReleaseHdc(h_DC);
}