Hi.
I have a password input text box and would like it to replace all the characters as typed with asterisks.
My question is: how does AGS process key presses, how can I stop it, and how can I simulate it?
i.e. How do I make it ignore a key that has been pressed, and register a different key that hasn't?
I have tried doing a straight swap with
if (keycode>='A' && keycode<='Z') keycode=42;
but the text box just displays what was typed.
I also tried maybe swapping the chars after the fact with
tempstring.AppendChar(42); txtPassword.Text=tempstring;
but that does absolutely nothing. The text still displays as normal.
I have no idea what else I can try. Any ideas?
Thanks in advance.
Textbox behavior is hardcoded, you have to do everything manually.
Basically, you'd want to do something in rep_exec_always:
String password;
function repeatedly_execute_always()
{
if (txtPassword.Enabled)
{
char c = 'A';
while (c <= 'Z')
{
if (IsKeyPressed(c))
{
if (password == null) password = "";
password = password.AppendChar(c);
c = 'Z';
}
c++; // hah! :)
}
if (IsKeyPressed(eKeyBackspace)) password = password.Truncate(password.Length - 1);
txtPassword.Text = "";
int i = 0;
while (i < password.Length)
{
txtPassword.Text = txtPassword.Text.AppendChar(42);
i++;
}
}
}
..to be honest, I haven't actually tested that, so you also might not be able to use TextBox.Enabled, and might have to code that as well (store it in a global bool, use it in place of txtPassword.Enabled, and then in rep_exec append a '_' if it is enabled).
Ugh. I keep forgetting that string.Append and string.Truncate are passive. I think it's because they're present-tense verbs, so it implies they actually do something.
Also, I didn't know you could directly use GUIControl.Text.Append, hence the tempstring.
Anyway, I'm going to keep it simple for now.
function repeatedly_execute {
if (txtPassword.Enabled)
{
if (txtPassword.Text.Length!=0) {
txtPassword.Text=txtPassword.Text.Truncate(txtPassword.Text.Length-1);
txtPassword.Text=txtPassword.Text.AppendChar(42);
}
}
}
It's basically what I was trying before, but in rep_exec instead of hoping it would trigger via on_key_press like I had it.
Downside is that the last letter typed is visible for a loop before becoming an asterisk, so I'll probably swap txtPassword for a regular label that just mimics a text box at some point, but this works well enough for the time being.
Thanks guys.
Well glad you got that working for you, but at the very least shouldn't you be storing the raw text into a separate String so you can actually read it? Otherwise at the end you'd just have a bunch of asterisks with no way of telling which characters were originally typed in. For that you'd need to also add an additional check (probably just comparing the length against the last loop) otherwise you'd be repeatedly adding the last character to the String.
Oh, and when it comes to String functions, you have to keep in mind that the storage used internally is read-only. So if you're changing the text of a String in any way, you have to reassign the pointer to the newly created String.
Quote from: monkey_05_06 on Sun 03/04/2011 16:00:00
Well glad you got that working for you, but at the very least shouldn't you be storing the raw text into a separate String so you can actually read it?
That's where our old friend tempstring returns.
Here's the complete working code so far. I've now hidden txtPassword and replaced it with lblPass.
function repeatedly_execute {
int place=txtPassword.Text.Length-1;
if (txtPassword.Enabled) {
if (txtPassword.Text.Length!=0) {
if (txtPassword.Text.Chars[place]!=42) {
tempstring=tempstring.AppendChar(txtPassword.Text.Chars[place]);
txtPassword.Text=txtPassword.Text.ReplaceCharAt(place, 42);
lblPass.Text=txtPassword.Text.AppendChar(95);
}
if (tempstring.Length-1>place) {
tempstring=tempstring.Truncate(place+1);
lblPass.Text=txtPassword.Text.AppendChar(95);
}
if (lblPass.Text.Chars[place+1]!=95) lblPass.Text=lblPass.Text.AppendChar(95);
}
else {
tempstring="";
lblPass.Text="_";
}
}
else if (lblPass.Text.Chars[place+1]==95) lblPass.Text=lblPass.Text.Truncate(place+1);
}
I still have two issues, though...
1) Is there a way to further simplify this at all? In particular, I'm pretty sure I don't need the
AppendChar(95) bit in three different places (four including
lblPass.Text="_"), or to check
lblPass.Text.Chars[place+1] twice.
2) The regular underscore on the label looks really thin and weedy next to one used in the real text box. Is there a way to beef it up at all? I use text boxes elsewhere in the game, and I'd rather not have to replace them all with labels just to make them match. Or to have to base my choice of font entirely around that one character.
EDIT:New approach, a lot simpler. I realised that only lblPass.Text needs to be obscured, and as long as txtPassword is hidden it can be left clean, which also means that tempstring is once again unnecessary.
function repeatedly_execute {
int place=lblPass.Text.Length-1;
if (txtPassword.Enabled) {
if (lblPass.Text.Chars[place]!=95) lblPass.Text=lblPass.Text.AppendChar(95);
else {
if (txtPassword.Text.Length>place) {
if (lblPass.Text.Chars[place]==95) lblPass.Text=lblPass.Text.Truncate(place);
lblPass.Text=lblPass.Text.AppendChar(42);
}
else if (txtPassword.Text.Length<place) {
lblPass.Text=lblPass.Text.Truncate(place-1);
}
}
}
else if (lblPass.Text.Chars[place]==95) lblPass.Text=lblPass.Text.Truncate(place);
}
Issue 2 still applies, though. Any ideas?
Thanks again.
I didn't read the whole thread, but a quick test revealed the underscore to look exactly alike on a label and in a textbox. Are you talking about the textbox cursor?
And you can always edit the font and make the underscore bigger.