zwei ListViews synchron Scrollen



  • Hi,
    ich hab mir eine ListView abgeleitet:

    public class ListViewEx: ListView
      {
    
      public ListViewEx()
        : base()
      { 
       isScrolling = false; 
      }
      public ListViewEx LinkedListViewEx
        {
          get;
          set;
        }
      private static bool isScrolling;
        protected override void WndProc(ref Message m)
        {
          if (m.Msg == MyNativeMethods.WM_VSCROLL ||         
              m.Msg == MyNativeMethods.WM_MOUSEWHEEL)
          {
    
            if (!isScrolling && LinkedListViewEx != null)
            {
             isScrolling = true;
             MyNativeMethods.ScrollInfoStruct si = new
              MyNativeMethods.ScrollInfoStruct();
             si.fMask = MyNativeMethods.SIF_ALL;
             si.cbSize = Marshal.SizeOf(si);
             MyNativeMethods.GetScrollInfo(this.LinkedListViewEx.Handle, 0, ref si);
             int oldPos = si.nPos;
             Int16 hi = (Int16)((int)m.WParam >> 16);//position
             Int16 lo = (Int16)m.WParam;//scroll type
             if (lo == 5) //SB_THUMBTRACK
             {          
                si.nPos = hi;
                si.fMask = MyNativeMethods.SIF_POS;
                MyNativeMethods.SendMessage(this.LinkedListViewEx.Handle,         
                        MyNativeMethods.WM_VSCROLL, (IntPtr)(4 + 0x10000 * hi), 
                        IntPtr.Zero);            
                MyNativeMethods.SetScrollInfo(this.LinkedListViewEx.Handle,(int) 
                          System.Windows.Forms.Orientation.Vertical,ref si, true);
    
              }
              else
                MyNativeMethods.SendMessage(
                      LinkedListViewEx.Handle, m.Msg, m.WParam, m.LParam);
    
              Logging.ConsoleLogging.getSingelton().Info(m.Msg.ToString());
              isScrolling = false;
            }
          }    
    
          base.WndProc(ref m);
        }
      }
    

    Funktioniert alles soweit ganz gut, solange ich nur per MOUSEWHEEL oder Tastatur scrolle , wenn ich jedoch den Slider direkt mit der Maus anpasse bzw. verschiebe
    springt die 2 ListView wieder zurück bzw. scrollt gar nicht. Hat einer ne Idee?
    Gruss



  • Hm ehrlich gesagt ich hab keinen Plan warum das nicht aktualisiert..

    Naja ich hab mal nen Workaround programmiert, jedesmal wenn die Scrollbar gezogen wird wird statt "nur" die Message zu senden die Scrollbar der anderen Listview manuell verschoben.

    Deine ListView-Klasse:

    public class ListViewEx : ListView
        {
    
            public ListViewEx()
                : base()
            {
                this.SelectedIndexChanged += new EventHandler(ListViewEx_SelectedIndexChanged);
            }
    
            void ListViewEx_SelectedIndexChanged(object sender, EventArgs e) //Selektion auf die andere ListView übertragen (nur wenn die Anzahl der Items gleich ist), damit die KeyDown Messages die Listview scrollen
            {
                if (!stopUpdate)
                {
                    stopUpdate = true;
                    if (LinkedListViewEx != null && this.Items.Count == LinkedListViewEx.Items.Count)
                    {
                        for (int i = 0; i < this.Items.Count; i++)
                        {
                            LinkedListViewEx.Items[i].Selected = this.Items[i].Selected;
                        }
                    }
                    stopUpdate = false;
                }
            }
    
            public ListViewEx LinkedListViewEx
            {
                get;
                set;
            }
    
            private static bool stopUpdate;
    
            static bool inDrag = false;
            uint dragLastPos = 0;
    
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == MyNativeMethods.WM_VSCROLL || m.Msg == MyNativeMethods.WM_MOUSEWHEEL || (m.Msg == MyNativeMethods.KEYDOWN && (m.WParam == (IntPtr)0x26 || m.WParam == (IntPtr)0x28 || m.WParam == (IntPtr)0x21 || m.WParam == (IntPtr)0x22 || m.WParam == (IntPtr)0x24 || m.WParam == (IntPtr)0x23))) //up,down,pageUp,pageDown,home,end
                {
                    if (LinkedListViewEx != null && !stopUpdate)
                    {
                        stopUpdate = true;
                        if (m.Msg == MyNativeMethods.WM_VSCROLL)
                        {
                            base.WndProc(ref m);
    
                            uint hi = (((uint)m.WParam) >> 16) & 0xFFFF;
                            uint lo = ((uint)m.WParam) & 0xFFFF;
    
                            switch (lo)
                            {
                                case MyNativeMethods.SB_ENDSCROLL:
                                    inDrag = false;
                                    break;
                                case MyNativeMethods.SB_THUMBPOSITION:
                                    break;
                                case MyNativeMethods.SB_THUMBTRACK:
                                    if (inDrag)
                                    {
    
                                        while (hi != dragLastPos)
                                        {
                                            if (hi > dragLastPos)
                                            {
                                                MyNativeMethods.SendMessage(LinkedListViewEx.Handle, MyNativeMethods.WM_VSCROLL, (IntPtr)MyNativeMethods.SB_LINEDOWN, (IntPtr)0);
                                                dragLastPos++;
    
                                            }
                                            else
                                            {
                                                MyNativeMethods.SendMessage(LinkedListViewEx.Handle, MyNativeMethods.WM_VSCROLL, (IntPtr)MyNativeMethods.SB_LINEUP, (IntPtr)0);
                                                dragLastPos--;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        inDrag = true;
                                        dragLastPos = hi;
                                    }
    
                                    break;
                                default:
                                    MyNativeMethods.SendMessage(LinkedListViewEx.Handle, m.Msg, m.WParam, m.LParam);
                                    break;
                            }
    
                            stopUpdate = false;
                            return;
    
                        }
                        else
                        {
                            MyNativeMethods.SendMessage(LinkedListViewEx.Handle, m.Msg, m.WParam, m.LParam);
                            stopUpdate = false;
                        }
    
                    }
                }
    
                base.WndProc(ref m);
            }
        }
    

    Natives:

    class MyNativeMethods
        {
            public static int WM_VSCROLL = 0x115;
            public static int WM_MOUSEWHEEL = 0x020a;
    
            public const int KEYDOWN = 0x0100;
            public const int SB_VERT = 1;
            public const int SB_ENDSCROLL = 8;
            public const int SB_THUMBTRACK = 5;
    
            public const int SB_LINEUP = 0;
            public const int SB_LINEDOWN = 1;
            public const int SB_THUMBPOSITION = 4;
    
            public const int SB_PAGEUP = 2;
            public const int SB_PAGEDOWN = 3;
    
            [DllImport("user32")]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
        }
    

    Falls noch Fehler drin sind schreib mir das bitte, dann werde ich versuchen sie zu beheben.



  • Hi DarkShadow44,
    vielen Dank für deine Programmiereinsatz 🙂
    damit funktioniert es. Ich hatte mir gestern im Netz ein Ast gesucht
    und nichts brauchbares gefunden.

    Viele Grüße 👍


Anmelden zum Antworten