如何使用滑块同步两个树视图中的滚动

2024-02-25

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

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

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

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

}

我在表格中添加了其中两个。

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


您可以使用以下方法,而不是使用 SendMessage 并将您的 DLL 标记为不安全GetScrollPos and SetScrollPosuser32.dll 中的函数。

我已将代码包装到您的 MyTreeView 类中,因此它得到了很好的封装。

您只需要致电AddLinkedTreeView像这样的方法:

treeView1.AddLinkedTreeView(treeView2);

这是 MyTreeView 类的源代码。

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

Edit:按照 MinnesotaFat 的建议添加了 WM_MOUSEWHEEL 消息的转发。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用滑块同步两个树视图中的滚动 的相关文章

随机推荐

  • 将货币价值存储为美分/小单位有哪些缺点?

    我注意到一些金融 api 例如用于信用卡处理的 stripe api 要求将金额以美分形式传递 这似乎是一个很好的简化 这让我想知道为什么我不在我当前的应用程序中的所有地方都这样做在我的 Java 代码中使用数据库 NUMERIC 无限长度
  • 停止 shell 通配符扩展?

    有没有办法让编译后的命令行程序告诉 bash 或 csh 它不希望在其参数中扩展任何通配符 例如 人们可能需要一个 shell 命令 例如 foo 简单地返回该字符的 ASCII 数字值 不会 扩展发生在命令实际运行之前 您只能在运行命令之
  • 如何在报告中插入两页

    我面临一个问题 还有两个问题jrmxl文件 我想加入其中pdf文件 但每个都在一页中 我看到了下面的一些提示 但我不知道它们是否是最好的 因为我的第一个文件有 3 个频段 title detail and summary 第二个有detai
  • 如何获取 UITableView 标签文本字符串 - 自定义单元格

    我有一个带有自定义单元格的 UITableView 自定义单元格包含 UILabel 和 UIImageView 我在网上看到 当用户按下单元格时 可以从普通的 UITableView 单元格获取文本并将其存储在字符串中 但是 当您使用自定
  • 如何从不同的范围创建对象

    我在 Guice 中有一个范围单例的对象 在方法中f 我想创建一个新对象 但让 Guice 进行注入 我认为传递注射器并不是一个好的做法 那么我怎样才能获得一个新的 Guicy 对象实例呢 正如上面所建议的 提供商可能是做到这一点的方法 这
  • 功能检测自动播放 HTML5 音频 - 移动浏览器上的音频

    因此 我有一个网站 用户希望演示服务器端脚本生成的音频输出 他们选择一些选项并点击创建按钮 然后我在 HTML5 音频元素中进行 AJAX 并将 autoplay 属性设置为 true 这在桌面上效果很好 但在移动设备上效果不佳 到目前为止
  • 动态引用 Excel 工作表

    我有一个应该很简单的问题 但我没有解决它 我为一家商店打印了价目表 今年他们将零件编号分成了 5 张工作表 而不是一张 当用户想要打印价格标签时 她在 C10 中输入 单击工作表 价格表 并导航到她需要的零件号 C10 的计算公式为 价目表
  • 如何以编程方式从类的方法之一中查找类的公共属性

    我有课Foo具有公共和受保护的财产 Foo需要有一个非静态方法 getPublicVars 返回所有公共属性的列表Foo 这只是一个例子 我从outside the Foo对象调用get object vars http php net g
  • 使用主机系统上的客户端访问在虚拟机中运行的 HBase

    我尝试使用客户端程序将一些数据写入hbase HBase Hadoop 在 Cloudera ubuntu 的预配置虚拟机中运行 客户端运行在托管虚拟机的系统上 并直接在虚拟机中运行客户端 所以现在想使用vm外的客户端来访问vm上的服务器
  • 是否可以从命令行启动 IE 的代理设置对话框?

    有没有办法从 Windows 命令行启动 IE 代理设置对话框 以节省在任何应用程序中浏览菜单的时间 我发现了另一个更短的 inetcpl cpl 4 您可以在运行框或命令提示符中使用它
  • IE11 + Angular 1.5.11 上奇怪的渲染行为

    我们目前正在 Angular 版本 1 5 11 中开发一个应用程序 现在它已经变得相当大 数百个控制器等 我们偶然发现了 Internet Explorer 11 中的一个问题 一段时间后 有时是几分钟 有时是几个小时 页面开始出现渲染故
  • Visual Studio 无法识别我的网络摄像头激光测距仪代码的 MFC 库

    我尝试直接从互联网复制源代码 但由于下面发现的错误 我无法构建 调试整个文件 请帮忙 Error occurred while restoring NuGet packages System ArgumentException The pa
  • 如何使用 gdb 调试进程而不暂停它?

    我有一个已经在运行的进程 我想用 GDB 调试它 我一直在使用 gdb pid PID 但是 当我这样做时 该过程会暂停 我想附加到进程而不暂停它 并在它仍在运行时在其内存中查看 这可能吗 或者 有没有办法 分叉 该进程 以便我可以查看其内
  • canOpenUrl 失败,但 openUrl 成功

    我面临一个奇怪的问题 我正在使用 xcode 7 2 iOS 9 在真实设备 iphone 4S 不是模拟器 上工作 我有 2 个应用程序 app1 和 app2 app1 应该使用 url 方案将数据发送到 app2 app2已经很好地声
  • 为什么Python中只有主线程可以设置信号处理程序

    在Python的信号处理语义中 只有主线程可以设置信号处理程序 并且只有主线程可以调用信号处理程序 为什么要这样设计呢 此注释出现在 cpython 源文件中信号模块 c https github com python cpython bl
  • 无手拒绝错误:交易查询已完成 - knex、express.js

    我试图首先检查表中的值 如果存在 则删除另一个表中的行并将此新数据插入该表中 我使用了带有 select del 和 insert 命令的事务 db transaction trx gt return trx users where use
  • 没有为实体指定标识符/主键(...)每个实体都必须具有标识符/主键

    I have Peticion实体 但缺少某些内容 因为出现以下错误 No identifier primary key specified for Entity Every Entity must have and identifier
  • cocos2d-x android 设置错误 - java.lang.NullPointerException

    我正在尝试设置适用于 Android 的 cocos2d x我跟着 我通过了终端的步骤 没有任何问题 setup py命令结果符合预期 我的问题是在我设置之后NDK ROOT in C C 构建 环境部分 我得到一些java lang Nu
  • 如何修复猫鼬中的“.create 不是函数”错误

    我正在尝试初始化 Seed js 文件以在我的数据库中启动一些内容 但是当我运行时node bin seed js我不断得到 TypeError Celebrity create is not a function 我已尝试重新安装mong
  • 如何使用滑块同步两个树视图中的滚动

    我正在使用 Visual Studio 2010 C 和 Windows 窗体应用程序 我有两个并排的树视图 并且我已经弄清楚如何使用滚动条上的向上 向下按钮同步滚动 但是当我使用滑块时 它不会移动另一个树视图 我采取了一个有效的列表视图示