简体   繁体   English

如何将WinForms TextBox的前几个字符设置为只读?

[英]How to set the first few characters of a WinForms TextBox to Read-Only?

I have a form with a textbox on it that is used to enter a URL. 我有一个带有文本框的表单,用于输入URL。 I need to add (http://) as a predefined value to this textbox and want it to be read only so the user won't be able to remove the http:// but he can write after it. 我需要将(http://)作为预定义的值添加到此文本框中,并希望它只读,这样用户就无法删除http://但是他可以在它之后写。

在此输入图像描述

Any help would be highly appreciated. 任何帮助将受到高度赞赏。

Here are a few options: 以下是一些选项:

  1. The easy way is to just create a label outside the text box (to the left) with those characters. 简单的方法是在文本框(左侧)外面创建一个带有这些字符的标签 (simple and easy to understand for the user) (用户简单易懂)

  2. Create a second readonly text box to use at the start, style it to match the input one and align them next to each other. 创建第二个只读文本框以在开始时使用,设置它以匹配输入的文本框并将它们彼此相邻对齐。 Yes, you will get a single pixel line to split them both, but I think this will add to the user experience to make it obvious this is not for messing with (I would personally choose this option) 是的,你会得到一个像素线将它们分开,但我认为这会增加用户体验,使其显而易见,这不是为了搞乱(我个人会选择这个选项)

  3. If you need the style you can roll your own user control that uses a panel, label and textbox with appropriate border styling set as needed. 如果您需要该样式,您可以使用面板,标签和文本框滚动您自己的用户控件 ,并根据需要设置适当的边框样式。 (best way to get the exact style you need) (获得所需风格的最佳方式)

  4. The fourth, more annoying way, would be to handle one of the key events (such as KeyDown ) on the textbox itself. 第四种更烦人的方法是处理文本框本身的一个关键事件(如KeyDown )。 With this you can do numerous checks and alter the caret position to make it work, but trust me this will do your head in trying to get it working perfectly! 有了这个,你可以做很多检查,并改变插入位置,使其工作,但相信我,这将努力让它完美地工作! (way too much hard work to get right) (太过努力才能做到正确)

To summarise, I think option 2 is the best here. 总而言之,我认为选项2在这里是最好的。 Of course if you were using WPF you would undoubtedly have a lot more flexibility in styling. 当然,如果你使用WPF,你无疑会在造型上有更多的灵活性。

Have you considered placing a label beside it with "http://" as the text? 您是否考虑在其旁边放置一个带有“http://”作为文本的标签? and then when accepting the users input you can just append the "http://" with your textbox.Text. 然后在接受用户输入时,您可以使用textbox.Text附加“http://”。

Here is another idea: 这是另一个想法:

On every backspace press, count the number of characters in your textbox. 在每个退格按下时,计算文本框中的字符数。 If it is == 7, then ignore the backspace. 如果是== 7,则忽略退格。 If it is greater, then check the number of characters after the backspace. 如果它更大,则检查退格后的字符数。 If the number of characters is less than 7, clear the textbox and reset the text. 如果字符数小于7,请清除文本框并重置文本。

private void a_keyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == (char)8)
    {
        if (myTextbox.Text.Length == 7)
        // do stuff..
    }
    else if //do stuff...
}

You could also not even display the http:// and just append it to the Textbox.Text code. 您甚至可能无法显示http://并将其附加到Textbox.Text代码。 Check first that it doesn't start with that as well. 首先检查它是否也不是从那开始。

To clarify my last remark: 澄清我的上一句话:

string sURL = txtURL.Text.StartsWith("http://") ? txtURL.Text : "http://" + txtURL.Text;

Something like this? 像这样的东西?

private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
    var textBox = sender as TextBox;

    if (!textBox.Text.StartsWith("http://"))
    {
        textBox.Text = "http://";
        textBox.Select(textBox.Text.Length, 0);

    }
}

You could use a RichTextBox instead, it allows protecting text: 您可以使用RichTextBox,它允许保护文本:

    public Form1() {
        InitializeComponent();
        richTextBox1.Text = "http://";
        richTextBox1.SelectAll();
        richTextBox1.SelectionProtected = true;
        richTextBox1.SelectionStart = richTextBox1.Text.Length;
        richTextBox1.DetectUrls = false;  // optional
    }

