我有7个编辑,用户可以输入数字,数字必须介于1100和1500之间。开始时,第一个编辑被聚焦,用户输入他的数字,然后他按Tab键聚焦到下一次编辑...
我的程序必须验证用户所引用的号码以及它是否不满足条件(1100
我在Edit1Change上尝试了这个代码,但它不起作用
If (1500 < (strtofloat(edit1.text)) or (strtofloat(edit1.text) <1100) then
begin
Showmessage ('my message');
edit1.setfocus
end;
对不起,我对问题的描述不是很清楚,我的英语也不是很好。
我没有比较或检查条件的问题,我的问题是当我按TAB选择下一个编辑时,即使条件不满意,我的信息出现,Edit1.Text
是重置为0,光标移动到下一个编辑控件。我想要的是当用户按Tab键并且数字entred不满足条件时,会显示消息,Edit1.Text
取0并且光标停留在Edit1上。
我试图检查条件和指令,以便将焦点放在Edit1.OnExit
中的相同编辑中,但它也不会起作用,总是当用户在输入一个不输入的数字后按Tab键时如果满足条件,则显示消息,第一个Edit取0,光标移动到下一个Edit。
答案 0 :(得分:3)
虽然你没有明确指出无法正常工作,但是有一些答案解释为什么这不起作用,因为它很明显你想要什么。典型用途是输入注册码。
您使用StrToFloat
将编辑文本转换为数字值。由于您希望值介于 1100 和 1500 之间,因此您应该使用StrToInt
,尽管这不是必需的。但是,使用此函数时出现问题,因为空编辑的Text
属性为''
,无法将其转换为数字并导致EConvertError
异常很容易避免。使用TryStrToInt
或StrToIntDef
来防止此错误。
您的条件表达式具有误导性。而不是
if (1500 < A) or (A < 1100) then
使用
if (A < 1100) or (A > 1500) then
很多更具可读性。您还可以使用InRange
单元中的System.Math
功能:
if not InRange(A, 1100, 1500) then
无论你喜欢什么。
您可以在编辑中的每次击键时检查此条件,因为OnChange
会在每次编辑时触发。现在,当您通过键入 1 开始输入正确的数字时,条件将被评估为true(消息将弹出(但我知道这是一个临时调试功能)),编辑将是集中精力。但它已经存在,所以这是不必要的。
当您按 TAB 选择下一个编辑控件时,OnChange
事件将不会触发,因为除了失去焦点之外没有任何变化。解决方案是检查OnExit
事件中的条件。这也是前一个评论的解决方案。
依赖OnExit
验证的一个缺点是,在对话框关闭的情况下,该事件可能不会触发。但这可能会或不会成为问题,因为退出带有 ESC 的对话框或对话框的关闭按钮,通常表示您正在取消操作。但请记住。
因此,直观的实施将解决各种问题。将所有这些事件处理程序链接到所有编辑控件:
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;
您也可以将NumbersOnly
属性设置为True,这会在有人试图输入字母字符时导致Windows警告气球。
在OnExit
中单独验证每个编辑都会给用户带来麻烦。当用户想要或决定中止操作时,无论出于何种原因,他都无法进行操作,因为无法访问取消按钮,直到他输入有效数字。另一个示例情况是部分输入第二个值,并希望返回到前一个值进行更正。
请勿以此类不便骚扰用户。相反,之后验证所有值。可以使用颜色,星星,感叹号,图标等在视觉上发出中间失效信号......
答案 1 :(得分:0)
然后他按Tab键聚焦到下一个编辑
OnExit
事件http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Controls.TWinControl.OnExit
在Edit1Change上尝试了这个代码,但它不起作用
“不起作用”是什么意思?
它确实有效 - 它不断地将焦点设置为您将文本键入的编辑。 然而,这是检查更改的不好时间:当用户“1100”到“1500”用户最可能具有“100”或“15100”的中间结果时,您的应用程序将通过模态对话框使其工作崩溃。
您应该在编辑时避免检查,并且仅在编辑后进行检查。或者您应该以非干扰的非模态方式显示检查结果,以便用户继续编辑。就像在红色和绿色之间更改TEdit的背景或者像使用一些验证器库来添加错误标记一样。
或者只使用带有min,max和内置检查的数字编辑器
答案 2 :(得分:0)
导航键(标签,BackTab,箭头键等)不受KeyPreview的影响,因为它们不会生成键盘事件。
唯一指向这一事实的地方。 Delphi Help TCustomForm.KeyPreview
您可以使用的唯一事件是以下或之前的TEdit的 KeyUp 事件。
在这里查看示例:回答Intercept TAB key in KeyPress event
答案 3 :(得分:0)
这是一个古老的问题,但我无法看到正确的答案:
在焦点正在改变的同时,切勿操纵焦点。 在OnExit窗口开始移动焦点但尚未完成。 如果由于验证而想要中断焦点更改,请使用&#34; Abort;&#34;
procedure Txy.OnExit()
begin
if not Validate then
Abort;
end;
还要确保您没有在OnClose事件中操纵焦点 因为它最终会触发活动控件的不需要的OnExit。