如何移除文本框的顶部和两侧边框

huangapple go评论126阅读模式
英文:

How to remove border of top and both sides of a TextBox

问题

我遇到了如何移除 Windows Forms 项目中 TextBox 顶部和两侧边框的问题。

我希望 TextBox 看起来像这样:

如何移除文本框的顶部和两侧边框

我的文本框代码:

this.textBox1.Anchor = System.Windows.Forms.AnchorStyles.None;
this.textBox1.Location = new System.Drawing.Point(85, 101);
this.textBox1.Name = "textBox1";
this.textBox1.PlaceholderText = "Login";
this.textBox1.Size = new System.Drawing.Size(213, 23);
this.textBox1.TabIndex = 0;
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;

你能帮我解决这个问题吗?

英文:

I'm with struggle with how to remove border of top and both sides of TextBox in Windows Forms project

I want the TextBox looks like this:

如何移除文本框的顶部和两侧边框

My textbox code:

this.textBox1.Anchor = System.Windows.Forms.AnchorStyles.None;
this.textBox1.Location = new System.Drawing.Point(85, 101);
this.textBox1.Name = "textBox1";
this.textBox1.PlaceholderText = "Login";
this.textBox1.Size = new System.Drawing.Size(213, 23);
this.textBox1.TabIndex = 0;
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;

Could you help me with this?

答案1

得分: 3

首先,快速且简单的解决方案

创建一个Label,其中包含重复的下划线字符,并将其定位在登录TextBox的底部:

txtName.BorderStyle = BorderStyle.None;
Label lblBottomBorder = new Label();
lblBottomBorder.ForeColor = Color.Blue;
lblBottomBorder.Width = txtName.Width + 8;
lblBottomBorder.Text = new String('_', 250);
lblBottomBorder.Location = new Point(txtName.Location.X - 3, txtName.Location.Y + 3);
Controls.Add(lblBottomBorder);

编辑:

第二种更灵活的解决方案

覆盖Form.OnPaint()方法,并使用Graphics.DrawLine()方法在登录TextBox下面绘制自定义线条:

public partial class FrmLogin : Form
{
    public FrmLogin()
    {
        InitializeComponent();
        Text = "Login";
        StartPosition = FormStartPosition.CenterScreen;
        MaximizeBox = false;
        MinimizeBox = false;
        FormBorderStyle = FormBorderStyle.FixedDialog;
        Font = new Font("Segoe UI", 10);
        BackColor = Color.White;
        AcceptButton = btnOK;
        Activated += (sender, e) => txtEmail.PlaceholderText = "Email, phone or Skype";

        lblEnter.Font = new Font("Segoe UI", 14, FontStyle.Bold);
        txtEmail.BorderStyle = BorderStyle.None;
        txtEmail.ForeColor = Color.DimGray;

        btnOK.BackColor = Color.DarkBlue;
        btnOK.ForeColor = Color.White;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Point txtEmailLocation = PointToClient(PointToScreen(txtEmail.Location));
        var lineStart = new Point(txtEmailLocation.X, txtEmailLocation.Y + txtEmail.Height + 7);
        var lineEnd = new Point(txtEmailLocation.X + txtEmail.Width, txtEmailLocation.Y + txtEmail.Height + 7);
        Pen pen = new Pen(Color.Blue) { Width = 2 };
        e.Graphics.DrawLine(pen, lineStart, lineEnd);
    }
}

请注意,TextBox.PlaceholderText属性需要.NET 5+。登录表单的屏幕截图如下:

如何移除文本框的顶部和两侧边框

虽然不像Microsoft页面那样优雅,但能完成任务。

英文:

First, quick and dirty solution

Create a Label with repeated underscore characters and locate it at the bottom of the login TextBox:

txtName.BorderStyle = BorderStyle.None;
Label lblBottomBorder = new Label();
lblBottomBorder.ForeColor = Color.Blue;
lblBottomBorder.Width = txtName.Width + 8;
lblBottomBorder.Text = new String('_', 250);
lblBottomBorder.Location = new Point(txtName.Location.X - 3, txtName.Location.Y + 3);
Controls.Add(lblBottomBorder);

EDIT:

Second and more flexible solution

Override the Form.OnPaint() method and draw a custom line under the login TextBox using the Graphics.DrawLine() method:

