[英]C# focus in forms and arrow keys
我想为游戏做一个地图编辑器。 它是一个具有Windows Forms UI(例如,propertyGrid可以编辑对象的属性)的程序,但是它也具有一个在其上绘制地图的面板。
我想要的是:
当焦点位于带有地图的面板上时,我想使用键盘来移动地图(箭头键),添加对象(数字键)等。当焦点不在此面板上时,我希望按钮可以用作在Windows窗体中正常-允许在控件之间制表符等
我的表格如下所示:
它具有一个ToolStripControl,它具有一个menuStrip(用于主菜单)和一个statusStrip(用于状态栏)。 在表单(或toolstripcontrol)的中间,将SplitControl停靠在其中(具有两个面板)(dock = fill)。 面板1具有PanelMap-一个显示地图的面板,面板2具有所有其他内容,例如propertygrid,tabcontrol,按钮等。
我将窗体的KeyPreview设置为true,并在窗体的keydown事件处理程序中处理键盘事件。
现在,发生的事情是,如果我将焦点分配给PanelMap,则下次按下箭头键时,将不会触发KeyDown事件。 没有一个! 偶数形式应该处理所有事件,因为它具有“ KeyPreview”,它甚至不会触发。 当我按箭头时,PanelMap失去对SplitControl的关注。
好的,我想,也许PanelMap不应该具有焦点,让我们将焦点赋予SplitControl(如果我在有焦点的情况下按箭头键,则可以处理它,因此它不会继续前进)。 但是,如果在SplitControl内部的某个文本框之类的东西具有焦点,则SplitControl无法获得焦点。 .Focus()不会执行任何操作-焦点仍然保留在拥有该控件的控件中!
为什么行为如此奇怪? 当面板具有焦点并按下箭头键时,为什么Form的KeyDown不会触发? 为什么即使CanFocus = true,当我调用.Focus()时,SplitControl也不会集中精力?
最终,我如何实现自己想要的? 有办法吗?
我认为在事件到达导航之前,您正在碰击小部件进行击键。 我遇到了这个问题,并这样做:
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;
告诉外界您已使用此事件,并且不希望它在其他任何地方使用。
现在,您可以在击键之前看到它们,并且不会从光标键之间进行导航。
我找到了这样的答案:
我制作了一个隐藏在面板下的文本框(但已启用且可见)。 当我想“锁定” PanelMap的焦点时,将给该文本框以焦点。 即使使用e.suppress = true,它也具有onkeydown,因此文本框永远不会受到任何击键来影响它。
粗略的解决方法,但可以解决问题...典型的M $业务...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.