C# ListView Disable Horizontal Scrollbar
Asked Answered
N

7

12

is there a way I can stop the horizontal scroll bar from ever showing up in a listview? I want the vertical scroll bar to show when needed but I want the horizontal scroll bar to never show up.

I would imagine it would have something to do with WndProc?

Thanks

Nappy answered 17/12, 2010 at 1:37 Comment(0)
V
4

You could try something like this, I used in a project once and it worked:

[DllImport ("user32")]
private static extern long ShowScrollBar (long hwnd , long wBar, long bShow);
long SB_HORZ = 0;
long SB_VERT = 1;
long SB_BOTH = 3;

private void HideHorizontalScrollBar ()
{
    ShowScrollBar(listView1.Handle.ToInt64(), SB_HORZ, 0);
}

Hope it helps.

Vtarj answered 17/12, 2010 at 2:16 Comment(4)
hi can you pls explain this, or can you tell me how i can read up on all these direct windows api callsBuiltin
Instead of long hwnd you could use IntPtr hwnd as the first parameter to the P/Invoke method.Blocking
Second that, for P/Invokes, alsways look at pinvoke. :) pinvoke.net/default.aspx/user32/ShowScrollBar.html gives signature [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ShowScrollBar(IntPtr hWnd, int wBar, [MarshalAs(UnmanagedType.Bool)] bool bShow); Only problem (I think) is IntPtr which Uwe already has mentioned.Wheedle
As already mentioned the P/Invoke definition of this answer is plain wrong - do not use it! long is 8 bytes while e.g. for a 32 bit process all arguments need to be 4 byte. It's just plain luck it works because 2nd and 3rd argument are zero.Pinna
T
10

There is a much simpler way to eliminate the lower scroll bar and have the vertical showing. It consists of making sure the header and if no header the rows are the width of the listview.Width - 4 and if the vertical scroll bar is show then listview.Width - Scrollbar.Width - 4;

the following code demostrates how to:

lv.Columns[0].Width = lv.Width - 4 - SystemInformation.VerticalScrollBarWidth;
Therapsid answered 4/5, 2015 at 20:22 Comment(3)
That is indeed a much cleaner approach than the selected answer and actually the root cause of the problem. The column(s) of the ListView need to be smaller. Thanks for that hint, it worked for me.Overrate
I don't think this will work if you use check box rows. Also I don't think that fixed values are good as other windows designs will maybe use different sizes. And last but not least this is not a cleaner approach. If you don't want a scroll bar you should hide/disable it and not adjust something else so it won't be shown. I don't like the p/Invoke solutions but it is still a better approach than the column width adjustment.Dismal
This worked for me as well, but in the final code snippet, shouldn't Width be changed to something like width or widthValue, to clarify that the answer isn't referring to this.Width inside of a UI component/control class? I almost edited the letter's case myself, but feel like the OP should verify that this is the intent.Franchot
A
6

The currently accepted answer is unsafe, as it unbalances the stack. you should use the following code instead for the DllImport:

[System.Runtime.InteropServices.DllImport("user32", CallingConvention=System.Runtime.InteropServices.CallingConvention.Winapi)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]

private static extern bool ShowScrollBar(IntPtr hwnd, int wBar, [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] bool bShow);

Andreas Reiff covers this in his comment after looking again, so I guess here it is all nicely formatted.


In order to use it:

# Use one of these valued for hwnd
long SB_HORZ = 0;
long SB_VERT = 1;
long SB_BOTH = 3;

# Use the actual name of the ListView control in your code here
# Hides the specified ListView scroll bar
ShowScrollBar(listView1.Handle.ToInt64(), SB_BOTH, 0);

To instead force it to show instead of hide, simply change bShow from 0 to 1, since 0 equates to false and 1 equates to true.

Agentive answered 31/1, 2013 at 22:55 Comment(3)
Any idea how to use this but still allow scrolling? I'd like to use for vertical scroll. ThanksAvalos
I believe hiding the scrollbar though has the side effect of disabling scrolling. I won't say it's impossible though as I've been out of writing WinForms for some time, but rather that I'm unaware of any method to hide the bar while still allowing scrolling.Agentive
@Agentive - if you're still about - could you point me towards further reading regarding why this is safer than bennyboi's code. I've got loads of DllImports in my code, but none use the attributes you've used - are these the things that render it 'safe'?Scipio
D
6

The best solution is the accepted answer that was given here: How to hide the vertical scroll bar in a .NET ListView Control in Details mode

It works perfectly and you don't need some tricks like column width adjustments. Moreover you disable the scrollbar right when you create the control.

The drawback is that you have to create your own list view class which derives from System.Windows.Forms.ListView to override WndProc. But this is the way to go.

To disable the horizontal scroll bar, remember to use WS_HSCROLL instead of WS_VSCROLL (which was used in the linked answer). The value for WS_HSCROLL is 0x00100000.

Dismal answered 19/10, 2016 at 14:23 Comment(0)
V
4

You could try something like this, I used in a project once and it worked:

[DllImport ("user32")]
private static extern long ShowScrollBar (long hwnd , long wBar, long bShow);
long SB_HORZ = 0;
long SB_VERT = 1;
long SB_BOTH = 3;

private void HideHorizontalScrollBar ()
{
    ShowScrollBar(listView1.Handle.ToInt64(), SB_HORZ, 0);
}

Hope it helps.

Vtarj answered 17/12, 2010 at 2:16 Comment(4)
hi can you pls explain this, or can you tell me how i can read up on all these direct windows api callsBuiltin
Instead of long hwnd you could use IntPtr hwnd as the first parameter to the P/Invoke method.Blocking
Second that, for P/Invokes, alsways look at pinvoke. :) pinvoke.net/default.aspx/user32/ShowScrollBar.html gives signature [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ShowScrollBar(IntPtr hWnd, int wBar, [MarshalAs(UnmanagedType.Bool)] bool bShow); Only problem (I think) is IntPtr which Uwe already has mentioned.Wheedle
As already mentioned the P/Invoke definition of this answer is plain wrong - do not use it! long is 8 bytes while e.g. for a 32 bit process all arguments need to be 4 byte. It's just plain luck it works because 2nd and 3rd argument are zero.Pinna
B
0

If you want a list view that show icon or value as horizontal just need to set alignment to left

Biometry answered 21/7, 2022 at 22:45 Comment(0)
C
0

I was personally looking for something very similar, but couldn't find out how to remove BOTH scrollbars yet still get the mouse wheel to work for a listview. I understand this doesn't exactly pertain to the original question asked, but if anyone stumbles upon this page looking to remove both scrollbars but still have vertical scrolling functionality, here is the code to do just that! I scoured the net and could not find the answer, and the question asked here is very very similar so please don't hate me for posting this here. And don't freak out with my while (1==1) loop haha! Also this is patch job code from many sources including my own so I cannot take full credit nor do I know the original sources of some of it. Just create a new custom control using this code (change the namespace to what you want). And you can just alter your design.cs file for the form it's on and reference this control instead of the original ListView (2 lines of code). Be sure that Scrollable is set to true but also set ScrollOverride to true otherwise it will act as a normal ListView.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace LancourWestbrook.Controls
{
    public partial class TPListView : ListView
    {
        [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);

        const int GWL_STYLE = -16;
        const int WS_VSCROLL = 0x00200000;
        const int WS_HSCROLL = 0x00100000;
        const int WM_MOUSEWHEEL = 0x20a;
        const int WM_NCCALCSIZE = 0x83;

        public TPListView()
        {
            InitializeComponent();
        }

        public TPListView(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }

        private int? LastItemIndexInView
        {
            get
            {
                if (this.Items == null || this.Items.Count <= 0)
                {
                    return null;
                }
                List<int> items = new List<int>();

                int topIndex = this.TopItem.Index;
                int currentIndex = topIndex;
                items.Add(topIndex);
                while (1 == 1)
                {
                    currentIndex++;
                    if (this.Items.Count - 1 < currentIndex)
                    {
                        break;
                    }
                    if (this.Items[currentIndex].Bounds.IntersectsWith(this.ClientRectangle))
                    {
                        items.Add(currentIndex);
                    }
                    else
                    {
                        break;
                    }
                }
                return currentIndex;
            }
        }

        public bool ScrollOverride { get; set; }

        protected override void WndProc(ref Message m)
        {            
            if (ScrollOverride == false)
            {
                base.WndProc(ref m);
                return;
            }
            switch (m.Msg)
            {
                case WM_MOUSEWHEEL:
                    if (this.Items == null || this.Items.Count <= 0)
                    {
                        break;
                    }
                    var zDelta = (short)HIWORD(m.WParam);
                    if (zDelta < 0)
                    {
                        //Scroll Downwards
                        int? lastItemInView = LastItemIndexInView;
                        if (lastItemInView.HasValue && this.Items.Count > lastItemInView.Value + 1)
                        {
                            this.Items[lastItemInView.Value + 1].EnsureVisible();
                        }
                        else if (this.Items.Count > 0)
                        {
                            this.Items[this.Items.Count - 1].EnsureVisible();
                        }
                    }
                    else if (zDelta > 0)
                    {
                        //Scroll Upwards
                        int topItemInView = this.TopItem.Index;
                        if (topItemInView > 0)
                        {
                            this.Items[topItemInView - 1].EnsureVisible();
                        }
                    }
                    break;
                case WM_NCCALCSIZE:
                    int style = (int)GetWindowLong(this.Handle, GWL_STYLE);
                    if ((style & WS_VSCROLL) == WS_VSCROLL)
                        SetWindowLong(this.Handle, GWL_STYLE, style & ~WS_VSCROLL);
                    if ((style & WS_HSCROLL) == WS_HSCROLL)
                        SetWindowLong(this.Handle, GWL_STYLE, style & ~WS_HSCROLL);                    
                    base.WndProc(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }


        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);
        }

        internal static ushort HIWORD(IntPtr dwValue)
        {
            return (ushort)((((long)dwValue) >> 0x10) & 0xffff);
        }
    }
}

Maybe someone can also add in code for a mouse wheel click and hold to scroll horizontally!

Chantell answered 9/6, 2023 at 20:18 Comment(0)
B
0

As stated in the comment to another answer, the automatic column size (when you specify the width of a column as "-2") is too wide and thus you have a horizontal scroll bar even if not needed, at least in Details view. There are several solutions to always hide the scrollbar. But for me the horizontal scrollbar should be shown if the text in the column is really too wide. So I determined the column width by my own with the TextRenderer class.

    public void SetItems(string[] itemNames) {
        int columnWidth = 0;
        this.Items.Clear();
            for (int i = 0; i < itemNames.Length; i++) {
                string text = itemNames[i];
                this.Items.Add(new ListViewItem(text));
                columnWidth = Math.Max(columnWidth, TextRenderer.MeasureText(text, this.Font).Width);
            }

        this.Columns[0].Width = columnWidth + 20; // + 20: I have set CheckBoxes property to true
    }
Bohn answered 25/2 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.