public partial class FrmLogin : Form
{
    public FrmLogin()
    {
        InitializeComponent();
        Text = "Login";
        StartPosition = FormStartPosition.CenterScreen;
        MaximizeBox = false;
        MinimizeBox = false;
        FormBorderStyle = FormBorderStyle.FixedDialog;
        Font = new Font("Segoe UI", 10);
        BackColor = Color.White;
        AcceptButton = btnOK;
        Activated += (sender, e) => txtEmail.PlaceholderText = "Email, phone or Skype";

        lblEnter.Font = new Font("Segoe UI", 14, FontStyle.Bold);
        txtEmail.BorderStyle = BorderStyle.None;
        txtEmail.ForeColor = Color.DimGray;

        btnOK.BackColor = Color.DarkBlue;
        btnOK.ForeColor = Color.White;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Point txtEmailLocation = PointToClient(PointToScreen(txtEmail.Location));
        var lineStart = new Point(txtEmailLocation.X, txtEmailLocation.Y + txtEmail.Height + 7);
        var lineEnd = new Point(txtEmailLocation.X + txtEmail.Width, txtEmailLocation.Y + txtEmail.Height + 7);
        Pen pen = new Pen(Color.Blue) { Width = 2 };
        e.Graphics.DrawLine(pen, lineStart, lineEnd);
    }
}

Please note that the TextBox.PlaceholderText property requires .NET 5+. The screenshot of the login form is:

如何移除文本框的顶部和两侧边框

Not as elegant as the Microsoft page but it gets the job done.

答案2

得分: 2

尝试使用这个简单的UserControl。它只包含一个标准的TextBox控件,并添加了一些属性来定义新的行为。

  • 它提供了自定义绘制背景以显示底部可调整大小的线条
  • 允许更改底线的颜色
  • 根据当前TextBox的大小自动调整大小(例如,当您更改字体时)
  • 可以设置Cue Banner(灰色文本),当文本为空时
  • 允许设置输入框用于输入密码时的替换字符
  • 允许右到左布局

当然,您可以随时添加其他内容(例如,添加一些图形元素相当简单)

