Панель не фокусируется - PullRequest
       39

Панель не фокусируется

26 голосов
/ 25 августа 2010

Я продолжаю программировать какую-то навигацию с помощью клавиатуры в моей простой графической программе (используя C #). И я снова столкнулся с неприятностями.

alt text

Моя проблема в том, что я хочу обработать ввод с клавиатуры, чтобы переместить слой. Перемещение слоя с помощью мыши уже работает достаточно хорошо, но элемент управления не получает фокус ( для этого элемента управления не запускается ни KeyUp / KeyDown / KeyPress, ни GotFocus / LostFocus ). Так как мой класс происходит от Panel (и переписывает несколько событий), я также перезаписал события, упомянутые выше, но мне не удается добиться запуска этих событий.

Я думаю, что мне удалось бы реализовать реакцию клавиатуры, используя что-то вроде Keyboard.GetState () или ProcessCmdWnd или что-то еще. Тем не менее: я все еще должен быть в состоянии сказать, когда элемент управления получил фокус.

Есть ли более или менее элегантный способ добавить эту возможность в пользовательский элемент управления (основанный на Panel)?

Я проверил много потоков здесь и мог бы использовать этот подход для ввода с клавиатуры. Однако проблема с фокусировкой остается.

Большое спасибо за информацию заранее!

Игорь.

p.s .: Я программирую на C # .NET v3.5, используя VS2008. Это приложение Windows.Forms, не WPF .

Ответы [ 6 ]

57 голосов
/ 25 августа 2010

Класс Panel был спроектирован как контейнер, он не требует фокусировки, поэтому дочерний элемент управления всегда получает его. Вам понадобится операция, чтобы это исправить. Я добавил код, чтобы получить нажатия клавиш курсора в событии KeyDown:

using System;
using System.Drawing;
using System.Windows.Forms;

class SelectablePanel : Panel {
    public SelectablePanel() {
        this.SetStyle(ControlStyles.Selectable, true);
        this.TabStop = true;
    }
    protected override void OnMouseDown(MouseEventArgs e) {
        this.Focus();
        base.OnMouseDown(e);
    }
    protected override bool IsInputKey(Keys keyData) {
        if (keyData == Keys.Up || keyData == Keys.Down) return true;
        if (keyData == Keys.Left || keyData == Keys.Right) return true;
        return base.IsInputKey(keyData);
    }
    protected override void OnEnter(EventArgs e) {
        this.Invalidate();
        base.OnEnter(e);
    }
    protected override void OnLeave(EventArgs e) {
        this.Invalidate();
        base.OnLeave(e);
    }
    protected override void OnPaint(PaintEventArgs pe) {
        base.OnPaint(pe);
        if (this.Focused) {
            var rc = this.ClientRectangle;
            rc.Inflate(-2, -2);
            ControlPaint.DrawFocusRectangle(pe.Graphics, rc);
        }
    }
}
6 голосов
/ 20 июля 2012

Тот же код Ганса Пассанта в VB.NET

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Public Class SelectablePanel
    Inherits Panel

    Public Sub SelectablePanel()
        Me.SetStyle(ControlStyles.Selectable, True)
        Me.TabStop = True
    End Sub

    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
        Me.Focus()
        MyBase.OnMouseDown(e)
    End Sub

    Protected Overrides Function IsInputKey(ByVal keydata As Keys) As Boolean
        If (keydata = Keys.Up OrElse keydata = Keys.Down) Then Return True
        If (keydata = Keys.Left OrElse keydata = Keys.Right) Then Return True
        Return MyBase.IsInputKey(keydata)
    End Function

    Protected Overrides Sub OnEnter(ByVal e As EventArgs)
        Me.Invalidate()
        MyBase.OnEnter(e)
    End Sub

    Protected Overrides Sub OnLeave(ByVal e As EventArgs)
        Me.Invalidate()
        MyBase.OnLeave(e)
    End Sub

    Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
        MyBase.OnPaint(pe)
        If (Me.Focused) Then
            Dim rc As Rectangle = Me.ClientRectangle
            rc.Inflate(-2, -2)
            ControlPaint.DrawFocusRectangle(pe.Graphics, rc)
        End If
    End Sub

End Class
0 голосов
/ 22 июня 2017

Самый простой трюк, который я использую, когда по какой-либо причине я не могу использовать родительское свойство Form KeyPreview, чтобы заставить форму обрабатывать ключевые события, - это поместить текстовое поле на

Панель:

Panel.Controls.Add(_focusTextBox = new TextBox() { Visible = true , Left = -300, TabIndex = 0});   

И используйте его для захвата события KeyDown:

_focusTextBox.KeyDown += panel_KeyDown;

Последний шаг - установить фокус на этот текстовый блок, когда другие элементы управления на панели нажимаются:

_focusTextBox.Focus();
0 голосов
/ 16 декабря 2015

Чтобы получить фокус, проверьте наличие события MouseEnter в окне свойств.

Введите следующий код:

private void mainPanel_MouseEnter(object sender, EventArgs e)
{
    mainPanel.Focus();
}
0 голосов
/ 14 октября 2015

Панели не получают фокус, вам нужно выбрать панель, если вы хотите отслеживать отпуск и вводить события

вызов panel1.Select() в MouseClick Событие

0 голосов
/ 12 мая 2014

фокусировка вызова в событии клика

private void Panel_Click(object sender, EventArgs e)
    {
        Panel.Focus();
    }
...