将焦点设置为Delphi xe2上的选项卡后的编辑

时间:2013-10-29 11:25:12

标签: delphi delphi-xe2 setfocus

我有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。

4 个答案:

答案 0 :(得分:3)

虽然你没有明确指出无法正常工作,但是有一些答案解释为什么这不起作用,因为它很明显你想要什么。典型用途是输入注册码。

  • 您使用StrToFloat将编辑文本转换为数字值。由于您希望值介于 1100 1500 之间,因此您应该使用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(消息将弹出(但我知道这是一个临时调试功能)),编辑将是集中精力。但它已经存在,所以这是不必要的。

  • 当您按 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。