I want to make a control which inherits from TextBox and which has a label inside which "sticks" to the right side of the text box and which text is not user-editable but rather is set by a property. How can this be done? I realize there may be many reasons why this UX is a bad idea, but I have to do it this way.
问题:
回答1:
Adapting from Hans Passant's Button inside a winforms textbox answer:
public class TextBoxWithLabel : TextBox {
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
Label label = new Label();
public TextBoxWithLabel() {
label.BackColor = Color.LightGray;
label.Cursor = Cursors.Default;
label.TextAlign = ContentAlignment.MiddleRight;
this.Controls.Add(label);
}
private int LabelWidth() {
return TextRenderer.MeasureText(label.Text, label.Font).Width;
}
public string LabelText {
get { return label.Text; }
set {
label.Text = value;
SendMessage(this.Handle, 0xd3, (IntPtr)2, (IntPtr)(LabelWidth() << 16));
OnResize(EventArgs.Empty);
}
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
int labelWidth = LabelWidth();
label.Left = this.ClientSize.Width - labelWidth;
label.Top = (this.ClientSize.Height / 2) - (label.Height / 2);
label.Width = labelWidth;
label.Height = this.ClientSize.Height;
}
}
Result:
回答2:
I will suggest you to create a UserControl
with TextBox
and a Label
docked right. That should be pain less and bug free.
As you said you already use TextBox
to avoid much refactoring you can add all the properties you used in TextBox as "Proxy properties". Something like this:
class MyTextBox : UserControl
{
public int TextLength { get { return textbox.TextLength; } }
...
}
This can help you to avoid much refactoring.
回答3:
I would actually create a composit control, or simply a UserControl, and put a label and textbox next to each other. Then you can remove the borders around the textbox and surround them with a borderbox to mimic the normal textbox design.
Finally I would make sure that the user controls properties, like Text
is mapped to the Textbox, so it is easy to use the control as a drop-replacement.