我在详细信息模式下有一个ListView控件,只有一列。它位于一个仅用于键盘的表格上,主要是用于向上/向下箭头滚动和输入以进行选择。所以我真的不需要滚动条,只是想让它们看起来更干净。但是,当我将ListView.Scrollable属性设置为false时,我仍然可以上下移动所选项目,但只要它移动到当前不在视图中的项目,列表就不会移动以显示该项目。我已经尝试使用EnsureVisible以编程方式滚动列表,但在此模式下它什么都不做。
有没有办法手动上下移动列表滚动,但没有滚动条?
答案 0 :(得分:13)
这不容易,但可以做到。如果您尝试通过ShowScrollBar隐藏滚动条,ListView将再次将其重新放回。所以你必须做一些更狡猾的事情。
您必须拦截WM_NCCALCSIZE消息,并在那里关闭垂直滚动样式。每当listview尝试再次打开它时,您将在此处理程序中再次将其关闭。
public class ListViewWithoutScrollBar : ListView
{
protected override void WndProc(ref Message m) {
switch (m.Msg) {
case 0x83: // WM_NCCALCSIZE
int style = (int)GetWindowLong(this.Handle, GWL_STYLE);
if ((style & WS_VSCROLL) == WS_VSCROLL)
SetWindowLong(this.Handle, GWL_STYLE, style & ~WS_VSCROLL);
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
const int GWL_STYLE = -16;
const int WS_VSCROLL = 0x00200000;
public static int GetWindowLong(IntPtr hWnd, int nIndex) {
if (IntPtr.Size == 4)
return (int)GetWindowLong32(hWnd, nIndex);
else
return (int)(long)GetWindowLongPtr64(hWnd, nIndex);
}
public static int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong) {
if (IntPtr.Size == 4)
return (int)SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
else
return (int)(long)SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, int dwNewLong);
}
这将为您提供一个没有滚动条的ListView,当您使用箭头键更改选择时,滚动条仍会滚动。
答案 1 :(得分:1)
由于ShowScrollBar不起作用,这可能会有所帮助:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private const int WM_VSCROLL = 0x115;
private const int SB_LINEDOWN = 1;
public Form1()
{
InitializeComponent();
for (int i = 0; i < 100; i++)
listView1.Items.Add("foo" + i);
listView1.Scrollable = false;
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
SendMessage(listView1.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
}
答案 2 :(得分:1)
我做了一些更轻松的事情。我将scrollable保持为true并使用了我在codeproject上找到的自定义滑块(colorSlider),我将滑块绘制在vscroller出现的位置,然后使用了ensureVisible函数。
答案 3 :(得分:0)
调用ShowScrollBar
API方法。
答案 4 :(得分:0)
如果ShowScrollBar
不起作用,我不知道该怎么做。
您可以将ListView放在面板中,使ListView比面板更宽,以便滚动条被切断(检查SystemInformation.VerticalScrollBarWidth
),但这是一个可怕的丑陋黑客。 / p>
答案 5 :(得分:0)
您可以使用ListView.Scrollable属性。将其设置为false并且不显示滚动条!