【问题标题】:Scrolling two listboxes ( Windows Form ) at same time同时滚动两个列表框(Windows 窗体)
【发布时间】:2015-01-14 15:05:04
【问题描述】:

基本上我在表单上有两个列表框syncListView1和syncListView2(windows表单应用程序)我试图让他们的滚动条同步

我用谷歌搜索了一些,我找到了这个类,但它似乎不起作用:

 class SyncListBox : System.Windows.Forms.ListBox
    {
        [Category("Action")]
        private const int WM_HSCROLL = 0x114;
        private const int WM_VSCROLL = 0x115;
        public event ScrollEventHandler OnHorizontalScroll;
        public event ScrollEventHandler OnVerticalScroll;

        private const int SB_LINEUP = 0;
        private const int SB_LINELEFT = 0;
        private const int SB_LINEDOWN = 1;
        private const int SB_LINERIGHT = 1;
        private const int SB_PAGEUP = 2;
        private const int SB_PAGELEFT = 2;
        private const int SB_PAGEDOWN = 3;
        private const int SB_PAGERIGHT = 3;
        private const int SB_THUMBPOSITION = 4;
        private const int SB_THUMBTRACK = 5;
        private const int SB_PAGETOP = 6;
        private const int SB_LEFT = 6;
        private const int SB_PAGEBOTTOM = 7;
        private const int SB_RIGHT = 7;
        private const int SB_ENDSCROLL = 8;
        private const int SIF_TRACKPOS = 0x10;
        private const int SIF_RANGE = 0x1;
        private const int SIF_POS = 0x4;
        private const int SIF_PAGE = 0x2;
        private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetScrollInfo(
        IntPtr hWnd, int n, ref ScrollInfoStruct lpScrollInfo);

        private struct ScrollInfoStruct
        {
            public int cbSize;
            public int fMask;
            public int nMin;
            public int nMax;
            public int nPage;
            public int nPos;
            public int nTrackPos;
        }
        protected override void WndProc(ref System.Windows.Forms.Message msg)
        {
            if (msg.Msg == WM_HSCROLL)
            {
                if (OnHorizontalScroll != null)
                {
                    ScrollInfoStruct si = new ScrollInfoStruct();
                    si.fMask = SIF_ALL;
                    si.cbSize = Marshal.SizeOf(si);
                    GetScrollInfo(msg.HWnd, 0, ref si);
                    if (msg.WParam.ToInt32() == SB_ENDSCROLL)
                    {
                        ScrollEventArgs sargs = new ScrollEventArgs(
                        ScrollEventType.EndScroll,
                        si.nPos);
                        OnHorizontalScroll(this, sargs);
                    }
                }
            }
            if (msg.Msg == WM_VSCROLL)
            {
                if (OnVerticalScroll != null)
                {
                    ScrollInfoStruct si = new ScrollInfoStruct();
                    si.fMask = SIF_ALL;
                    si.cbSize = Marshal.SizeOf(si);
                    GetScrollInfo(msg.HWnd, 0, ref si);
                    if (msg.WParam.ToInt32() == SB_ENDSCROLL)
                    {
                        ScrollEventArgs sargs = new ScrollEventArgs(
                        ScrollEventType.EndScroll,
                        si.nPos);
                        OnVerticalScroll(this, sargs);
                    }
                }
            }
            base.WndProc(ref msg);
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // scrolled
            // 
            this.Size = new System.Drawing.Size(120, 95);
            this.ResumeLayout(false);
        }
    }

在后面的代码中:

private void syncListView2_OnVerticalScroll(object sender, ScrollEventArgs e)
        {
            syncListView1.TopIndex = syncListView2.TopIndex;
        }

        private void syncListView1_OnVerticalScroll(object sender, ScrollEventArgs e)
        {
            syncListView2.TopIndex = syncListView1.TopIndex;
        }

【问题讨论】:

  • 你的问题是什么?
  • 它不起作用我需要帮助才能使它起作用
  • 他在问如何同时滚动两个列表框。
  • it does not seem to work请解释一下。
  • 您似乎没有为您的syncListBoxes订阅您的活动..

标签: c# winforms


【解决方案1】:

你不需要派生类 SyncListBox

只需为 windows 窗体 InitializeComponent() 或 windows 窗体构造函数中的列表框附加事件处理程序,如下所示

EventHandler handler = (s,e) =>{
            if (s == syncListView1)
                syncListView2.TopIndex = syncListView1.TopIndex;
            if (s == syncListView2)
                syncListView1.TopIndex = syncListView2.TopIndex;
        };

this.syncListView1.MouseCaptureChanged += handler;
this.syncListView2.MouseCaptureChanged += handler;
this.syncListView1.SelectedIndexChanged += handler;
this.syncListView2.SelectedIndexChanged += handler;

