c# bürgerkrieg - Panel bekommt keinen Fokus





militärintervention kämpfer (6)


Der einfachste Trick, den ich verwende, wenn ich aus irgendeinem Grund die übergeordnete Form KeyPreview-Eigenschaft nicht verwenden kann, um das Formular Schlüsselereignisse zu machen, ist, eine Textbox zu setzen

Das Panel:

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

Und verwenden Sie es, um das KeyDown-Ereignis zu erfassen:

_focusTextBox.KeyDown += panel_KeyDown;

Der letzte Schritt besteht darin, den Fokus auf diese TextBox zu setzen, wenn andere Steuerelemente im Bedienfeld angeklickt wurden:

_focusTextBox.Focus();

Ich werde weiterhin eine Art Tastaturnavigation in meinem einfachen Grafikprogramm (mit C #) programmieren. Und ich geriet erneut in Schwierigkeiten.

Mein Problem ist, dass ich die Tastatureingabe verarbeiten möchte, um eine Ebene zu verschieben. Das Verschieben der Ebene mit der Maus funktioniert bereits ganz gut, aber das Steuerelement erhält den Fokus nicht ( weder KeyUp / KeyDown / KeyPress noch GotFocus / LostFocus wird für dieses Steuerelement ausgelöst ). Da meine Klasse von Panel abgeleitet ist (und ein paar Ereignisse überschreibt), habe ich auch die oben erwähnten Ereignisse überschrieben, aber ich kann diese Ereignisse nicht auslösen.

Ich denke, ich könnte es schaffen, die Tastaturantwort zu implementieren, indem ich etwas wie Keyboard.GetState () oder ProcessCmdWnd oder so etwas verwende. Allerdings: Ich muss noch sagen können, wann die Kontrolle den Fokus hat.

Gibt es eine mehr oder weniger elegante Möglichkeit, diese Fähigkeit einer Benutzersteuerung hinzuzufügen (die auf Panel basiert)?

Ich habe viele Threads hier überprüft und ich könnte diesen Ansatz für die Tastatureingabe verwenden. Das Fokusproblem bleibt jedoch bestehen.

Vielen Dank für Informationen im Voraus!

Igor.

ps: Ich programmiere in C # .NET v3.5 mit VS2008. Es ist eine Windows.Forms-Anwendung, nicht WPF .




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



Anruf Fokus in Klick-Ereignis

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



Die Panel-Klasse wurde als Container konzipiert. Sie vermeidet es, den Fokus zu verwenden, sodass ein untergeordnetes Steuerelement sie immer erhält. Sie benötigen eine Operation, um das zu beheben. Ich habe den Code eingefügt, um auch im KeyDown-Event Cursor-Keystrokes zu erhalten:

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



Der gleiche 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



Im Allgemeinen benutze ich, abhängig von den Codierungsstandards des Projekts, ein "_" oder "m" vor dem Namen für meine privaten Klassenattribute. (Wie unten)

private int mVariable;
private int _Variable;

Mit denen vor der Variable erkenne ich sofort, dass es sich um eine interne Variable für die Klasse handelt. Dann, wenn es um das Debuggen geht, kann ich selbst oder jemand anderes sofort erkennen, dass der Code sich mit einer internen privaten Variable beschäftigt und eine Anpassung vornimmt. Es kommt also auf Lesbarkeit für mich an.





c# winforms keyboard focus panel