Прослушиватель .NET C # MouseEnter для элемента управления WITH Scrollbar - PullRequest
8 голосов
/ 09 июня 2010

Пока мышь находится над определенным элементом управления, мы показываем некоторую форму.Когда мышь покидает элемент управления, мы скрываем его после небольшого времени ожидания.Это стандартное поведение при наведении.

Однако, когда элемент управления (например, Treeview) имеет полосу прокрутки, а мышь включена или находится над полосой прокрутки, события не запускаются ...

Если бы мы могли получить ссылку на элемент управления полосы прокрутки, это решило бы нашу проблему, поскольку мы добавили бы те же события прослушивателя на полосу прокрутки.Однако полоса прокрутки не доступна, насколько я знаю ...

Как мы можем решить эту проблему?

Ответы [ 2 ]

3 голосов
/ 09 июня 2010

Полоса прокрутки находится в не-клиентской области дерева.Когда мышь перемещается туда, она начинает генерировать не клиентские сообщения, такие как WM_NCMOUSEMOVE и WM_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 голосов
/ 09 июня 2010

Я думаю, что есть несколько разных способов сделать это, но ключом является ваше желание иметь тайм-аут на действии. Я думаю, что сочетание двух методов может работать:

Поместите элемент управления на панель, закрепите, чтобы заполнить, и используйте MouseEnter на панели, чтобы включить ваше поведение - это будет включать полосу прокрутки элемента управления. Вы также можете использовать событие MouseLeave панели, но вам нужно будет проверить положение курсора, чтобы убедиться, что он не переместился в содержащийся элемент управления. Этот метод в основном надежен, но быстрое перемещение мыши может запутать его.

Если вы объедините это с таймером, который запускается, когда отображается показанный / скрытый элемент управления, и периодически проверяйте положение курсора. Это будет работать, но ваш тайм-аут перед сокрытием элемента управления не обязательно будет согласованным (потому что таймер запускается, когда они входят в элемент управления). Вы можете остановить / запустить таймер при перемещении мыши в элементе управления, чтобы несколько смягчить это.

Я собрал проект различных методов, которые я попробовал здесь: http://lovethedot.s3.amazonaws.com/100609StackoverflowScrollbarQuestion.zip

Закрепив элемент управления, который вы хотите отслеживать на панели, он по сути оборачивает его, и вы получите MouseEnter на самом краю отслеживаемого элемента управления:

    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;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...