如何使用滑块在两个树视图中同步滚动 [英] How do I sync scrolling in two treeviews using the slider

查看:29
本文介绍了如何使用滑块在两个树视图中同步滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Visual Studio 2010 (C#) 和 Windows 窗体应用程序.

I am using Visual Studio 2010 (C#) and a Windows Forms application.

我有两个并排的树视图,我想出了如何使用滚动条上的向上/向下按钮同步滚动,但是当我使用滑块时,它不会移动另一个树视图.我采用了一个有效的列表视图示例,但相同的代码不适用于树视图.

I have two treeviews side by side, and I have figured out how to synchronise the scrolling using the up/down buttons on the scrollbar, but when I use the slider it does not move the other treeview. I have taken a listview example that works, but the same code does not work for treeviews.

到目前为止,我有,主要形式:

So far I have, in the main form:

    [DllImport("User32.dll")]
    public static extern int SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);

    private void myListBox1_Scroll(ref Message m)
    {
        SendMessage(myListBox2.Handle, (uint)m.Msg, (uint)m.WParam, (uint)m.LParam);
    }

我创建了一个控件:

public partial class MyTreeView : TreeView
{
    public MyTreeView()
    {
        InitializeComponent();
    }

    public event ScrollEventHandler Scroll;
    public delegate void ScrollEventHandler(ref Message m);


    private const int WM_VSCROLL = 0x115;

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        if (m.Msg == WM_VSCROLL)
            if (Scroll != null)
            {
                Scroll(ref m);
            }

        base.WndProc(ref m);
    }

}

我在表单中添加了两个.

which I add two of to the form.

我可以使用相同的代码让 listivew 控制树视图,如果您拖动滑块,这将起作用,但反过来,它仅适用于向上向下按钮.

I can use the same code to have a listivew control the treeview and that will work if you drag the slider, but in reverse it only works with the up down buttons.

推荐答案

您可以使用 GetScrollPosSetScrollPos 函数,而不是使用 SendMessage 并将您的 DLL 标记为不安全user32.dll.

Rather than use SendMessage and mark your DLL as unsafe you can use the GetScrollPos and SetScrollPos functions from user32.dll.

我已将代码封装到您的 MyTreeView 类中,以便对其进行很好的封装.

I've wrapped the code up into your MyTreeView class so it's nicely encapsulated.

您只需要像这样调用 AddLinkedTreeView 方法:

You just need to call the AddLinkedTreeView method like so:

treeView1.AddLinkedTreeView(treeView2);

这是 MyTreeView 类的源代码.

Here's the source for the MyTreeView class.

public partial class MyTreeView : TreeView
{
    public MyTreeView() : base()
    {
    }

    private List<MyTreeView> linkedTreeViews = new List<MyTreeView>();

    /// <summary>
    /// Links the specified tree view to this tree view.  Whenever either treeview
    /// scrolls, the other will scroll too.
    /// </summary>
    /// <param name="treeView">The TreeView to link.</param>
    public void AddLinkedTreeView(MyTreeView treeView)
    {
        if (treeView == this)
            throw new ArgumentException("Cannot link a TreeView to itself!", "treeView");

        if (!linkedTreeViews.Contains(treeView))
        {
            //add the treeview to our list of linked treeviews
            linkedTreeViews.Add(treeView);
            //add this to the treeview's list of linked treeviews
            treeView.AddLinkedTreeView(this);

            //make sure the TreeView is linked to all of the other TreeViews that this TreeView is linked to
            for (int i = 0; i < linkedTreeViews.Count; i++)
            {
                //get the linked treeview
                var linkedTreeView = linkedTreeViews[i];
                //link the treeviews together
                if (linkedTreeView != treeView)
                    linkedTreeView.AddLinkedTreeView(treeView);
            }
        }
    }

    /// <summary>
    /// Sets the destination's scroll positions to that of the source.
    /// </summary>
    /// <param name="source">The source of the scroll positions.</param>
    /// <param name="dest">The destinations to set the scroll positions for.</param>
    private void SetScrollPositions(MyTreeView source, MyTreeView dest)
    {
        //get the scroll positions of the source
        int horizontal = User32.GetScrollPos(source.Handle, Orientation.Horizontal);
        int vertical = User32.GetScrollPos(source.Handle, Orientation.Vertical);
        //set the scroll positions of the destination
        User32.SetScrollPos(dest.Handle, Orientation.Horizontal, horizontal, true);
        User32.SetScrollPos(dest.Handle, Orientation.Vertical, vertical, true);
    }

    protected override void WndProc(ref Message m)
    {
        //process the message
        base.WndProc(ref m);

        //pass scroll messages onto any linked views
        if (m.Msg == User32.WM_VSCROLL || m.Msg == User32.WM_MOUSEWHEEL)
        {
            foreach (var linkedTreeView in linkedTreeViews)
            {
                //set the scroll positions of the linked tree view
                SetScrollPositions(this, linkedTreeView);
                //copy the windows message
                Message copy = new Message
                {
                    HWnd = linkedTreeView.Handle,
                    LParam = m.LParam,
                    Msg = m.Msg,
                    Result = m.Result,
                    WParam = m.WParam
                };
                //pass the message onto the linked tree view
                linkedTreeView.RecieveWndProc(ref copy);
            }                               
        }
    }

    /// <summary>
    /// Recieves a WndProc message without passing it onto any linked treeviews.  This is useful to avoid infinite loops.
    /// </summary>
    /// <param name="m">The windows message.</param>
    private void RecieveWndProc(ref Message m)
    {
        base.WndProc(ref m);
    }

    /// <summary>
    /// Imported functions from the User32.dll
    /// </summary>
    private class User32
    {
        public const int WM_VSCROLL = 0x115;
        public const int WM_MOUSEWHEEL = 0x020A;  

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar);

        [DllImport("user32.dll")]
        public static extern int SetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar, int nPos, bool bRedraw);
    }
}

编辑:根据 MinnesotaFat 的建议添加了 WM_MOUSEWHEEL 消息的转发.

Edit: Added forwarding of the WM_MOUSEWHEEL message as per MinnesotaFat's suggestion.

这篇关于如何使用滑块在两个树视图中同步滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