【讨论】:

    【解决方案2】:

    这对copy/paste code from article 来说是非常糟糕的做法,甚至不必费心阅读有关代码和用户评论的所有内容。你不是第一个被困在这个地方的人......因为one user already commented the problem

    所以您可能错过的是订阅事件。有两个选项可以做到这一点:

    1. 在设计器窗口中选择第一个列表框。然后在属性窗口中选择事件选项卡(1.)并查找 OnVerticalScroll 事件。当您找到它时,单击下拉按钮 (2.)。该列表应至少包含 2 个选项 syncListView1_OnVerticalScroll 和 syncListView1_OnVerticalScroll。所以选择syncListView1_OnVerticalScroll。对第二个列表框做同样的事情,但选择syncListView1_OnVerticalScrol2

    1. 在您有列表框的表单中打开代码视图。应该有构造函数在哪里调用InitializeComponent() 方法。在该方法之后添加以下代码行。

      syncListView1.OnVerticalScroll += this.syncListView1_OnVerticalScroll; syncListView2.OnVerticalScroll += this.syncListView2_OnVerticalScroll;

    【讨论】:

    • 我应该在哪里插入这段代码对不起我在这里有点新
    • 我更新了我的答案。添加了如何订阅事件的选项。
    • 嗯列表框事件中没有这样的事件,当我尝试第二个选项时给我错误 System.. 不包含 OnVerticalScroll 的定义
    • 你确定你放在表单 SyncListBox 控件上吗?在设计器中选择它并查看属性窗口。在该行(图片中的 btnAddRelease 所在位置)中,您应该看到 syncListView1 ***.SyncListBox。我猜它会是 ListView。
    • 如果您没有看到 SyncListBox,请删除您的列表框。构建解决方案并尝试在工具箱窗口中找到 SyncListBox。它应该显示为类似this 的齿轮并命名为SyncListBox。把它们放在你的表格中,然后按照我在答案中写的去做
    【解决方案3】:

    另一个例子...这个例子可以让你保留原来的 .Net ListBoxes,只需将它们传递给 Form 的 Load() 事件中的 SyncListBoxes 的构造函数。这将处理垂直滚动、鼠标滚轮滚动以及当 ListBoxes 由于键盘输入而滚动时(通过 SelectedIndexChanged 事件):

    public partial class Form1 : Form
    {
    
        private SyncListBoxes _SyncListBoxes = null;
    
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            this._SyncListBoxes = new SyncListBoxes(this.syncListView1, this.syncListView2);
        }
    
    }
    
    public class SyncListBoxes
    {
    
        private ListBox _LB1 = null;
        private ListBox _LB2 = null;
    
        private ListBoxScroll _ListBoxScroll1 = null;
        private ListBoxScroll _ListBoxScroll2 = null;
    
        public SyncListBoxes(ListBox LB1, ListBox LB2)
        {
            if (LB1 != null && LB1.IsHandleCreated && LB2 != null && LB2.IsHandleCreated && 
                LB1.Items.Count == LB2.Items.Count && LB1.Height == LB2.Height)
            {
                this._LB1 = LB1;
                this._ListBoxScroll1 = new ListBoxScroll(LB1);
                this._ListBoxScroll1.Scroll += _ListBoxScroll1_VerticalScroll;
    
                this._LB2 = LB2;
                this._ListBoxScroll2 = new ListBoxScroll(LB2);
                this._ListBoxScroll2.Scroll += _ListBoxScroll2_VerticalScroll;
    
                this._LB1.SelectedIndexChanged += _LB1_SelectedIndexChanged;
                this._LB2.SelectedIndexChanged += _LB2_SelectedIndexChanged;
            }
        }
    
        private void _LB1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this._LB2.TopIndex != this._LB1.TopIndex)
            {
                this._LB2.TopIndex = this._LB1.TopIndex;
            }
            if (this._LB2.SelectedIndex != this._LB1.SelectedIndex)
            {
                this._LB2.SelectedIndex = this._LB1.SelectedIndex;
            }
        }
    
        private void _LB2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this._LB1.TopIndex != this._LB2.TopIndex)
            {
                this._LB1.TopIndex = this._LB2.TopIndex;
            }
            if (this._LB1.SelectedIndex != this._LB2.SelectedIndex)
            {
                this._LB1.SelectedIndex = this._LB2.SelectedIndex;
            }
        }
    
        private void _ListBoxScroll1_VerticalScroll(ListBox LB)
        {
            if (this._LB2.TopIndex != this._LB1.TopIndex)
            {
                this._LB2.TopIndex = this._LB1.TopIndex;
            }
        }
    
        private void _ListBoxScroll2_VerticalScroll(ListBox LB)
        {
            if (this._LB1.TopIndex != this._LB2.TopIndex)
            {
                this._LB1.TopIndex = this._LB2.TopIndex;
            }
        }
    
        private class ListBoxScroll : NativeWindow
        {
    
            private ListBox _LB = null;
            private const int WM_VSCROLL = 0x115;
            private const int WM_MOUSEWHEEL = 0x20a;
    
            public event dlgListBoxScroll Scroll;
            public delegate void dlgListBoxScroll(ListBox LB);
    
            public ListBoxScroll(ListBox LB)
            {
                this._LB = LB;
                this.AssignHandle(LB.Handle);
            }
    
            protected override void WndProc(ref Message m)
            {
                base.WndProc(ref m);
                switch (m.Msg)
                {
                    case WM_VSCROLL:
                    case WM_MOUSEWHEEL:                        
                        if (this.Scroll != null)
                        {
                            this.Scroll(_LB);
                        }
                        break;
                }
            }
    
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      将您的列表框类型更改为 SyncListBox 并附加到 OnVerticalScroll 事件。

          //Omitted for brevity
           private SyncListBox listBox1;
           private SyncListBox listBox2;
      
          //Omitted for brevity
      
           this.listBox1 = new WindowsFormsApplication1.SyncListBox();
           this.listBox2 = new WindowsFormsApplication1.SyncListBox();
      
          //Omitted for brevity
          listBox1.OnVerticalScroll += listBox1_OnVerticalScroll;
          listBox2.OnVerticalScroll += listBox2_OnVerticalScroll;
      
          //Event handlers
          void listBox2_OnVerticalScroll(object sender, ScrollEventArgs e)
          {
             listBox1.TopIndex = listBox2.TopIndex;
          }
      
          void listBox1_OnVerticalScroll(object sender, ScrollEventArgs e)
          {
             listBox2.TopIndex = listBox1.TopIndex;
          }
      

      【讨论】:

        猜你喜欢
        • 2021-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多