表单上的 KeyEvents 只能与 CTRL 结合使用
代码:
Private Sub KeyHandling(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Left
btnPrev.PerformClick()
Case Keys.Right
btnNext.PerformClick()
Case Keys.Up
btnFirst.PerformClick()
Case Keys.Down
btnLast.PerformClick()
End Select
End Sub
我的表单的 KeyPreview 属性已启用。
问题:
除非我按住控制键,否则此代码不会执行任何操作。谁能解释一下吗? :)
Code:
Private Sub KeyHandling(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Left
btnPrev.PerformClick()
Case Keys.Right
btnNext.PerformClick()
Case Keys.Up
btnFirst.PerformClick()
Case Keys.Down
btnLast.PerformClick()
End Select
End Sub
The KeyPreview property of my form is enabled.
Problem:
This code won't do anything, except when I hold the control key. Can anyone explain this? :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是因为光标键在 KeyDown 事件触发之前就被提前拦截。 Winforms使用它来移动焦点,就像Tab一样。当您按住 Ctrl 键时,它不再是导航键,您的 KeyDown 事件可以看到它。
通常,您可以通过重写 IsInputKey() 来解决此问题,但如果表单有任何控件,则该方法将不起作用。如果您将 KeyPreview 设置为 true,它们可能会这样做。窗体永远不会获得焦点,控件却能。您需要放弃 KeyPreview,无论如何,它都是旧的 VB6 不合时宜的内容,您可以通过重写 ProcessCmdKey() 来捕获光标键。像这样:
This is because the cursor keys get intercepted early, before the KeyDown event fires. Winforms uses it to move the focus, just like Tab. When you hold down the Ctrl key, it is no longer a navigating key and your KeyDown event can see it.
You'd normally fix that by overriding IsInputKey() but that won't work if the form has any controls. They probably do if you set KeyPreview to true. The form never gets the focus, the controls do. You need to give up on KeyPreview, it's an old VB6 anachronism anyway, you catch the cursor keys by overriding ProcessCmdKey(). Like this:
我假设您的表单上有按钮。当按钮具有焦点时,用户可以通过使用表单上按钮之间的箭头按钮进行导航来更改焦点。这就是为什么按下箭头键时按钮不会收到 KeyDown 事件的原因。
以下技巧将帮助您避免这种情况。对于表单上的每个按钮,将 PreviewKeyDown 事件设置为以下内容:
I assume you have Buttons on your form. When a button has the focus the user can change the focus by navigate with the arrow buttons between the buttons on the form. That is the reason why buttons don't receive the KeyDown event when an arrow key is pressed.
Following trick will help you to avoid this. For every button on your form set the PreviewKeyDown event to the following:
发生的情况是箭头键正在浏览表单上的控件,非常类似于 Tab 键。每次按箭头键都会将焦点从当前活动的控件移动到与该箭头键相同的相对方向的下一个控件。
箭头键的这种解释是在比您正在处理的表单的
KeyDown
事件更高的级别上实现的。每次按键实际上都被ProcessDialogKey
函数,它阻止该按键事件被传递到您的KeyHandling
方法进行任何进一步的处理。按住 Ctrl 键时一切按预期工作的原因是
ProcessDialogKey
函数不会消耗这些事件,从而允许它们传递到您的事件处理程序方法。该方法的文档告诉我们:如果您不希望箭头键在控件之间导航,而只想“单击”适当命名的按钮,那么解决方案应该是显而易见的:您需要重写
ProcessDialogKey
方法,添加您的自定义密钥处理逻辑,并返回值“True”以指示您自己处理了密钥。否则,您将继续调用基类,以免破坏 Tab 和 Enter 等内容的标准处理。同样,文档非常清晰这里:只需将以下代码添加到您的表单中,然后删除您现在拥有的
KeyHandling
方法:What's happening is that the arrow keys are navigating the controls on the form, much like the Tab key. Each press of an arrow key is moving the focus from the currently active control to the next control in the same relative direction as that arrow key.
This interpretation of arrow keys is implemented at a higher level than the form's
KeyDown
event that you're handling. Each key press is actually being consumed by theProcessDialogKey
function, which is preventing that key event from ever being passed down to yourKeyHandling
method for any further processing.The reason that everything works as you expect when the Ctrl key is held down is that the
ProcessDialogKey
function doesn't consume those events, allowing them to be passed on to your event handler method. The method's documentation tells us:If you don't want the arrow keys to navigate between your controls and only to "click" the aptly-named buttons, the solution should be obvious: You need to override the
ProcessDialogKey
method, add your custom key handling logic, and return a value of "True" to indicate that you processed the key yourself. Otherwise, you'll go ahead and call through to the base class so as not to disrupt the standard handling of things like Tab and Enter. Again, the documentation is refreshingly clear here:Simply add the following code to your form, and remove the
KeyHandling
method you have now:您需要提供更多信息。
对于初学者来说,您正在处理哪个表单事件。您显示具有非标准处理程序名称的处理程序,但不显示它与哪个事件关联。您如何将其与事件关联起来?
在表单设计器中,查看“属性”窗口中的“事件”选项卡。 KeyDown 或 KeyPress 下有什么东西吗?这就是它需要的地方。
其次,它是否没有执行任何操作,因为您没有将其连接到形成键盘事件,或者因为它运行但没有执行您想要的操作?设置断点。代码会被调用吗?
根据上述问题的答案,您可能需要在处理 KeyDown 或 KeyPress 事件之间切换,具体取决于您要检测的字符。
You need to provide a lot more information.
For starters, which form event are you handling. You show a handler with a non-standard handler name, but you don't show which event it is associated with. How are you associating it with an event?
In the form designer, look at the events tab in the Properties window. Do you have anything under KeyDown or KeyPress? That's where it needs to be.
Second, is it not doing anything because you don't have it hooked up to form keyboard events or because it runs but just doesn't do what you want? Set a breakpoint. Does the code ever get called?
Depending on the answer to the questions above, you may need to switch between handling the KeyDown or KeyPress event, depending on which characters you are trying to detect.