PDA

View Full Version : TEdit and maxLength problem



Wizard
14-03-2008, 10:58 AM
Hi everyone.

Let's say you have the following where edit1.maxLength is set to 2.


if (edit1.Text = '21') and (block.Image = formGame.DXImageList.Items.Find('Block1')) then
begin
pause;
result := True;
player.Moved := true;
end;
if (edit1.Text = '6') and (block.Image = formGame.DXImageList.Items.Find('Block2')) then
begin
pause;
result := True;
player.Moved := true;
end;

Now if the user enters 21 into the edit it works and if the user enters 6 into the edit it also works. But what if the user enters 61 into the edit? It still works because the 6 is recognized but not the 1 after the 6. Let's say the condition is 3x2=6 then 61 will also be accepted, which is false. The maxLength is 2 so the user will allways be able to enter 2 digits into the edit.

I also tried setting the maxLength at the edit.change and edit.exit but it doesn't work. Any ideas?

AthenaOfDelphi
14-03-2008, 12:14 PM
Hi Wizard,

If my understanding is correct, you want to allow a user to enter 21 or 6?

If thats the case... this will do the trick.


procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
valid:boolean;
begin
valid:=false;
if (key in [#8]) then
begin
valid:=true;
end;
if (key in ['1','2','6']) then
begin
if (edit1.text='') and (key in ['2','6']) then
begin
valid:=true;
end
else
begin
if (edit1.text='2') and (key in ['1']) then
begin
valid:=true;
end;
end;
end;

if not valid then
begin
key:=#0;
end;
end;


You basically have to hook the keypress event and validate it yourself. There are possibly other mechanisms like fancy formatted edits, but I've personally not had any success with them and whenever I need specific validation requirements like this, I normally end up doing something like I've given above.

Obvsiously, if you have a lot of different possibilities, then writing a validation routine can be a pain in the ass. So, what you may prefer to do is have some kind of list of stings. As each keypress comes in, look at the possibilities... compare that against what you already have and look to see whether the incoming key is valid. If you need help with something like that, let me know and I'll see if I can knock something together.

Memphis
14-03-2008, 12:39 PM
if (edit1.Text = '6') and (block.Image = formGame.DXImageList.Items.Find('Block2')) then


this condition will not be accepted as 61... i fail to understand the problem

Wizard
14-03-2008, 12:50 PM
Hi Athena, thanks for the reply :-)

Let me explain what I'm busy with. In my game there's about 21 blocks and a player. Each block has a different math problem to solve, if the answer entered into the edit field is correct for that specific block (obstacle) the collision is executed and the player can move on to the next block to answer the next problem.

There is no problem with double digits in the edit box i.e. if the problem is 2x20 then the user enters 40 and then move on.

The problem I'm having is with single digits i.e. 10 - 6, the user then enters 4 and move on. However, if the user enters 41, 46 or whatever the 4 is still recognized.

So what I need is when the answer is a single number the user must only be able to enter a single number in the edit.

All the blocks is part of a list with Block numbers, so I validate the collision on two things: If the player collides with lets say Block1 and the answer given for that specific block is correct (edit.text) then Collision continues and player can move on.

Memphis: It does accept 6, 61 etc. i.e. any digit entered after the 6. Try it, you'll see.

Memphis
14-03-2008, 01:10 PM
@ AthenaOfDelphi > another way to avoid comparing strings etc....



procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
case Key of
#8:
case Tag of
6: Tag := 0;
21: Tag := 2;
else
Tag := 0;
end;
else
case Tag of
0: if Key in [#50, #54] then Tag := Ord(Key)-48 else Key := #0;
2: if Key = #49 then Tag := 21 else Key := #0;
else
Key := #0;
end;
end;
end;


@ Wizard.. ^ the above method will do just that... njoy


*Edit*

from what i see of your code, here is 1 way you could modify this procedure to work.. there is a few differ ways you can do it, but here is 1 quick example


case Key of
#8:
case Tag of
6: Tag := 0;
21: Tag := 2;
else
Tag := 0;
end;
else
case Tag of
0:
case Key of
#50: Tag := 2;
#54: begin //6
if block.Image = formGame.DXImageList.Items.Find('Block2') then begin
pause;
Result := True;
player.Moved := true;
Tag := 0;
Edit1.Clear;
end else
Key := #0;
end;
end;

2:
if (Key = #49) and (block.Image = formGame.DXImageList.Items.Find('Block1')) then begin
pause;
Result := True; //you will need to change the return, as it will be in keypress.
player.Moved := true;
Tag := 0;
Edit1.Clear;
end else begin
Key := #0;
end;
else
Key := #0;
end;
end;


let me know if that works :>

-Meka][Meka

Wizard
14-03-2008, 05:02 PM
Memphis, it works but not the way I need it to. The reason I have pause
(( while (GetTickCount - StartTime) < Duration do application.ProcessMessages;)) is so that the user can see the numbers entered into the edit field. With your solution and with pause you can't see what was entered. Further, once I press 6 and a number after 6 like 7 only 7 is seen on the edit field.

Instead of comparing values entered, is there no way (except edit.maxLength - which doesn't seem to work) to limit the number of characters entered into the edit? I would like to move between 1 and 2 characters (in the code) and if I can achieve that the problem would be solved.

Memphis
14-03-2008, 05:35 PM
is so that the user can see the numbers entered into the edit field. With your solution and with pause you can't see what was entered.

this does allow u to see the numbers... you have totally lost me now lol

from what i understand, this is another problem with your own code.

Wizard
14-03-2008, 05:59 PM
Ok, it works :-) I had edit1.text := '' in my collision procedure. Can you tell me where you get the values #50,#54 and #49? I suppose it's the keyboard mapping? Where can i get a map of the keyboard for other numbers?

Thanks for your help :-)

AthenaOfDelphi
14-03-2008, 06:40 PM
They are standard ASCII character codes.

#48 = ASCII 48 = 0
...
#57 = ASCII 57 = 9
#8 = Backspace (IIRC)



Instead of comparing values entered, is there no way (except edit.maxLength - which doesn't seem to work) to limit the number of characters entered into the edit? I would like to move between 1 and 2 characters (in the code) and if I can achieve that the problem would be solved.


This is relatively easy to do.... just hook the keypress handler and look at the length of the text field. If it is less than the required length (or the key code is a control character like backspace), then leave it as it is, otherwise, set the key value to 0... it will then be ignored, thus stopping the user entering more characters.

Wizard
14-03-2008, 08:08 PM
Guys and girl :-) I knew there must be a simple solution!!!!!

I finally figured it out :-)

procedure TFormGame.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not ( Key in ['0'..'9',#8] ) then
begin
Key := #0;
MessageBeep (MB_ICONEXCLAMATION);
end
else inherited KeyPress(Key);

if (block.Image = formGame.DXImageList.Items.Find('Block2')) //single
or (block.Image = formGame.DXImageList.Items.Find('Block3')) //single
or (block.Image = formGame.DXImageList.Items.Find('Block6')) //single
or (block.Image = formGame.DXImageList.Items.Find('Block8'))// single
and (key in['0'..'9']) then
edit1.MaxLength := 1
else
edit1.MaxLength :=2
end;

And in my RenderPlay:

if (edit1.Text = '21') and (block.Image = formGame.DXImageList.Items.Find('Block1')) then
begin
pause;
result := True;
player.Moved := true;
end;
if (edit1.Text = '6') and (block.Image = formGame.DXImageList.Items.Find('Block2')) then
begin
pause;
result := True;
player.Moved := true;
end;
Now I can be sure that the user is only able to enter single numbers where the answer must be a single number and for the rest double numbers.

:twisted: :twisted: :twisted: :twisted: :twisted: :twisted: :twisted: