WPF有PasswordBox接收密码输入到SecureString,但我有一个WinForms应用程序。我可以使用SecurePasswordTextBox,但我想要一些与DevExpress控件和DevExpress外观自定义混合的东西。在DevExpress TextEdit控件上,您可以设置UseSystemPasswordChar = true,但它不使用SecureString(并且不会:cf. 10/22/2010,cf. also。
如何轻松地将SecureString支持转换为DevExpress WinForms TextEdit控件?
我提出了一些问题,我将其作为自己的答案发布在下面。还有其他人有解决方案吗?
编辑:我接受我自己的答案,这是有效的,因为我需要DevExpress外观。
答案 0 :(得分:1)
最简单的方法是使用在ElementHost中托管的WPF PasswordBox。
您可以从ToolBox中拖动ElementHost控件,或者在代码中执行整个操作:
public Form1()
{
InitializeComponent();
System.Windows.Forms.Integration.ElementHost host = new System.Windows.Forms.Integration.ElementHost();
System.Windows.Controls.PasswordBox pb=new System.Windows.Controls.PasswordBox();
host.Child = pb;
this.Controls.Add(host);
}
当然这不使用DevExpress控件,但是当有一个简单的替代方法时,我看不出有任何理由将Rich Text Editor用作密码框。
答案 1 :(得分:1)
这是我自己的答案:
而不是继承TextEdit,这似乎太复杂了,我只是抓住KeyPress事件并隐藏每个按下的字符,直到EditValueChanging事件。我在假字符串中保留了唯一的标记,以便我可以在每个EditValueChanging事件中找出我的SecureString中要更改的内容。
这是概念验证 - 一个带有TextEdit控件和两个事件处理程序的简单表单:
public partial class PasswordForm : DevExpress.XtraEditors.XtraForm
{
private Random random = new Random();
private HashSet<char> pool = new HashSet<char>();
private char secret;
private char token;
private List<char> fake = new List<char>();
public PasswordForm()
{
InitializeComponent();
this.Password = new SecureString();
for (int i = 0; i < 128; i++)
{
this.pool.Add((char)(' ' + i));
}
}
public SecureString Password { get; private set; }
private void textEditPassword_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
string value = e.NewValue as string;
// If any characters have been deleted...
foreach (char c in this.fake.ToArray())
{
if (value.IndexOf(c) == -1)
{
this.Password.RemoveAt(this.fake.IndexOf(c));
this.fake.Remove(c);
this.pool.Add(c);
}
}
// If a character is being added...
if (this.token != '\0')
{
int i = value.IndexOf(this.token);
this.Password.InsertAt(i, this.secret);
this.secret = '\0';
fake.Insert(i, this.token);
}
}
private void textEditPassword_KeyPress(object sender, KeyPressEventArgs e)
{
if (Char.IsControl(e.KeyChar))
{
this.token = '\0';
}
else
{
this.token = this.pool.ElementAt(random.Next(this.pool.Count)); // throws ArgumentOutOfRangeException when pool is empty
this.pool.Remove(this.token);
this.secret = e.KeyChar;
e.KeyChar = this.token;
}
}
}