You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为C# WinForms的TextBox控件添加占位符(含密码框场景)

为C# WinForms控件添加占位符的实现方案

刚好做过类似的需求,给你分享一套完整的实现思路和代码,完美匹配你提到的两个核心要求:空文本失焦时显示占位符密码框模式下占位符明文显示,输入时切换为密码字符

核心实现思路

WinForms原生TextBox没有内置占位符功能,直接修改Text属性模拟的话,在密码框模式(UsePasswordChar=true)下会导致占位符被掩码成密码字符,不符合需求。所以正确的思路是:

  • 不修改控件的Text属性,而是通过重绘控件的方式绘制占位符文本
  • 利用GotFocus/LostFocus事件判断何时显示/隐藏占位符
  • 结合TextChanged事件,确保用户输入内容时自动隐藏占位符

具体代码实现(自定义TextBox控件)

最方便的方式是封装一个自定义TextBox控件,这样可以在整个项目中复用,无需重复写事件逻辑:

using System.Drawing;
using System.Windows.Forms;

public class PlaceholderTextBox : TextBox
{
    // 存储占位符文本
    private string _placeholderText = "请输入内容";
    // 标记是否需要显示占位符
    private bool _showPlaceholder;

    // 对外暴露占位符设置属性
    public string PlaceholderText
    {
        get => _placeholderText;
        set
        {
            _placeholderText = value;
            // 更改后触发重绘
            Invalidate();
        }
    }

    public PlaceholderTextBox()
    {
        // 绑定必要的事件
        GotFocus += PlaceholderTextBox_GotFocus;
        LostFocus += PlaceholderTextBox_LostFocus;
        Paint += PlaceholderTextBox_Paint;
        TextChanged += PlaceholderTextBox_TextChanged;
    }

    private void PlaceholderTextBox_TextChanged(object sender, System.EventArgs e)
    {
        // 用户输入内容时,自动隐藏占位符
        if (!string.IsNullOrEmpty(Text))
        {
            _showPlaceholder = false;
            Invalidate();
        }
    }

    private void PlaceholderTextBox_GotFocus(object sender, System.EventArgs e)
    {
        // 获得焦点时,如果当前显示占位符,就隐藏它
        if (_showPlaceholder)
        {
            _showPlaceholder = false;
            Invalidate();
        }
    }

    private void PlaceholderTextBox_LostFocus(object sender, System.EventArgs e)
    {
        // 失去焦点且文本为空时,显示占位符
        if (string.IsNullOrEmpty(Text))
        {
            _showPlaceholder = true;
            Invalidate();
        }
    }

    private void PlaceholderTextBox_Paint(object sender, PaintEventArgs e)
    {
        // 满足条件时绘制占位符
        if (_showPlaceholder && string.IsNullOrEmpty(Text))
        {
            // 使用灰色文本模拟占位符样式,可自定义颜色
            using (var placeholderBrush = new SolidBrush(SystemColors.GrayText))
            {
                // 模拟原生文本的padding和对齐方式,视觉更统一
                var textRect = new Rectangle(
                    Padding.Left,
                    Padding.Top,
                    ClientSize.Width - Padding.Left - Padding.Right,
                    ClientSize.Height - Padding.Top - Padding.Bottom
                );

                // 匹配控件的文本对齐设置
                var textFormat = new StringFormat();
                switch (TextAlign)
                {
                    case HorizontalAlignment.Left:
                        textFormat.Alignment = StringAlignment.Near;
                        break;
                    case HorizontalAlignment.Center:
                        textFormat.Alignment = StringAlignment.Center;
                        break;
                    case HorizontalAlignment.Right:
                        textFormat.Alignment = StringAlignment.Far;
                        break;
                }

                // 绘制占位符文本
                e.Graphics.DrawString(_placeholderText, Font, placeholderBrush, textRect, textFormat);
            }
        }
    }

    // 重写WndProc处理密码框模式下的重绘消息
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        // WM_PAINT消息,确保密码框切换时占位符正常显示
        if (m.Msg == 0x000F)
        {
            if (_showPlaceholder && string.IsNullOrEmpty(Text))
            {
                Invalidate();
            }
        }
    }
}

使用方法

设计器方式

编译项目后,这个自定义控件会出现在WinForms设计器的工具箱里,直接拖到窗体上即可,然后在属性面板设置:

  • PlaceholderText:自定义占位符内容
  • UsePasswordChar:设置为true即可开启密码框模式

代码创建方式

// 创建密码框实例
var passwordInput = new PlaceholderTextBox();
passwordInput.PlaceholderText = "请输入登录密码";
passwordInput.UsePasswordChar = true;
passwordInput.Location = new Point(20, 20);
passwordInput.Size = new Size(250, 28);
this.Controls.Add(passwordInput);

// 创建普通输入框实例
var usernameInput = new PlaceholderTextBox();
usernameInput.PlaceholderText = "请输入用户名";
usernameInput.Location = new Point(20, 60);
usernameInput.Size = new Size(250, 28);
this.Controls.Add(usernameInput);

关键细节说明

  1. 密码框兼容性:因为占位符是通过Paint事件绘制的,没有修改TextBox的Text属性,所以即使UsePasswordChar=true,占位符依然是明文显示,用户输入时直接显示密码字符,完全符合需求。
  2. 视觉一致性:绘制占位符时考虑了控件的PaddingTextAlign属性,和原生文本的显示位置完全一致,不会出现偏移。
  3. 复用性:自定义控件的方式可以在整个项目中重复使用,无需为每个TextBox绑定事件。

内容的提问来源于stack exchange,提问作者Hassan Kotti

火山引擎 最新活动