Панель не получает фокус
Я продолжаю программировать какую-то навигацию по клавиатуре в моей простой графической программе (используя С#). И я снова столкнулся с проблемой.
![alt text]()
Моя проблема в том, что я хочу обработать ввод с клавиатуры, чтобы перемещать слой вокруг. Перемещение слоя с помощью мыши уже работает достаточно хорошо, но элемент управления не получает фокуса (для этого элемента управления не задействованы ни кнопки KeyUp/KeyDown/KeyPress, ни GotFocus/LostFocus).
Поскольку мой класс происходит из Panel (и перезаписывает несколько событий), я также перезаписал события, упомянутые выше, но мне не удается добиться этих событий.
Думаю, мне удастся реализовать ответ клавиатуры, используя что-то вроде Keyboard.GetState() или ProcessCmdWnd или что-то в этом роде. Тем не менее: я все еще должен быть в состоянии сказать, когда управление получило фокус.
Есть ли более или менее элегантный способ добавить эту возможность к пользовательскому элементу управления (который основан на панели)?
Я проверил множество потоков здесь, и я мог бы использовать этот подход для ввода с клавиатуры. Однако проблема фокусировки остается.
Спасибо за информацию заранее!
Игорь.
p.s.: Я программирую на С#.NET v3.5, используя VS2008. Это приложение Windows.Forms, не WPF.
Ответы
Ответ 1
Класс 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);
}
}
}
Ответ 2
Тот же самый код Hans Passant в 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
Ответ 3
фокус вызова в событии click
private void Panel_Click(object sender, EventArgs e)
{
Panel.Focus();
}
Ответ 4
Чтобы получить фокус, проверьте событие MouseEnter в окне "Свойства".
Введите ниже код:
private void mainPanel_MouseEnter(object sender, EventArgs e)
{
mainPanel.Focus();
}
Ответ 5
Самый простой трюк, который я использую, когда по какой-либо причине я не могу использовать родительское свойство Form KeyPreview для того, чтобы сделать ключевые события с обработкой формы, заключается в том, чтобы помещать текстовое поле в
Панель:
Panel.Controls.Add(_focusTextBox = new TextBox() { Visible = true , Left = -300, TabIndex = 0});
И используйте его для захвата события KeyDown:
_focusTextBox.KeyDown += panel_KeyDown;
Последний шаг - установить фокус на этот TextBox, когда другие элементы управления на панели нажали:
_focusTextBox.Focus();
Ответ 6
Панели не фокусируются, вам нужно выбрать панель, если вы хотите отслеживать отпуск и вводить события
вызов panel1.Select()
в MouseClick
Событие