要构建此UserControl:

  • 向项目添加一个新的UserControl,命名为 TextBoxInput(暂时命名为此)
  • 将其Width设置为 150
  • 将其Padding设置为 (3, 10, 3, 1),并将BorderStyle设置为 None
  • 将其AutoScaleMode设置为 Dpi
  • 添加一个TextBox,命名为 EditControl,并将其停靠到Top
  • 更改UserControl的BackColorForeColor属性以匹配TextBox的属性
  • 使用此处找到的代码替换代码文件中的内容(保留namespace
  • 构建项目,在工具箱中找到您的UserControl,并将其拖放到窗体上

自定义设计器。仅用于删除一些无关的属性和对控件分配的默认文本(以便显示Cue Banner)。

要在.NET 5+应用程序中使用设计器,请通过NuGet包管理器安装Microsoft.WinForms.Designer.SDK支持。

public class TextBoxInputDesigner : ControlDesigner {
    private readonly string[] RemovedProperties = new[] {
        "AutoSize", "AutoSizeMode", "AutoScroll", "AutoScrollMargin", "AutoScrollMinSize",
        "BackgroundImage", "BackgroundImageLayout", "Cursor"
    };

    public TextBoxInputDesigner() { }

    public override void InitializeNewComponent(IDictionary defaultValues) {
        base.InitializeNewComponent(defaultValues);

        var descriptor = TypeDescriptor.GetProperties(Component)["Text"];
        if (descriptor != null && (descriptor.PropertyType == typeof(string))) {
            descriptor.SetValue(Component, string.Empty);
        }
    }

    protected override void PreFilterProperties(IDictionary properties) {
        foreach (string prop in RemovedProperties) {
            properties.Remove(prop);
        }
        base.PreFilterProperties(properties);
    }
}

这是它的工作原理:

如何移除文本框的顶部和两侧边框

英文:

Try out this simple UserControl. It just contains a standard TextBox Control and adds some properties to define the new behavior.

  • It provides custom painting of the background to show a resizable line at the bottom
  • Allows to change the Color of the bottom line
  • Auto-sizes depending on the current TextBox size (e.g, when you change the Font)
  • Can set a Cue Banner (grayed text) when the text is empty
  • Allows to set a replacement char when the input box is used to enter a Password
  • Allows Right-To-Left layout

You can of course add other stuff as you go (e.g., adding some graphic elements it's quite simple)


To build this UserControl:

  • Add a new UserControl to the Project, name it TextBoxInput (for now)
  • Set its Width to 150
  • Set its Padding to (3, 10, 3, 1) and BorderStyle = None
  • Set its AutoScaleMode = Dpi
  • Add a TextBox, name it EditControl and dock it to Top
  • Change the BackColor and ForeColor properties of the UserControl to match the TextBox's properties
  • Replace what's in the code file with the code you find here (preserving the namespace)
  • Build the Project, find your UserControl in the ToolBox and drop it on a Form

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.Design;

[Designer(typeof(TextBoxInputDesigner))]
public partial class TextBoxInput : UserControl {
    private string m_CueBanner = string.Empty;
    private bool m_CueBannerShowOnFocus = true;
    private Color m_LineColor = Color.CadetBlue;
    private int m_LineDistance = 4;
    private int m_LineHeight = 1;

    public TextBoxInput() {
        InitializeComponent();
        ResizeRedraw = true;
        Padding = new Padding(3, 10, 3, 1);
        EditControl.TextChanged += (_, __) => OnTextChangedInternal(EditControl.Text, false);
        EditControl.HandleCreated += (_, __) => SetCueBanner(EditControl.Handle, m_CueBanner, m_CueBannerShowOnFocus);
        CueBanner = "<Enter CueBanner>";
    }

    public string CueBanner { 
        get => m_CueBanner;
        set {
            m_CueBanner = value;
            SetCueBanner(EditControl.Handle, m_CueBanner, m_CueBannerShowOnFocus);
        } 
    }

    [DefaultValue(true)]
    public bool CueBannerShowOnFocus { 
        get => m_CueBannerShowOnFocus; 
        set {
            m_CueBannerShowOnFocus = value;
            SetCueBanner(EditControl.Handle, m_CueBanner, m_CueBannerShowOnFocus);
        }
    }

    public Color LineColor {
        get => m_LineColor;
        set {
            m_LineColor = value;
            Invalidate();
        }
    }

    [DefaultValue(1), Description("Sets the height of the Line. Allowed values (1, 8)")]
    public int LineHeight {
        get => m_LineHeight;
        set {
            m_LineHeight = Math.Max(1, Math.Min(value, 8));
            Invalidate();
            OnResize(EventArgs.Empty);
        }
    }

    [DefaultValue(false)]
    public bool IsPassword { 
        get => EditControl.UseSystemPasswordChar;
        set => EditControl.UseSystemPasswordChar = value;
    }

    [Bindable(true), Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public override string Text {
        get => base.Text; 
        set {
            OnTextChangedInternal(value, true);
        } 
    }

    protected override void OnBackColorChanged(EventArgs e) {
        base.OnBackColorChanged(e);
        EditControl.BackColor = base.BackColor;
    }

    protected override void OnForeColorChanged(EventArgs e) {
        base.OnForeColorChanged(e);
        EditControl.ForeColor = base.ForeColor;
    }

    protected override void OnLayout(LayoutEventArgs e) {
        base.OnLayout(e);
        ClientSize = new Size(ClientSize.Width, EditControl.Bounds.Bottom + m_LineDistance + m_LineHeight + 1);
    }

    protected override void OnPaintBackground (PaintEventArgs e) {
        base.OnPaintBackground(e);
        int yPos = EditControl.Bounds.Bottom + m_LineDistance + (m_LineHeight / 2);
        using (var pen = new Pen(m_LineColor, m_LineHeight)) {
            e.Graphics.DrawLine(pen, 0, yPos, ClientSize.Width, yPos);
        }
    }

    protected override void OnRightToLeftChanged(EventArgs e) {
        base.OnRightToLeftChanged(e);
        EditControl.RightToLeft = RightToLeft;
    }

    internal virtual void OnTextChangedInternal(string text, bool internalCall) {
        base.Text = text;
        if (internalCall) EditControl.Text = text;
        OnTextChanged(EventArgs.Empty);
        SetCueBanner(EditControl.Handle, m_CueBanner, m_CueBannerShowOnFocus);
    }

    public void SetCueBanner(IntPtr handle, string text, bool showOnFocus) {
        if (handle != IntPtr.Zero) {
            SendMessage(handle, EM_SETCUEBANNER, showOnFocus ? 1 : 0, text);
        }
    }

    private const int EM_SETCUEBANNER = 0x1501;

    [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, string lParam);
}

Custom designer. This is used just to remove some irrelevant properties and the default text assigned to a Control (so the Cue Banner is shown instead).

To use the designer in a .NET 5+ application, install, via NuGetPackage Manager, the Microsoft.WinForms.Designer.SDK support.

public class TextBoxInputDesigner : ControlDesigner {
    private readonly string[] RemovedProperties = new[] {
            "AutoSize", "AutoSizeMode", "AutoScroll", "AutoScrollMargin","AutoScrollMinSize",
            "BackgroundImage", "BackgroundImageLayout", "Cursor"
        };

    public TextBoxInputDesigner() { }

    public override void InitializeNewComponent(IDictionary defaultValues) {
        base.InitializeNewComponent(defaultValues);

        var descriptor = TypeDescriptor.GetProperties(Component)["Text"];
        if (descriptor != null && (descriptor.PropertyType == typeof(string))) {
            descriptor.SetValue(Component, string.Empty);
        }
    }

    protected override void PreFilterProperties(IDictionary properties) {
        foreach (string prop in RemovedProperties) {
            properties.Remove(prop);
        }
        base.PreFilterProperties(properties);
    }
}

This is how it works:

如何移除文本框的顶部和两侧边框

huangapple
  • 本文由 发表于 2023年8月10日 22:26:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76876685.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定