滚动条恢复到之前的位置

时间:2015-08-25 20:46:39

标签: c# winforms winapi scrollbar

我正在使用辅助Scrollbar进行一些手动滚动。我使用GetScrollInfo API来获取Scrollbar的跟踪位置。但是,当滚动结束时,轨道位置将恢复到其最后设定位置。因此,我使用SetScrollInfo API在滚动结束后设置滚动信息,但之后只能在鼠标移动后直观地更新。我该怎么做才能解决这个问题?

ScrollUtility:

public class ScrollUtility
{
    [DllImportAttribute("user32.dll")]
    [PreserveSigAttribute()]
    public static extern int SetScrollInfo(
       IntPtr hWnd,
       int fnBar,
       ref SCROLLINFO si,
       bool redraw
    );

    [DllImport("user32.dll")]
    [PreserveSigAttribute()]
    public static extern bool GetScrollInfo(
        IntPtr hwnd,
        int fnBar,
        ref SCROLLINFO ScrollInfo
    );
}

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct SCROLLINFO
{
    public uint cbSize;
    public uint fMask;
    public int nMin;
    public int nMax;
    public uint nPage;
    public int nPos;
    public int nTrackPos; // Ignored by setter

    public override string ToString()
    {
        return cbSize + " " + fMask + " " + nMin + " " + nMax + " " + nPage + " " + nPos + " " + nTrackPos;
    }

    public const int SB_HORZ = 0x0000;
    public const int SB_VERT = 0x0001;
    public const int WM_HSCROLL = 0x0114;
    public const int WM_VSCROLL = 0x0115;
    public const int SB_THUMBPOSITION = 4;

    public enum ScrollInfoMask : uint
    {
        SIF_RANGE = 0x1,
        SIF_PAGE = 0x2,
        SIF_POS = 0x4,
        SIF_DISABLENOSCROLL = 0x8,
        SIF_TRACKPOS = 0x10,
        SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
    }
}

Form1中:

public partial class Form1 : Form
{
    private bool setOnStartUp = true; // Track position will not update if this is false
    private bool setOnEndScroll = true; // Track position reverts to last set position if this is false, but still doesn't update visually if this is true until the mouse moves.

    public Form1()
    {
        InitializeComponent();

        if (setOnStartUp)
        {
            SCROLLINFO info = new SCROLLINFO
            {
                cbSize = (uint)Marshal.SizeOf(typeof(SCROLLINFO)),
                fMask = (uint)SCROLLINFO.ScrollInfoMask.SIF_ALL,
                nMax = 1000,
                nMin = 0,
                nPage = 50,
                nPos = 500, // The middle of the scroll bar - just for testing
            };

            // Am I using the right handle?
            ScrollUtility.SetScrollInfo(vScrollBar.Handle, SCROLLINFO.SB_VERT, ref info, true);
        }
    }

    private void vScrollBar_Scroll(object sender, ScrollEventArgs e)
    {
        SCROLLINFO info = new SCROLLINFO
        {
            cbSize = (uint)Marshal.SizeOf(typeof(SCROLLINFO)),
            fMask = (uint)SCROLLINFO.ScrollInfoMask.SIF_ALL
        };
        ScrollUtility.GetScrollInfo(vScrollBar.Handle, SCROLLINFO.SB_VERT, ref info);

        label.Text = "Track: " + info.nTrackPos;

        if (setOnEndScroll)
        {
            if (e.Type == ScrollEventType.EndScroll)
            {
                info.nPos = info.nTrackPos;
                ScrollUtility.SetScrollInfo(vScrollBar.Handle, SCROLLINFO.SB_VERT, ref info, true);
            }
        }
    }
}

0 个答案:

没有答案