1

我有 7 个用户可以输入数字的编辑,数字必须在 1100 到 1500 之间。开始时,第一个编辑是焦点,用户输入他的数字,然后他按下标签来关注下一个编辑。 ..

我的程序必须验证用户输入的号码,如果它不满足条件(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 并且输入的数字不满足条件时,会出现消息,Edit1.Text取 0 并且光标停留在 Edit1 上。

我尝试将条件检查和将焦点放在同一编辑上的指令放在其中,Edit1.OnExit但它不会正常工作,总是当用户在输入不满足条件的数字后按 Tab 时,会出现消息,第一个Edit取0,光标移到下一个Edit。

4

4 回答 4

3

虽然您没有具体说明什么不起作用,但特此给出一些关于为什么不起作用的答案,因为您想要什么很明显。典型用途是输入注册密钥。

  • 您用于StrToFloat将编辑文本转换为数值。由于您希望该值介于11001500之间,因此您应该使用StrToInt,尽管这不是必需的。但是这个函数的使用有一个问题,因为Text空编辑的属性是'',不能转换为数字,会导致一个EConvertError很容易避免的异常。使用TryStrToIntStrToIntDef来防止此错误。

  • 您的条件表达式具有误导性。代替

    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会给用户带来麻烦。当用户想要或想要中止操作时,无论出于何种原因,他都无法这样做,因为在他输入有效数字之前无法到达取消按钮。另一个示例情况是部分输入第二个值,并希望返回到前一个值进行更正。

不要以这种不便的方式骚扰用户。相反,之后验证所有值。中间失效可以通过使用颜色、星号、感叹号、图标等在视觉上发出信号......

于 2013-10-29T19:36:35.790 回答
1

导航键(Tab、BackTab、箭头键等)不受 KeyPreview 的影响,因为它们不会生成键盘事件。
唯一指向这一事实的地方。Delphi 帮助 TCustomForm.KeyPreview

您可以使用的唯一事件是下一个或上一个 TEdit 的KeyUp事件。

在此处查看示例:在 KeyPress 事件中对拦截 TAB 键的回答

于 2013-10-30T15:36:44.233 回答
0

然后他按下标签专注于下一个编辑

这被OnExit事件拦截http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Controls.TWinControl.OnExit

在 Edit1Change 上尝试了此代码,但它不起作用

“不起作用”是什么意思?

它确实有效 - 它不断地将焦点集中在您正在键入文本的编辑上。然而,这是检查更改的糟糕时机:当用户“1100”到“1500”用户最有可能有“100”或“15100”的中间结果时,您的应用程序将通过模式对话框使他的工作崩溃。

您应该避免在编辑时检查,只在编辑后检查。或者您应该以不干扰的非模态方式显示检查结果,以便用户继续编辑。就像在红色和绿色之间改变 TEdit 的背景,或者喜欢使用一些验证器库来添加错误标记。

或者只是使用带有这些最小值、最大值和内置检查的数字编辑器

于 2013-10-29T11:48:37.370 回答
-1

这是一个老问题,但我看不到正确的答案:

切勿在焦点发生变化时操纵焦点。在 OnExit 窗口中开始移动焦点但尚未完成。如果您想因验证而中断焦点更改,请使用“Abort;”

procedure Txy.OnExit()
begin
 if not Validate then
   Abort;
end;

还要确保您没有在 OnClose 事件中操纵焦点,因为它最终会触发活动控件的不需要的 OnExit。

于 2017-02-22T14:20:55.083 回答