文本框不可点击但可编辑

时间:2014-07-24 20:12:02

标签: c# winforms textbox

我有一个带有10个文本框的小表单,我将它们设置在右边的Tab顺序中,目前我希望它们以Tab To的方式。我想知道是否有办法设置文本框,因此除非它们被选中,否则无法选择它们进行编辑。即...我不希望最终用户能够点击文本框来编辑它们,我只希望它们可以通过Tabbing进行编辑。

4 个答案:

答案 0 :(得分:6)

这应该可以解决问题

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
}

答案 1 :(得分:1)

这是与Sriram 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;
    }

}

答案 2 :(得分:0)

设置所有文本框&#39; 已启用属性为 false ,但第一个属性除外。在 TextChanged 事件中,检查文字是否为空。如果它不是空的,启用下一个TextBox,依此类推......

答案 3 :(得分:0)

您也可以使用 Enter 事件foreach TextBox

尝试此操作
    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();
    }