代码之家  ›  专栏  ›  技术社区  ›  Run CMD

带有滚动条的控件上的.NET C#MouseEnter侦听器

  •  8
  • Run CMD  · 技术社区  · 15 年前

    但是,当控件(例如Treeview)有一个滚动条,并且鼠标在滚动条上或上方时,事件不会触发。。。

    如果我们可以获得对scrollbar控件的引用,这将解决我们的问题,因为我们将向scrollbar添加相同的侦听器事件。然而,据我所知滚动条是不可访问的。。。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Hans Passant    15 年前

    滚动条位于树视图的非客户端区域。当鼠标移动到那里时,它开始生成非客户端消息,如WM\u NCMOUSEMOVE和WM\u NCMOUSELEAVE。您必须对TreeView进行子类化,并重写WndProc()以检测这些消息。

    不过,这并不能真正解决您的问题,您仍然很难处理边缘案例。带计时器的低技术方法始终有效:

        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
  •  2
  •   Ragoczy    15 年前

    我认为有几种不同的方法可以做到这一点,但关键是你希望有一个暂停的行动。我认为结合两种技术可能会奏效:

    将控件放在面板上,停靠以填充,然后使用面板的鼠标指针打开您的行为—这将包括控件的滚动条。您也可以使用面板的MouseLeave事件,但是您必须检查光标的位置,以确保它没有移动到包含的控件中。这种方法基本上是可靠的,但快速移动鼠标可能会混淆它。

    如果将此功能与显示/隐藏控件时启动的计时器结合使用,并定期检查光标位置。这可以工作,但是隐藏控件之前的超时不一定是一致的(因为计时器在它们进入控件时启动)。您可以在控件中的鼠标移动上停止/启动计时器来减轻这种情况。

    http://lovethedot.s3.amazonaws.com/100609StackoverflowScrollbarQuestion.zip

        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";
        }
    

    您正在跟踪进入控件周围面板的入口,如果光标不在跟踪的控件内,则从该面板退出。

    为了获得更好的“离开”体验,它还结合了一个计时器来检查光标的位置:

            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;
            }
        }