Wie können Sie eine Datagridview Scroll ein Element zu einem Zeitpunkt machen mit dem Mausrad?

StackOverflow https://stackoverflow.com/questions/135105

  •  02-07-2019
  •  | 
  •  

Frage

Wir möchten Datagridview Standardverhalten außer Kraft zu setzen, wenn ein Mausrad mit dieser Steuerung. Standardmäßig entspricht die Datagridview scrollt eine Anzahl von Zeilen der SystemInformation.MouseWheelScrollLines Einstellung. Was wir möchten, dass tun, scroll nur ein Element zu einem Zeitpunkt.

(Wir zeigen Bilder in der Datagridview, die etwas groß ist. Aufgrund dieser Scroll drei Reihen (eine typische Systemeinstellung) ist zu viel, oft den Benutzer verursacht, um Elemente zu blättern sie nicht einmal sehen können.)

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

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

  2. Sie können OnMouseWheel außer Kraft setzen, aber dies scheint nicht aufgerufen werden.

  3. Sie könnten in der Lage sein, diese Scroll-Code in der Basis zu korrigieren, aber es klingt wie eine schmutzige Arbeit, da andere Arten von Scrollen (z.B. die Tastatur) kommt durch die gleiche Pipeline.

Wer einen guten Vorschlag?

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

    /// <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);
    }
War es hilfreich?

Lösung

Ich habe gerade ein wenig schnorren und Prüfung von meinem eigenen. Ich benutzte Reflector zu untersuchen und ein paar Dinge entdeckt. Das MouseWheel Ereignis stellt einen MouseEventArgs Parameter, aber die OnMouseWheel() Überschreibung in DataGridView wirft es auf Handled MouseEventArgs. Dies funktioniert auch, wenn die MouseWheel Event-Handling. OnMouseWheel() in der Tat aufgerufen, und es ist in Überschreibung DataGridView ist, dass es SystemInformation.MouseWheelScrollLines verwendet.

So:

  1. Sie in der Tat das MouseWheel Ereignis umgehen können, MouseEventArgs Gießen HandledMouseEventArgs und setzt Handled = true, dann tun, was Sie wollen.

  2. Subclass DataGridView gekröpft OnMouseWheel() selbst, und versuchen, den gesamten Code erstellen Ich lese hier in Reflector Ausnahme SystemInformation.MouseWheelScrollLines mit 1 ersetzt werden.

Letzteres wäre ein großer Schmerz sein, weil es eine Reihe von privaten Variablen verwendet (einschließlich Verweise auf den ScrollBars) und Sie würden einige mit Ihrem eigenen haben ersetzen und erhalten / set andere Reflexion verwendet wird.

Andere Tipps

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

.
public partial class MyDataGridView : DataGridView

Dann überschreiben Sie die WndProc Methode und Ersatz etwas wie folgt:

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 nicht setzen FirstDisplayedScrollingRowIndex auf eine Zahl außerhalb des Bereichs des Rasters etc. Aber das funktioniert ganz gut!

Richard

Übergeordnete OnMouseWheel und nicht Aufruf base.OnMouseWheel funktionieren soll. Einige Rad Mäuse haben spezielle Einstellungen, die Sie benötigen, sich zu setzen, damit sie richtig arbeiten. Sehen Sie diesen Beitrag http://forums.microsoft.com/MSDN/ShowPost aspx? PostID = 126295 & SiteID = 1

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

.

Eine Möglichkeit, dies zu erreichen, ist die DataGridView Unterklasse und die WndProc außer Kraft setzt spezielle Handhabung der WM_MOUSEWHEEL Nachricht hinzuzufügen.

In diesem 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 des DataGridView wählt. 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 oben erwähnt):

public class MyDataGridView : DataGridView
{
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        if (e.Delta < 0)
            SendKeys.Send("{DOWN}");
        else
            SendKeys.Send("{UP}");
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top