我有一个包含10个文本框的小表单,我将它们设置为正确的Tab键顺序,这是我希望它们选中的方式。我想知道是否有办法设置文本框,以便它们不能被选中进行编辑,除非它们被选中。即...我不希望最终用户能够点击文本框来编辑它们,我只希望它们可以通过Tabbing进行编辑。文本框不可点击但可编辑
回答
这应该做的伎俩
public partial class PoorTextBox : TextBox
{
protected override void WndProc(ref Message m)
{
if (m.Msg == (int) WM.LBUTTONDOWN)
{
return;//Eat mouse down events
}
base.WndProc(ref m);
}
}
窗口消息枚举可以发现here。
如何做没有继承
TextBox
:
class EatMouseDown : NativeWindow
{
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM.LBUTTONDOWN)
{
return;
}
base.WndProc(ref m);
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
new EatMouseDown().AssignHandle(textBox1.Handle);//Subclass a Handle
}
如何做到这一点没有任何继承:
清理省略的部分,这也很重要。这可能是越野车,但它的作品。推荐的方法是使用继承。必需的方法从.net fw src中提取。
class EatMouseDown
{
public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
#region External methods...
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, WndProc wndproc);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, WndProc wndproc);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLong(HandleRef hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLongPtr(HandleRef hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
#endregion
private const int GWLP_WNDPROC = -4;
private IntPtr handle;
private IntPtr originalWndProc;
private IntPtr currentWndProc;
public static IntPtr SetWindowLongHelper(HandleRef hWnd, int nIndex, WndProc wndProc)
{
return IntPtr.Size == 4
? SetWindowLong(hWnd, nIndex, wndProc)
: SetWindowLongPtr(hWnd, nIndex, wndProc);
}
public static IntPtr GetWindowLongHelper(HandleRef hWnd, int nIndex)
{
return IntPtr.Size == 4
? GetWindowLong(hWnd, nIndex)
: GetWindowLongPtr(hWnd, nIndex);
}
internal void SubclassHandle(IntPtr handle)
{
this.handle = handle;
this.originalWndProc = GetWindowLongHelper(new HandleRef(this, handle), GWLP_WNDPROC);
SetWindowLongHelper(new HandleRef(this, handle), GWLP_WNDPROC, new WndProc(this.Callback));
this.currentWndProc = GetWindowLongHelper(new HandleRef(this, handle), GWLP_WNDPROC);
}
private IntPtr Callback(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam)
{
var m = Message.Create(hwnd, msg, wparam, lparam);
if (m.Msg == (int)WM.LBUTTONDOWN)
{
return IntPtr.Zero;
}
return CallWindowProc(originalWndProc, hwnd, msg, wparam, lparam);
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
new EatMouseDown().SubclassHandle(textBox1.Handle);//Subclass a Handle
}
这真的很难看 –
@MatinLotfaliee不要幼稚。 –
那么,我相信继承和使用Windows消息是丑陋的,当他可以做一些简单的事件。 –
设置所有文本框'启用属性为虚假除第一个。在TextChanged事件中,检查它是否为文本为空或不是。如果不是空的,启用下一个文本框等等...
这可能是可行的,我会看到如果我能从你的建议中得出一个工作解决方案。谢谢。 – roadmaster
这不是一个真正的答案,因为它对文本的相关性作出了空白或不是没有问题的假设。但也许它有助于... – TaW
你也可以试试这个与输入事件的foreach文本框
private void textBox2_Enter(object sender, EventArgs e)
{
if (textBox1.Text == "")
textBox1.Focus();
}
private void textBox3_Enter(object sender, EventArgs e)
{
if (textBox1.Text == "")
textBox1.Focus();
else
if (textBox2.Text == "")
textBox2.Focus();
}
private void textBox4_Enter(object sender, EventArgs e)
{
if (textBox1.Text == "")
textBox1.Focus();
else
if (textBox2.Text == "")
textBox2.Focus();
else
if (textBox3.Text == "")
textBox3.Focus();
}
这真的很难看 –
这不是一个真正的答案,因为它可以假设文本的相关性为空或者不在问题中。但也许它有帮助.. – TaW
这里有一个类似的方法是什么斯利拉姆Sakthivel做了,但使用IMessageFilter来代替:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
List<TextBox> TextBoxes = new List<TextBox>();
FindTextBoxes(this, TextBoxes);
Application.AddMessageFilter(new SuppressTextBoxClicks(TextBoxes));
}
private void FindTextBoxes(Control ctl, List<TextBox> TBs)
{
foreach(Control childCtl in ctl.Controls)
{
if (childCtl is TextBox)
{
TBs.Add((TextBox)childCtl);
}
else if(childCtl.HasChildren)
{
FindTextBoxes(childCtl, TBs);
}
}
}
}
public class SuppressTextBoxClicks : IMessageFilter
{
private List<TextBox> _TextBoxes = null;
private const int WM_LBUTTONDOWN = 0x201;
public SuppressTextBoxClicks(List<TextBox> TextBoxes)
{
_TextBoxes = TextBoxes;
}
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
if (_TextBoxes != null)
{
foreach(TextBox TB in _TextBoxes)
{
if (TB.Handle.Equals(m.HWnd))
{
return true;
}
}
}
break;
default:
break;
}
return false;
}
}
我正要添加类似的使用'IMessageFilter',现在没有必要它+1 :) –
- 1. 可编辑的文本框点击,angular.js
- 2. itext - 可编辑的texfield不可点击
- 3. 当我点击对应的复选框时,如何让不可编辑的文本框可编辑
- 4. 可编辑文本框
- 5. JTable单元格不可编辑但可点击
- 6. wxPython中的不可编辑文本框
- 7. Lightswitch文本框不可编辑
- 8. 可点击但不可见?
- 9. 在一次点击中选择所有文本(不可编辑)
- 10. 可点击网格而不是编辑
- 11. 使可点击的行可编辑
- 12. TinyMce编辑器文本框不可编辑
- 13. 日期选择器文本框编辑不可编辑
- 14. 可选但不可编辑的html文本字段
- 15. 使文本字段可查看但不可编辑
- 16. 不可编辑的文本框,但能够选择文本和过程
- 17. XUL文本框是不可编辑或可见
- 18. 可编辑文本框通过JSON
- 19. jQuery的可编辑的GUI文本框
- 20. bootgrid与可编辑文本框
- 21. 可编辑的文本框tableviewcell迅速
- 22. 使文本框可编辑使用JavaScript
- 23. 可编辑的富文本框
- 24. jQuery中的可编辑文本框
- 25. 的EditText无论是编辑还是不可编辑,并点击
- 26. fabricjs - 允许单击文本编辑,但区分文本点击和边框点击
- 27. 禁用可编辑文本 - 它不应该是可编辑的
- 28. 文本字段使可编辑,不可编辑使用jquery
- 29. 如何使文本框可点击
- 30. 点击时可见的文本框
请问以这种方式控制用户体验的东西是否会吸引你?看起来像一个奇怪的要求。 –
如果用户计算机中的tab键出现故障,该怎么办:p –
订阅“Click”事件并在发射时聚焦另一个控件会怎样?另外,我想知道和@MikeCheel一样的东西。 – Jashaszun