在winform上放了20个动态textbox(其中有部分enabled=false),然后加上按键事件,期望可以通过上下左右切换当前textbox的焦点,遇到的问题是左右下都没有问题,但是按UP键就是会回到最上方的一格去。求助是什么原因,code如下:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
TextBox textBox = new TextBox();
textBox.AutoSize = false;
textBox.Width = 80;
textBox.Height = 20;
textBox.TabIndex = 0;
textBox.TabStop = false;
if (i % 2 == 0)
{
textBox.Enabled = false;
}
textBox.Name = "textBox1_" + (i + 1).ToString() + "_";
textBox.KeyDown += new KeyEventHandler(textBox1_KeyDown);
textBox.Location = new Point(100, 30 + i * 30);
Controls.Add(textBox);
}
for (int i = 0; i < 10; i++)
{
TextBox textBox = new TextBox();
textBox.AutoSize = false;
textBox.Width = 80;
textBox.Height = 20;
textBox.TabIndex = 0;
textBox.TabStop = false;
if (i % 2 == 0)
{
textBox.Enabled = false;
}
textBox.Name = "textBox2_" + (i + 1).ToString() + "_";
textBox.KeyDown += new KeyEventHandler(textBox2_KeyDown);
textBox.Location = new Point(300, 30 + i * 30);
Controls.Add(textBox);
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
if (c.Name == "textBox2_" + number + "_")
{
c.Select();
}
}
}
if (e.KeyCode == Keys.Down)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
for (int i = int.Parse(number) + 1; i <= 10; i++)
{
if (c.Name == "textBox1_" + i.ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
}
}
}
}
if (e.KeyCode == Keys.Up)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
for (int i = int.Parse(number) - 1; i >= 1; i--)
{
if (c.Name == "textBox1_" + i.ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
}
}
}
}
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
if (c.Name == "textBox1_" + number + "_")
{
c.Select();
}
}
}
if (e.KeyCode == Keys.Down)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
for (int i = int.Parse(number) + 1; i <= 10; i++)
{
if (c.Name == "textBox2_" + i.ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
}
}
}
}
if (e.KeyCode == Keys.Up)
{
TextBox textBox = sender as TextBox;
string number = GetValue(textBox.Name, "_", "_");
foreach (Control c in Controls)
{
for (int i = int.Parse(number) - 1; i >= 1; i--)
{
if (c.Name == "textBox2_" + i.ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
}
}
}
}
}
/// <summary>
/// 获得字符串中开始和结束字符串中间得值
/// </summary>
/// <param name="str">字符串</param>
/// <param name="s">开始</param>
/// <param name="e">结束</param>
/// <returns></returns>
public static string GetValue(string str, string s, string e)
{
Regex rg = new Regex("(?<=(" + s + "))[.\\s\\S]*?(?=(" + e + "))", RegexOptions.Multiline | RegexOptions.Singleline);
return rg.Match(str).Value;
}
哇塞,搞的这么复杂。 在你的循环中 写textBox.TabIndex=i; 应该就可以实现你要求的功能了。
我不要tab切换,我想要在激活任意一个textbox的情况下能调到周围任意另一个textbox,tab只能按index的顺序切换下去
自定义个textbox继承系统的textbox,然后加几个属性,row,count,前提是你界面固定几行几列,弄个tableLayoutPanel固定好,初始化的时候循环放到容器的行列里面去,按上下的时候判断行列,加减一下,找到对应的textbox激活
把TextBox存在List里,开keyup事件,检测有上或下键(按下)弹起的时候,就把list里的textbox往前或往后取一个,设置它的Focus
你的循环逻辑有问题,foreach从小到大,你的for循环又是全部循环一遍,所以第一个text就匹配了。 你不如去掉for循环直接判断呢。如下就可以。
foreach (Control c in Controls)
{
//for (int i = int.Parse(number) - 1; i >= 1; i--)
//{
if (c.Name == "textBox1_" + (int.Parse(number) - 2).ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
//}
}
}
foreach是为了寻找所有的动态控件,然后for是为了循环这些控件里面enabled的控件,因为我要跳过enabled=false的控件,不然 的话就只是周围一个textbox(如果这个textbox的enabled=false,那么根本无法focus)。for循环只是为了取可以 focus的控件(这也是为什么我要设置部分控件enabled=false的原因)。比如当前为第i个控件,如果第i-1个控件enabled,那么 focus这个控件然后返回,如果第i-1个控件enabled=false,那么for循环取i-2个控件……以此类推,直到取到的控件 enabled,focus之后才返回
你的循环逻辑有问题,foreach从小到大,你的for循环又是全部循环一遍,所以第一个text就匹配了。 你不如去掉for循环直接判断呢。如下就可以。
foreach (Control c in Controls)
{
//for (int i = int.Parse(number) - 1; i >= 1; i--)
//{
if (c.Name == "textBox1_" + (int.Parse(number) - 2).ToString() + "_")
{
if (c.Enabled)
{
c.Select();
return;
}
//}
}
}
你这样改成 (int.Parse(number) - 2).ToString() 纯粹只是一种特例(我简单设置了一个隔一个enabled=false),如果enabled的控件是随机的。就出错
就是UP中for循环去除,就OK拉
代码就简化很多,如下代码我测试了,是可以的。
List<TextBox> mTxt = new List<TextBox> { };
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
TextBox textBox = new TextBox();
textBox.AutoSize = false;
textBox.Width = 80;
textBox.Height = 20;
textBox.TabIndex = 0;
textBox.TabStop = false;
//if (i % 2 == 0)
//{
// textBox.Enabled = false;
//}
textBox.Name = "textBox_" + (i + 1).ToString();
textBox.KeyDown += new KeyEventHandler(textBox1_KeyDown);
textBox.Location = new Point(100, 30 + i * 30);
if (i >= 10)
{
textBox.Location = new Point(300, 30 + (i - 10) * 30);
}
mTxt.Add(textBox);
Controls.Add(textBox);
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
int number = int.Parse(((TextBox)sender).Name.Substring(8, ((TextBox)sender).Name.Length - 8)) - 1;
switch (e.KeyCode)
{
case Keys.Right:
if (number <= 9)
{
mTxt[number + 10].Focus();
}
break;
case Keys.Left:
if (number > 9)
{
mTxt[number - 10].Focus();
}
break;
case Keys.Up:
if (number != 0)
{
mTxt[number - 1].Focus();
}
break;
case Keys.Down:
if (number != 19)
{
mTxt[number + 1].Focus();
}
break;
}
}
你可以用一个二维数组保存动态的控件。这样更容易操作一些。
用一个point来记录当前具有焦点的控件,当按键时,用一个point来收集按键:
Dim newrc As Point = currc
Dim dir As Point = Point.Empty
If e.KeyData = Keys.Up Then dir.X = -1
If e.KeyData = Keys.Down Then dir.X = 1
If e.KeyData = Keys.Left Then dir.Y = -1
If e.KeyData = Keys.Right Then dir.Y = 1
If dir <> Point.Empty Then
Do
newrc += dir
'如果newrc不在r,c范围内,退出循环——超出矩形边缘
'如果newrc所代表的控件enabled,则currc=newrc并将焦点放在当前坐标上的控件
Loop
End If
如果要跳过enabled=false, 学你一样,加个循环判断,哈哈
List<TextBox> mTxt = new List<TextBox> { };
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
TextBox textBox = new TextBox();
textBox.AutoSize = false;
textBox.Width = 80;
textBox.Height = 20;
textBox.TabIndex = 0;
textBox.TabStop = false;
if (i % 3 == 0)
{
textBox.Enabled = false;
}
textBox.Name = "textBox_" + (i + 1).ToString();
textBox.KeyDown += new KeyEventHandler(textBox1_KeyDown);
textBox.Location = new Point(100, 30 + i * 30);
if (i >= 10)
{
textBox.Location = new Point(300, 30 + (i - 10) * 30);
}
mTxt.Add(textBox);
Controls.Add(textBox);
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
int number = int.Parse(((TextBox)sender).Name.Substring(8, ((TextBox)sender).Name.Length - 8)) - 1;
switch (e.KeyCode)
{
case Keys.Right:
if (number <= 9)
{
mTxt[number + 10].Focus();
}
break;
case Keys.Left:
if (number > 9)
{
mTxt[number - 10].Focus();
}
break;
case Keys.Up:
while ((number - 1) > 0 && mTxt[number - 1].Enabled==false )
{
number--;
}
mTxt[number - 1].Focus();
break;
case Keys.Down:
while ((number + 1) < 18 && mTxt[number + 1].Enabled == false)
{
number++;
}
mTxt[number + 1].Focus();
break;
}
}
虽然和我预期的效果还有那么一点点差距。不过方法不错,我考虑一下怎么修改一下。另外UP和DOWN的逻辑稍微论坛发帖机有点问题,18的话有的情况取不到最后一个 textbox,19的话focus的时候算加减会超出数组下标,改成先判断加减1是否超出下标,对number修改之后再focus才行。还是谢谢了