虽然您没有具体说明什么不起作用,但特此给出一些关于为什么不起作用的答案,因为您想要什么很明显。典型用途是输入注册密钥。
您用于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,(消息将弹出(但我知道这是一个临时调试功能)),并且 Edit 将设置为焦点。但它已经是,所以这是不必要的。
当您通过按 选择下一个 Edit 控件时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
会给用户带来麻烦。当用户想要或想要中止操作时,无论出于何种原因,他都无法这样做,因为在他输入有效数字之前无法到达取消按钮。另一个示例情况是部分输入第二个值,并希望返回到前一个值进行更正。
不要以这种不便的方式骚扰用户。相反,之后验证所有值。中间失效可以通过使用颜色、星号、感叹号、图标等在视觉上发出信号......