小组没有得到关注

时间:2010-08-25 01:30:00

标签: c# winforms keyboard focus panel

我将继续在我的简单图形程序(使用C#)中编程某种键盘导航。我又一次陷入困境。

alt text

我的问题是我想处理键盘输入以移动图层。使用鼠标移动图层已经非常有效,但控件无法获得焦点(此控件未触发KeyUp / KeyDown / KeyPress和GotFocus / LostFocus )。 由于我的类派生自Panel(并覆盖了几个事件),我也覆盖了上面提到的事件,但我无法成功触发这些事件。

我想我可以设法使用Keyboard.GetState()或ProcessCmdWnd之类的东西来实现键盘响应。但是:我仍然需要知道控件何时得到关注。

是否有一种或多或少的优雅方式将此功能添加到用户控件(基于Panel)?

我在这里检查了很多线程,我可能会使用this approach进行键盘输入。然而,焦点问题仍然存在。

非常感谢您提前获取信息!

伊戈尔。

p.s。:我使用VS2008在C#.NET v3.5中编程。它是一个Windows.Forms应用程序,不是WPF

6 个答案:

答案 0 :(得分:57)

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

答案 1 :(得分:6)

VB.NET中的Hans Passant代码

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

答案 2 :(得分:0)

在点击事件中调用焦点

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

答案 3 :(得分:0)

要获得焦点,请在“属性”窗口中检查MouseEnter事件。

写下面的代码:

private void mainPanel_MouseEnter(object sender, EventArgs e)
{
    mainPanel.Focus();
}

答案 4 :(得分:0)

我出于任何原因使用的最简单的技巧,我不能使用父Form KeyPreview属性来使表单处理键事件,是将文本框放在

小组:

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

并使用它来捕获KeyDown事件:

_focusTextBox.KeyDown += panel_KeyDown;

最后一步是在单击面板上的其他控件时将焦点设置到此TextBox:

_focusTextBox.Focus();

答案 5 :(得分:-1)

面板无法获得焦点,如果您想跟踪请假并输入事件,则必须选择面板

panel1.Select()活动

中致电MouseClick