2008-09-25 5 views
7

Wir möchten das Standardverhalten von DataGridView überschreiben, wenn Sie ein Mausrad mit diesem Steuerelement verwenden. Standardmäßig scrollt die DataGridView eine Reihe von Zeilen, die der SystemInformation.MouseWheelScrollLines-Einstellung entsprechen. Was wir gerne tun würden, ist jeweils nur ein Element zu scrollen.Wie können Sie ein DataGridView mit dem Mausrad um ein Element blättern lassen?

(Wir zeigen Bilder in der DataGridView, die etwas groß sind. Aufgrund dieses Scrollens drei Zeilen (eine typische Systemeinstellung) ist zu viel, oft den Benutzer zu Elementen, die sie nicht sehen können scrollen.)

Ich habe schon ein paar Dinge ausprobiert und bisher nicht viel Erfolg gehabt. Hier sind einige Fragen, die ich in laufen haben:

  1. Sie Mousewheel Ereignisse abonnieren können, aber es gibt keine Möglichkeit, das Ereignis zu markieren, wie behandelt und mein eigenes Ding machen.

  2. Sie können OnMouseWheel überschreiben, aber dies scheint nie aufgerufen zu werden.

  3. Sie können dies möglicherweise im Basis-Scroll-Code korrigieren, aber es klingt wie ein schmutziger Job, da andere Arten des Scrollens (z. B. über die Tastatur) durch die gleiche Pipeline gehen.

Wer hat einen guten Vorschlag?

Hier ist der endgültige Code, da die wunderbare Antwort mit:

/// <summary> 
    /// Handle the mouse wheel manually due to the fact that we display 
    /// images, which don't work well when you scroll by more than one 
    /// item at a time. 
    /// </summary> 
    /// 
    /// <param name="sender"> 
    /// sender 
    /// </param> 
    /// <param name="e"> 
    /// the mouse event 
    /// </param> 
    private void mImageDataGrid_MouseWheel(object sender, MouseEventArgs e) 
    { 
     // Hack alert! Through reflection, we know that the passed 
     // in event argument is actually a handled mouse event argument, 
     // allowing us to handle this event ourselves. 
     // See http://tinyurl.com/54o7lc for more info. 
     HandledMouseEventArgs handledE = (HandledMouseEventArgs) e; 
     handledE.Handled = true; 

     // Do the scrolling manually. Move just one row at a time. 
     int rowIndex = mImageDataGrid.FirstDisplayedScrollingRowIndex; 
     mImageDataGrid.FirstDisplayedScrollingRowIndex = 
      e.Delta < 0 ? 
       Math.Min(rowIndex + 1, mImageDataGrid.RowCount - 1): 
       Math.Max(rowIndex - 1, 0); 
    } 

Antwort

4

Ich habe gerade ein wenig schlingern und testen von mir selbst. Ich habe Reflector verwendet, um einige Dinge zu untersuchen und zu entdecken. Das MouseWheel Ereignis stellt einen MouseEventArgs Parameter bereit, aber der OnMouseWheel() Override in DataGridView wirft es auf HandledMouseEventArgs. Dies funktioniert auch bei der Behandlung des Ereignisses MouseWheel. OnMouseWheel() wird tatsächlich aufgerufen, und es ist in DataGridView 's überschreiben, dass es SystemInformation.MouseWheelScrollLines verwendet.

So:

  1. Sie könnte in der Tat die MouseWheel Ereignis behandeln, MouseEventArgs-HandledMouseEventArgs Gießen und setzen Handled = true, dann tun, was Sie wollen.

  2. Subclass DataGridView, außer Kraft setzen OnMouseWheel() selbst, und versuchen, den gesamten Code erstellen ich in Reflector hier lesen Ausnahme SystemInformation.MouseWheelScrollLines mit 1 ersetzen.

Letzteres wäre ein großer Schmerz sein, weil es eine Reihe von privaten Variablen (einschließlich Verweise auf den ScrollBar s) verwendet und man müßte einige mit Ihrer eigenen ersetzen und erhalten/set andere Spiegelung verwenden.

1

ich das Datagridview in meine eigene benutzerdefinierte Steuerunterklasse würde (Sie wissen, fügen Sie eine neue Windows Forms -> Custom Control Datei und ändern Sie die Basisklasse von Control zu DataGridView).

public partial class MyDataGridView : DataGridView 

außer Kraft setzen Sie dann die WndProc Methode und Ersatz etwas wie so:

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == 0x20a) 
    { 
     int wheelDelta = ((int)m.WParam) >> 16; 

     // 120 = UP 1 tick 
     // -120 = DOWN 1 tick 

     this.FirstDisplayedScrollingRowIndex -= (wheelDelta/120); 
    } 
    else 
    { 
     base.WndProc(ref m); 
    } 
} 

Natürlich, werden Sie die Kontrolle haben, dass Sie außerhalb des Bereichs von FirstDisplayedScrollingRowIndex auf eine Zahl gesetzt nicht Ihre Gitter usw. Aber das funktioniert ganz gut!

Richard

+0

Dank. Ich denke, das würde funktionieren, auch wenn die Antwort, die ich wählte, einfacher war. –

1

Zwingende OnMouseWheel und nicht telefonieren base.OnMouseWheel sollte funktionieren. Einige Radmäuse verfügen über spezielle Einstellungen, die Sie möglicherweise selbst einstellen müssen, damit sie ordnungsgemäß funktioniert. Sieh diesen Beitrag http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=126295&SiteID=1

+0

Ich habe das erwähnt, aber ich habe etwas falsch gemacht. Ich denke, das würde funktionieren (vorausgesetzt, jemand hat es richtig gemacht!). –

1

UPDATE: Da ich jetzt habe gelernt, dass die DataGridView hat ein MouseWheel Ereignis, ich habe eine zweite, einfachere Überschreibung hinzugefügt.

Eine Möglichkeit, dies zu erreichen, besteht darin, die DataGridView Unterklasse zu bilden und die WndProc zu überschreiben, um eine spezielle Behandlung der Nachricht WM_MOUSEWHEEL hinzuzufügen.

Dieses Beispiel fängt die Mausrad Bewegung und ersetzt sie durch einen Aufruf SendKeys.Send.

(Dies ist ein wenig anders als nur Scrollen, da sie auch die nächste/vorherige Zeile der DataGridView wählen. Aber es funktioniert.)

public class MyDataGridView : DataGridView 
{ 
    private const uint WM_MOUSEWHEEL = 0x20a; 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == WM_MOUSEWHEEL) 
     { 
      var wheelDelta = ((int)m.WParam) >> 16; 

      if (wheelDelta < 0) 
      { 
       SendKeys.Send("{DOWN}"); 
      } 

      if (wheelDelta > 0) 
      { 
       SendKeys.Send("{UP}"); 
      } 

      return; 
     } 

     base.WndProc(ref m); 
    } 
} 

2. nehmen (mit den gleichen Einschränkungen wie erwähnt oben):

public class MyDataGridView : DataGridView 
{ 
    protected override void OnMouseWheel(MouseEventArgs e) 
    { 
     if (e.Delta < 0) 
      SendKeys.Send("{DOWN}"); 
     else 
      SendKeys.Send("{UP}"); 
    } 
} 
Verwandte Themen