Reputation: 5037
I have a form with a textbox on it that is used to enter a 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.
Any help would be highly appreciated.
Upvotes: 52
Views: 8200
Reputation: 125197
As an option you can add an auto-size label to TextBox
control. Also to force the text start after the label, you need to send EM_SETMARGINS
to apply left padding to the text box:
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);
}
}
Upvotes: 4
Reputation: 48415
Here are a few options:
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)
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)
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)
The fourth, more annoying way, would be to handle one of the key events (such as KeyDown) on the textbox itself. 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. Of course if you were using WPF you would undoubtedly have a lot more flexibility in styling.
Upvotes: 64
Reputation: 941397
You could use a RichTextBox instead, it allows protecting text:
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.
A pragmatic way to do it with a TextBox is to just set it back the way you want it. 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;
}
}
Upvotes: 5
Reputation: 23580
Note: I misread the question, due to somehow I was coming here from the "HTML"-tag. But if you want to do something like this with HTML/CSS, this could be one solution.
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:
And of course, you have to add the 'http://' manually after sending in the form.
The whole thing has one disadvantage. What is, if your user wants to insert 'https://'? :)
Cheers, Philipp
Upvotes: 4
Reputation: 12805
You could also not even display the http:// and just append it to the Textbox.Text code. 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;
Upvotes: 12
Reputation: 1366
Have you considered placing a label beside it with "http://" as the text? and then when accepting the users input you can just append the "http://" with your textbox.Text.
Here is another idea:
On every backspace press, count the number of characters in your textbox. If it is == 7, then ignore the backspace. 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.
private void a_keyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)8)
{
if (myTextbox.Text.Length == 7)
// do stuff..
}
else if //do stuff...
}
Upvotes: 20
Reputation: 101604
If you wanted a CSS approach (coupled with a background image) you can try something like this:
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.
Upvotes: 4
Reputation: 1911
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);
}
}
Upvotes: 6
Reputation: 2340
$('#myField').bind('keypress', function(event)
{
if (event.charCode == 0 && event.currentTarget.value.length <= 7)
{
return false;
}
});
Upvotes: 0
Reputation: 65274
Create a delegate for the keyup
event (and possibly others, e.g. Clipboard) and check the start of the value.
Upvotes: 0
Reputation: 921
You can put a label just left to the textboxt and set its text property to "http://". or you can append 2 textboxes one is read only the other is not read only. and write http:// in the one which is read only.
Upvotes: 1