问题描述
我有一个基本的 WinForms 项目,用户可以在其中单击一个按钮。这将打开另一个表单,如下所示:
form2 myForm2 = new form2();
myForm2.ShowDialog();
在这个新表单中,有四个代表值的按钮。用户按 SPACE 键在按钮之间跳转,按 ENTER 键选择一个。当用户在按钮上按下 ENTER 时,我希望表单关闭。为此,我使用“this.Close()”。这对于除 ENTER 以外的每个键都非常有效。我正在使用visual studio,所以我插入了一个断点并跳过了代码。成功检测到 ENTER 键,我可以跳过代码“this.Close()”,但窗口永远不会关闭。我的代码如下:
private void button1_KeyDown(object sender,PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
// Change colour of the button you are on. This works fine.
}
else if (e.KeyCode == Keys.Enter)
{
this.Close();
// This will close the form with all keys other than the Enter key. Yet the enter key is
// successfully detected and the program enters this else if statement.
}
}
非常感谢任何帮助,谢谢。
解决方法
我会覆盖 ProcessCmdKey()
并使空格键的作用类似于 Tab 键以选择下一个控件。然后像平常一样处理每个按钮的点击事件。当用户按下 Enter 键时,按钮的点击处理程序将触发:
public partial class form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg,Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
// possibly do something else with "btn"?...
this.SelectNextControl(btn,true,true);
return true; // suppress default handling of space
}
}
return base.ProcessCmdKey(ref msg,keyData);
}
private void button1_Click(object sender,EventArgs e)
{
// possibly set some value?
Console.WriteLine("button1");
this.DialogResult = DialogResult.OK;
}
private void button2_Click(object sender,EventArgs e)
{
// possibly set some value?
Console.WriteLine("button2");
this.DialogResult = DialogResult.OK;
}
private void button3_Click(object sender,EventArgs e)
{
// possibly set some value?
Console.WriteLine("button3");
this.DialogResult = DialogResult.OK;
}
private void button4_Click(object sender,EventArgs e)
{
// possibly set some value?
Console.WriteLine("button4");
this.DialogResult = DialogResult.OK;
}
}
另一种方法是也将回车键困在 ProcessCmdKey()
中,如下所示:
public partial class Form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg,Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
Console.WriteLine("Space -> Tab");
// possibly do something else with "btn"?...
this.SelectNextControl(btn,true);
return true; // suppress default handling of space
}
else if (keyData == Keys.Enter)
{
Console.WriteLine("Enter in ProcessCmdKey() for " + btn.Name);
// possibly do something else with "btn"?...
this.Close();
// < or >
this.DialogResult = DialogResult.OK;
return true;
}
}
return base.ProcessCmdKey(ref msg,keyData);
}
}
,
查看处理程序 export default {
name: "JackHammer",data() {
return {
timer: null,}
},beforeDestroy() {
clearInterval(this.timer);
},mounted() {
var funcs = [
"load","addEventListener","daysLeft","getElementById","setInterval","getTime","getTimezoneOffset","floor","textContent",];
var daysLeft;
var frameNumber = 0;
var endDate = new Date(2021,1,20,10,0);
window.addEventListener(
"load",initJackhammer.bind(this),false
);
function initJackhammer() {
daysLeft = document.getElementById(funcs[2]);
ShowTimeLeft();
window.setInterval(ShowTimeLeft,1000);
var jackhammerTip = document.getElementById("jackhammerTip");
var jackhammer = document.getElementById("jackhammer");
var jackBody = document.getElementById("jackBody");
var jackArms = document.getElementById("jackArms");
this.timer = setInterval(animateJackhammer,40);
}
function ShowTimeLeft() {
// if (!document.getElementById("hoursLeft")) {
// return;
// }
var CurrTime = new Date();
var timeDiff = (endDate - CurrTime) / 1000;
var timeDiffInDays = Math.floor(timeDiff / 86400);
timeDiff -= timeDiffInDays * 86400;
var TimeDiffHours = Math.floor(timeDiff / 3600) % 24;
timeDiff -= TimeDiffHours * 3600;
var TimeDiffMinutes = Math.floor(timeDiff / 60) % 60;
timeDiff -= TimeDiffMinutes * 60;
var TimeDiffSeconds = Math.floor(timeDiff % 60);
daysLeft.textContent = timeDiffInDays;
hoursLeft.textContent = TimeDiffHours;
minutesLeft.textContent = TimeDiffMinutes;
secondsLeft.textContent = TimeDiffSeconds;
}
function animateJackhammer() {
// console.log(jackhammerTip)
if (!document.getElementById("jackhammerTip")) {
return;
}
frameNumber++;
jackhammerTip.setAttribute(
"transform","translate(0," + (frameNumber % 3) * -3 + ")"
);
jackhammer.setAttribute(
"transform"," + -Math.sin(frameNumber * 1.5) + ")"
);
var jackBodyAmount = Math.sin(frameNumber) + 2;
jackBody.setAttribute(
"transform"," + -jackBodyAmount + ")"
);
jackArms.setAttribute(
"transform"," + -jackBodyAmount + ")"
);
if (frameNumber == 1000) frameNumber = 0;
}
},};
的签名,显然 OP 已经在处理 (object sender,PreviewKeyDownEventArgs e)
事件。
我重现并解决了问题。
当您使用 PreviewKeyDown
或 Show
打开表单时,行为会有所不同。使用 ShowDialog
一切正常,但使用 Show
时,要关闭 ShowDialog
中的表单,您需要使用以下选项之一:
PreviewKeyDown
应该有一些关于模型消息循环的东西。我没有详细追踪,但您可能会发现以下链接很有用:
作为旁注:如果 Enter 应在表单级别处理,则设置表单的 private void button1_PreviewKeyDown(object sender,PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
this.Close();
// OR
// if (e.KeyData == Keys.Enter)
// this.BeginInvoke(new Action(() => this.Close()));
// OR first hide,then close,without calling BeginInvoke
// this.Hide();
// this.Close();
}
或覆盖 AcceptButton
或 ProcessKeyDown
形式是要走的路。