2010-06-09 4 views
8

Solange die Maus über ein bestimmtes Steuerelement ist, zeigen wir einige Form. Wenn die Maus das Steuerelement verlässt, wird das Steuerelement nach einer kurzen Zeitüberschreitung ausgeblendet. Dies ist das Standard-Hover-Verhalten..NET C# MouseEnter Listener auf einem Steuerelement mit Bildlaufleiste

Wenn jedoch eine Steuerung (zum Beispiel eines Treeview) eine Scrollbar und die Maus auf oder über den Scrollbar, die Ereignisse nicht ausgelöst ...

Wenn wir einen Verweis auf das bekommen könnten scrollbar control, das würde unser Problem lösen, da wir der Scrollbar dieselben Listener-Events hinzufügen würden. Allerdings ist die Bildlaufleiste nicht zugänglich, soweit ich weiß ...

Wie können wir dieses Problem lösen?

Antwort

3

Die Scrollbar ist in der Nicht-Client-Bereich der Baumansicht. Wenn sich die Maus dorthin bewegt, beginnt sie, Nicht-Client-Nachrichten wie WM_NCMOUSEMOVE und WM_NCMOUSELEAVE zu erzeugen. Sie müssten die TreeView sub-class und überschreiben WndProc(), um diese Nachricht zu erkennen.

Dies löst nicht wirklich Ihr Problem, aber Sie werden immer noch mit Rand Fällen schwer haben. Ein Low-Tech-Ansatz mit einem Timer funktioniert immer:

private Form frmPopup; 

    private void treeView1_MouseEnter(object sender, EventArgs e) { 
     timer1.Enabled = true; 
     if (frmPopup == null) { 
      frmPopup = new Form2(); 
      frmPopup.StartPosition = FormStartPosition.Manual; 
      frmPopup.Location = PointToScreen(new Point(treeView1.Right + 20, treeView1.Top)); 
      frmPopup.FormClosed += (o, ea) => frmPopup = null; 
      frmPopup.Show(); 
     } 
    } 

    private void timer1_Tick(object sender, EventArgs e) { 
     Rectangle rc = treeView1.RectangleToScreen(new Rectangle(0, 0, treeView1.Width, treeView1.Height)); 
     if (!rc.Contains(Control.MousePosition)) { 
      timer1.Enabled = false; 
      if (frmPopup != null) frmPopup.Close(); 
     } 
    } 
2

Ich denke, es gibt mehrere verschiedene Möglichkeiten, dies zu tun, aber der Schlüssel ist Ihr Wunsch, eine Zeitüberschreitung bei der Aktion zu haben. Ich denke, eine Kombination aus zwei Techniken könnte funktionieren:

Setzen Sie das Steuerelement auf ein Panel, angedockt, um zu füllen, und verwenden Sie den MouseEnter des Bedienfelds, um Ihr Verhalten zu aktivieren - das wird die Bildlaufleiste des Steuerelements enthalten. Sie können auch das MouseLeave-Ereignis des Bedienfelds verwenden. Sie müssen jedoch die Position des Cursors überprüfen, um sicherzustellen, dass er nicht in das enthaltene Steuerelement verschoben wurde. Diese Methode ist meist zuverlässig, aber wenn Sie die Maus schnell bewegen, kann das verwirren.

Wenn Sie dies mit einem Timer kombinieren, der startet, wenn Ihr angezeigtes/verdecktes Steuerelement angezeigt wird, und überprüfen Sie die Cursorposition in regelmäßigen Abständen. Dies funktioniert, aber Ihr Timeout vor dem Ausblenden des Steuerelements ist nicht unbedingt konsistent (weil der Zeitgeber beim Eingeben des Steuerelements gestartet wird). Sie können den Timer bei Mausbewegungen im Steuerelement stoppen/starten, um dies etwas zu verringern.

ich zusammen ein Projekt der verschiedenen Methoden, die ich hier versucht: http://lovethedot.s3.amazonaws.com/100609StackoverflowScrollbarQuestion.zip

Durch Andocken der Kontrolle, die Sie im Panel verfolgen wollen, ist es es im Wesentlichen umschließt, und Sie werden MouseEnter- am äußersten Rand des bekommen getrackten Kontrolle:

private void panel1_MouseEnter(object sender, EventArgs e) 
    { 
     this.Text = "in"; 
    } 

    private void panel1_MouseLeave(object sender, EventArgs e) 
    { 
     if (!new Rectangle(new Point(0, 0), panel1.Size).Contains(panel1.PointToClient(Control.MousePosition))) 
      this.Text = "out"; 
    } 

Sie Tracking-Eintrag in das Panel der Steuerung umgibt, und Ausfahrt aus diesem Panel sofern der Cursor nicht innerhalb der verfolgten Kontrolle.

Um ein besseres „leave“ Erfahrung zu bekommen, ist es mit einem Timer kombiniert, die überprüft, wo sich der Cursor auch ist:

 private void listBox3_MouseEnter(object sender, EventArgs e) 
    { 
     button1.Visible = true; 
     visibleTimer.Stop(); 
     visibleTimer.Start(); 
    } 

    void visibleTimer_Tick(object sender, EventArgs e) 
    { 
     if (!new Rectangle(new Point(0, 0), listBox3.Size).Contains(listBox3.PointToClient(Control.MousePosition))) 
     { 
      visibleTimer.Stop(); 
      button1.Visible = false; 
     } 
    } 
+0

Der Panel Container eine gute Idee war, aber das funktioniert nicht, weil die Ereignisse nicht zu übergeordneten Steuerungen sprudelt ar ..., dass das gleiche sein würde, wie das Hinzufügen das mouseenter -Ereignis für das ganze Formular. Das Timeout und Timer ist kein Problem, die funktionieren gut. Trotzdem danke!! –

Verwandte Themen