But unfortunately it doesn't work well if you set its Multiline property to False. 但不幸的是,如果将Multiline属性设置为False,它将无法正常工作。

A pragmatic way to do it with a TextBox is to just set it back the way you want it. 使用TextBox执行此操作的实用方法是将其设置为您想要的方式。 Also works with pastes and selection deletes: 也适用于粘贴和选择删除:

    string protect = "http://";

    private void textBox1_TextChanged(object sender, EventArgs e) {
        if (!textBox1.Text.StartsWith(protect)) {
            textBox1.Text = protect;
            textBox1.SelectionStart = textBox1.Text.Length;
        }
    }

Note: I misread the question, due to somehow I was coming here from the "HTML"-tag. 注意:我误解了这个问题,因为不知怎的,我是从“HTML”标签来到这里的。 But if you want to do something like this with HTML/CSS, this could be one solution. 但是如果你想用HTML / CSS做这样的事情,这可能是一个解决方案。

You could do something like this: 你可以这样做:

<style>
    label.mylabel, input.myinput {
        display:        block;
        float:          left;
        height:         20px;
        margin:         0;
        padding:        10px 5px 0px 5px;
        border:         1px solid #ccc;
        font-size:      11px;
        line-height:    11px;
    }

    label.mylabel {
        border-right:   0;
    }

    input.myinput {
        border-left:    0;
    }
</style>

<label class="mylabel" for="myinput">http://</label>
<input id="myinput" class="myinput" name="myinput" value="">

So this has two advantages: 所以这有两个好处:

  • it looks like one input box 它看起来像一个输入框
  • when the user hits "http", the actually form field will be focused 当用户点击“http”时,实际的表单字段将被聚焦

And of course, you have to add the 'http://' manually after sending in the form. 当然,您必须在发送表单后手动添加“http://”。

The whole thing has one disadvantage. 整个事情有一个缺点。 What is, if your user wants to insert 'https://'? 如果您的用户想要插入“https://”,该怎么办? :) :)

Cheers, Philipp 干杯,菲利普

If you wanted a CSS approach (coupled with a background image) you can try something like this : 如果你想要一个CSS方法(加上背景图片),你可以尝试这样的事情

Enter URL: <input type="text" size="50" class="url" value="www.google.com" />

<style>
  input[type="text"].url {
    background: url(http://s18.postimage.org/4wkjdpidh/http.png) no-repeat left top transparent;
    text-indent: 34px;
  }
</style>

Then it's just a matter of prepending the http:// back on the input's value when you go to process it. 然后,当你去处理它时,只需要将http://重新加上输入的值。

As an option you can add an auto-size label to TextBox control. 作为选项,您可以向TextBox控件添加自动大小标签。 Also to force the text start after the label, you need to send EM_SETMARGINS to apply left padding to the text box: 另外,要强制文本在标签后开始,您需要发送EM_SETMARGINS以将左边距填充到文本框:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class SampleTextBox : TextBox
{
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);
    private const int EM_SETMARGINS = 0xd3;
    private const int EC_LEFTMARGIN = 1;
    private Label label;
    public SampleTextBox() : base()
    {
        label = new Label() { Text = "http://", Dock = DockStyle.Left, AutoSize = true };
        this.Controls.Add(label);
    }
    public string Label
    {
        get { return label.Text; }
        set { label.Text = value; if (IsHandleCreated) SetMargin(); }
    }
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        SetMargin();
    }
    private void SetMargin()
    {
        SendMessage(this.Handle, EM_SETMARGINS, EC_LEFTMARGIN, label.Width);
    }
}

You can put a label just left to the textboxt and set its text property to "http://". 您可以在文本文本左侧放置一个标签,并将其text属性设置为“http://”。 or you can append 2 textboxes one is read only the other is not read only. 或者你可以附加2个文本框,一个是只读的,另一个不是只读的。 and write http:// in the one which is read only. 并在只读的一个中写入http://。

keyup事件创建委托(可能还有其他人,例如Clipboard)并检查值的开头。

$('#myField').bind('keypress', function(event)
{
    if (event.charCode == 0 && event.currentTarget.value.length <= 7)
{
     return false;
}
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM