C#聚焦于表单和箭头键

时间:2012-03-29 20:21:36

标签: c# windows forms controls

我想为游戏做一个地图编辑器。它是一个具有Windows窗体UI的程序(如propertyGrid来编辑对象的属性),但它也有一个面板,将在其上绘制地图。

我想要的是什么:

当焦点在带有地图的面板上时,我想使用键盘移动地图(箭头键),添加对象(数字键)等。当焦点不在此面板上时,我想要按钮在Windows窗体中正常工作 - 允许在控件之间进行选项卡等。

我的表单如下:

它有一个ToolStripControl,它有一个menuStrip(用于主菜单)和一个statusStrip(用于状态栏)。在窗体(或toolstripcontrol)的中间,SplitControl停靠(dock = fill),它有两个面板。 Panel 1有PanelMap - 一个显示地图的Panel,Panel 2有所有其他东西,如propertygrid,tabcontrols,button等。

我将表单的KeyPreview设置为true,并在表单的keydown事件处理程序中处理键盘事件。

现在,如果我将焦点分配给PanelMap,下次按箭头键时,会触发NO KeyDown事件。不是一个人!即使是应该处理所有事件的形式,因为它具有“KeyPreview”也不会触发它。当我按箭头时,PanelMap失去了对SplitControl的关注。

好吧,我想,也许PanelMap不应该有焦点,让我们把焦点放在SplitControl上(如果我在有焦点时按箭头键,我可以处理它,所以它不会进一步)。但是,如果像SplitControl内部的文本框之类的内容有焦点,那么SplitControl就无法获得焦点。 .Focus()什么都不做 - 焦点仍然存在于拥有它的控制器中!

为什么这么奇怪?当面板具有焦点并按下箭头键时,为什么Form的KeyDown不会触发?当我调用.Focus()时,为什么SplitControl没有聚焦,即使CanFocus = true?

最终,我如何实现我想要的?有办法吗?

2 个答案:

答案 0 :(得分:1)

我认为在你的活动到达他们导航之前,你正在遇到按键的小部件。我有这个问题,并且这样做了:

    private void RemoveCursorNavigation(Control.ControlCollection controls)
    {
        foreach(Control ctrl in controls)
        {
            ctrl.PreviewKeyDown += new PreviewKeyDownEventHandler(MainWin_PreviewKeyDown);
            RemoveCursorNavigation(ctrl.Controls);
        }
    }

我在主窗体的Load处理程序中调用此函数,如下所示:

RemoveCursorNavigation(this.Controls);

在PreviewKeyDown处理程序中,您需要执行以下操作:

    public void MainWin_PreviewKeyDown(Object sender, PreviewKeyDownEventArgs e)
    {
        switch(e.KeyCode)
        {
            case Keys.Up:
            case Keys.Down:
            case Keys.Left:
            case Keys.Right:
                e.IsInputKey = true;
                break;
            default:
                break;
        }
    }

e.IsInputKey = true;告诉外面你已经使用过这个事件,并且不希望它去其他任何地方。

现在,您可以在转到小部件之前看到按键,并且您无法通过光标键在它们之间进行导航。

答案 1 :(得分:0)

我找到了这样的答案:

我创建了一个隐藏在面板下面的文本框(但已启用且可见)。当我想要将焦点“锁定”在我的PanelMap上时,此文本框将获得焦点。即使使用e.suppress = true,它仍然存在onkeydown,因此文本框永远不会受到影响它的任何击键。

原油解决方案,但有奇迹......典型的M $业务......