我在表单上有两个编辑框,一个用于最小值,另一个用于用户需要输入的最大值。我希望在用户输入值时捕获可能的错误。一个可能的错误是最大值小于最小值。如果发生这种情况,我会提示错误消息。但是,即使用户想要在最小框中输入5并且在最大框中输入100,如果用户在最大框中输入100的“1”,它也会显示错误消息在min框中输入了5。如何允许用户在出现错误消息之前输入整个值?
这是我的代码(我也捕获了其他错误,但只有max< min错误似乎受到影响):
procedure TfrmAnalysisOptions.lbleConstraintsMaxChange(Sender: TObject);
var
I: integer;
Val, ValidEntry: string;
Chr: char;
RangeMin, RangeMax: Double;
const Allowed = ['0'..'9', '.'];
begin
Val := lbleConstraintsMax.Text;
//initialize values
ValidEntry := '';
ConstraintsMaxChange := '';
//value can contain only numerals, and "."
for I := 1 to Length(Val) do
begin
Chr := Val[I];
if not (Chr in Allowed) then
begin
MessageDlgPos('The value entered for the max value of the ' +
'constraint must contain only a numeral, a decimal ' +
'point or a negative sign.',
mtError, [mbOK], 0, 300, 300);
Exit;
end
else ValidEntry := 'OK'; //validity check for this part
end;
//max value cannot be zero or less than the min value
if not TryStrToFloat(Val, RangeMax) then Exit
else if RangeMax = 0 then
begin
MessageDlg('Max value cannot be zero.', mtError, [mbOK], 0);
Exit;
end
else if not TryStrToFloat(lbleConstraintsMin.Text, RangeMin) then Exit
else if RangeMax < RangeMin then
begin
MessageDlgPos('Max value cannot be less than Min value.',
mtError, [mbOK], 0, 300, 300);
Exit;
end
else if (RangeMax < 0) then
begin
MessageDlgPos('A constraint cannot be negative.',
mtError, [mbOK], 0, 300, 300);
Exit;
end
//final validity check
else if ValidEntry = 'OK' then ConstraintsMaxChange := 'OK'
else MessageDlgPos('There was an unexpected problem with the ' +
'value entered in the max constraints box.',
mtError, [mbOK], 0, 300, 300);
end;
答案 0 :(得分:5)
每次修改编辑控件的内容时都会触发OnChange
事件。虽然这是过滤掉无效字符的合适位置,但它不是验证数值的合适位置。无法预测用户打算输入的号码,无论是5
,50
,500
,5,000
,其中每个号码可能是可接受的,也可能是不可接受的。
解决方案1 :在填写完这些编辑控件并且用户尝试进入下一步(保存,继续,加载,启动等)后执行此检查。
解决方案2 :您可以在这些控件旁边显示一个标签,而不是显示消息框,该标签显示&#34;无效条目&#34;同时保持同样的逻辑。这样,用户就不会遇到许多消息框。
解决方案3 :使用OnExit
事件代替OnChange
。请注意,这不会完全解决您的问题,但会将其最小化。当焦点离开控件时会触发此事件。
解决方案4 与解决方案2类似,使用OnChange
和OnExit
来控制用户可能按下的按钮的Enabled
属性。< / p>
解决方案5 与解决方案4类似,使用操作并更改该特定操作的Enabled
属性。然后,无法点击用户可能按下的任何按钮。
另一方面,当您过滤掉无效字符时,忽略这些字符会更加优雅,而不是让它们首先进入控件,而不是弹出一条消息。您可以使用OnKeyPress
事件代替,或使用TMaskEdit
。
答案 1 :(得分:1)
作为OnExit或OnChange的替代方法,我可以建议一种面向对象的模式方法:
TMyBusinessModelObject = class ....
OnExit
个事件。其次,甚至比编写代码来阻止无效字符的TMaskEdit
或TEdit
更好,JVCL中有专门为数字输入设计的控件,包括允许您输入约束的控件在控制层面。
Delphi是一个面向组件的RAD工具,当你像一个人一样使用它时,当你从一开始就避免使用代码隐藏形式(Big Ball of Mud)时,你就不会有一个巨大的混乱以后清理。 (一个相当可悲的事实是,标准德尔菲的做法是做最简单的事情,可能有效,并建立一个巨大的泥球,没有OOP。)