Panel not getting focus

36,654

Solution 1

The Panel class was designed as container, it avoids taking the focus so a child control will always get it. You'll need some surgery to fix that. I threw in the code to get cursor key strokes in the KeyDown event as well:

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

Solution 2

The code from Hans Passant translated to VB.NET

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

Public Class SelectablePanel
    Inherits Panel

    Public Sub New()
        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
Share:
36,654
Igor
Author by

Igor

Updated on October 05, 2020

Comments

  • Igor
    Igor over 3 years

    I am continuing to program some kind of keyboard navigation in my simple graphic program (using C#). And I ran into trouble once again.

    alt text

    My problem is that I want to process the keyboard input to move a layer around. Moving the layer with the mouse already works quite well, yet the control doesn't get the focus (neither KeyUp/KeyDown/KeyPress nor GotFocus/LostFocus is triggered for this control). Since my class derives from Panel (and overwrites a couple of events), I've also overwritten the events mentioned above, but I can't succeed in getting those events triggered.

    I think I could manage to implement keyboard response either using something like Keyboard.GetState() or ProcessCmdWnd or something. However: I still have to be able to tell when the control got the focus.

    Is there an more or less elegant way to add this ability to a user control (which is based on Panel)?

    I've checked many threads in here and I might use this approach for keyboard input. The focus problem however still remains.

    Thank you very much for information in advance!

    Igor.

    p.s.: I am programming in C# .NET v3.5, using VS2008. It's a Windows.Forms application, not WPF.