Reputation: 11
I have 7 edits where the user can put numbers,the numbers must be between 1100 and 1500. At the beginning, the first edit is focused, and the the user enter his number, and then he push tab to focus to the next edit...
My program must verify the number that was entred by the user and if it dont satisfy the condition (1100
I tried this code on the Edit1Change but it won't work
If (1500 < (strtofloat(edit1.text)) or (strtofloat(edit1.text) <1100) then
begin
Showmessage ('my message');
edit1.setfocus
end;
Excuse me guys, my description for the problem wasn't very clear, and my english is not very good as well.
I don't have problem with the comparison or checking the condition, my problem is that when I select the next Edit by pressing TAB, even if the condition wasn't satisified, my message appears, Edit1.Text
is reset to 0 and the cursor moves to the next Edit control. What I want is that when the user presses Tab and the number entred doesn't satisfy the condition, the message appears, Edit1.Text
takes 0 and the cursor stays on Edit1.
I tried to place the checking of the condition and the instruction to give focus to the same edit in Edit1.OnExit
but it won't work as well, always when the user presses Tab after entering a number that doesn't satisfy the condition, the message appears, the first Edit takes 0 and the cursor moves to the next Edit.
Upvotes: 1
Views: 20140
Reputation: 132
It's an old question but as i can't see the right answer:
Never manipulate focus meanwhile the focus is changing. In OnExit windows started to move the focus but didn't finished yet. If you want to interrupt the focus change because of validation, use "Abort;"
procedure Txy.OnExit()
begin
if not Validate then
Abort;
end;
Also make sure that you are not manipulating the focus in the OnClose event because it will eventually trigger an unwanted OnExit of the active control.
Upvotes: -1
Reputation: 16045
then he push tab to focus to the next edit
That is intercepted by OnExit
event http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Controls.TWinControl.OnExit
tried this code on the Edit1Change but it won't work
What do you mean by "does not work" ?
It actually works - it continually sets focus to the edit you are keying text into. However that is bad time to check for changes: when user "1100" to "1500" user most probably have intermediate result of "100" or "15100" where your application would crash his work by modal dialogs.
You should either avoid checking while editing and only check after edit made. Or you should display result of the check in a non-interfering non-modal way, so the user would continue editing. Like changing TEdit's background between red and green or like using some validators library to add error marks.
Or just use the numeric editor with those min, max and checks built-in
Upvotes: 0
Reputation: 11968
Navigation keys (Tab, BackTab, the arrow keys, and so on) are unaffected by KeyPreview because they do not generate keyboard events.
The only place which points to this fact. Delphi Help TCustomForm.KeyPreview
The only event you can use is the KeyUp Event of the following or previous TEdit.
Look here for an example : Answer to Intercept TAB key in KeyPress event
Upvotes: 1
Reputation: 43649
Although you do not specify exactly what does not work, hereby some answers on why this does not work, because it is pretty obvious what you want. Typical use is entering a registration key.
You use StrToFloat
to convert the Edit text into a numeric value. Since you want the value to be between 1100 and 1500, you should use StrToInt
, although that is not necessary. However, there is a problem with the use of this function, because the Text
property of an empty edit is ''
, which cannot be converted to a number and would cause an EConvertError
exception that can easily be avoided. Use TryStrToInt
or StrToIntDef
to prevent this error.
Your conditional expression is misleading. Instead of
if (1500 < A) or (A < 1100) then
use
if (A < 1100) or (A > 1500) then
which is much more readable. You can also use the InRange
function from the System.Math
unit:
if not InRange(A, 1100, 1500) then
whatever you prefer.
You check this condition on every keystroke in the Edit, because OnChange
fires on every single edit. Now, when you start entering a correct number by typing 1, the condition will be evaluated true, (the message will popup (but I understand that is a temporarily debugging feature)), and the Edit will be set focussed. But it already was, so that is unnecessary.
When you select the next Edit control by pressing TAB, the OnChange
event will not fire, because nothing changed besides losing focus. The solution is to check the condition in the OnExit
event. This is the solution for the previous remark as well.
A drawback of relying on validation in OnExit
is that that event might not fire in case of dialog closure. But that could or would not be a problem because exiting a dialog with ESC or the dialog's close button, typically indicates that you are cancelling the operation. But remember.
Hereby an intuitive implementation that will solve various concerns. Link all these event handlers to all Edit controls:
const
MinValue = 1100;
MaxValue = 1500;
procedure TForm1.EditChange(Sender: TObject);
var
Edit: TEdit absolute Sender;
begin
if Length(Edit.Text) = 4 then
SelectNext(Edit, True, True);
end;
procedure TForm1.EditEnter(Sender: TObject);
var
Edit: TEdit absolute Sender;
begin
Edit.SelStart := Length(Edit.Text);
end;
procedure TForm1.EditExit(Sender: TObject);
var
Edit: TEdit absolute Sender;
begin
if not InRange(StrToIntDef(Edit.Text, -1), MinValue, MaxValue) then
Edit.SetFocus;
end;
procedure TForm1.EditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Edit: TEdit absolute Sender;
begin
if (Edit <> Edit1) and (Length(Edit.Text) = 0) and (Key = VK_BACK) then
begin
Edit.OnExit := nil;
SelectNext(Edit, False, True);
Edit.OnExit := EditExit;
end;
end;
You also might set the NumbersOnly
property to True which will cause a Windows warning balloon when someone tries to enter an alphabetic character.
Validating every Edit seperately in OnExit
will cause trouble for the user. When the user wants or desides to abort the operation, for whatever reason, he is not able to because the cancel button cannot be reached untill he enters a valid number. Another example situation would be entering second value partially, and wanting to return to the previous for correction.
Do not harass users with such inconvenience. Instead, validate all values afterwards. Intermediate invalidation could be visually signalled by using colors, stars, exclamation marks, icons, etc...
Upvotes: 3