Ich programmiere weiterhin eine Art Tastaturnavigation in meinem einfachen Grafikprogramm (mit C #). Und ich hatte wieder einmal Ärger.
Mein Problem ist, dass ich die Tastatureingaben verarbeiten möchte, um eine Ebene zu verschieben. Das Verschieben der Ebene mit der Maus funktioniert bereits recht gut, jedoch erhält das Steuerelement nicht den Fokus ( weder KeyUp/KeyDown/KeyPress noch GotFocus/LostFocus wird für dieses Steuerelement ausgelöst ). Since Meine Klasse stammt von Panel (und überschreibt einige Ereignisse), ich habe auch die oben genannten Ereignisse überschrieben, aber es ist mir nicht möglich, diese Ereignisse auszulösen.
Ich denke, ich könnte es schaffen, die Tastaturantwort entweder mit Keyboard.GetState () oder ProcessCmdWnd oder so etwas zu implementieren. Allerdings: Ich muss immer noch erkennen können, wann das Steuerelement den Fokus hat.
Gibt es eine mehr oder weniger elegante Möglichkeit, diese Fähigkeit zu einem Benutzersteuerelement hinzuzufügen (das auf Panel basiert)?
Ich habe hier viele Threads eingecheckt, und ich könnte diesen Ansatz für die Tastatureingabe verwenden. Das Fokusproblem bleibt jedoch bestehen.
Vielen Dank für die Information im Voraus!
Igor.
p .: Ich programmiere in C # .NET v3.5 mit VS2008. Es ist eine Windows.Forms-Anwendung, nicht WPF .
Die Panel-Klasse wurde als Container entworfen. Sie vermeidet den Fokus, sodass ein untergeordnetes Steuerelement diesen immer erhält. Sie müssen operiert werden, um das zu beheben. Ich habe den Code hineingeworfen, um auch im KeyDown-Ereignis die Cursortasten zu markieren:
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);
}
}
}
Derselbe Hans Passant-Code in 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
Der einfachste Trick, den ich verwende, wenn ich aus irgendeinem Grund die übergeordnete Form KeyPreview-Eigenschaft nicht dazu verwenden kann, Formularereignisschlüsselereignisse auszuführen, ist das Einfügen eines Textfelds
Das Panel:
Panel.Controls.Add(_focusTextBox = new TextBox() { Visible = true , Left = -300, TabIndex = 0});
Und verwenden Sie es, um ein KeyDown-Ereignis zu erfassen:
_focusTextBox.KeyDown += panel_KeyDown;
Der letzte Schritt besteht darin, den Fokus auf dieses Textfeld zu setzen, wenn auf andere Steuerelemente im Bedienfeld geklickt wird:
_focusTextBox.Focus();
rufen Sie den Fokus im Klick-Ereignis auf
private void Panel_Click(object sender, EventArgs e)
{
Panel.Focus();
}
Um den Fokus zu erhalten, überprüfen Sie das MouseEnter-Ereignis im Eigenschaftenfenster.
Schreiben Sie den folgenden Code:
private void mainPanel_MouseEnter(object sender, EventArgs e)
{
mainPanel.Focus();
}