delphi - 如何使编辑控件不接受 0 作为第一位数字?

标签 delphi delphi-7

嗯,我有一个只需要数字的编辑(没有字母,没有符号,只有数字)。问题是我不希望用户将 0 作为第一个数字,例如(0239847)。

我正在考虑创建一个变量“x”-->字节,它将计算编辑的长度并删除第一个数字(如果它是0):

var l:length; number:string100;
begin
l:length(edit1.text);

现在,如果第一个数字是 0 (0239847),则将其删除,但如果没有其他数字(只有 0),则保持原样。

天哪,我终于找到了最简单的方法:

procedure TForm1.Edit1Change(Sender: TObject);
var digit1:string;
begin
digit1:=edit1.Text;
if (digit1='00') or (digit1='01') or (digit1='02') or (digit1='03') or (digit1='04') or
(digit1='05') or (digit1='06') or (digit1='07') or (digit1='08') or (digit1='09') then
edit1.Text:=clear;    //or edit1.text:=0;  it's the same

end;

end.

仍然可以复制和粘贴数字,但我不介意

这是一个非常愚蠢的问题,因为答案很简单也很明显,但如果你太累了,就很难找到它,我很抱歉让你为此忙碌,安德烈亚斯,感谢你的帮助和提示。

最佳答案

要做好这一点很难。最雄心勃勃的方法是在按键、粘贴等方面执行大量逻辑,就像 this answer 中一样。您会惊讶地发现有多少案件需要处理!

我认为这非常有效:

type
  TEdit = class(StdCtrls.TEdit)

...

procedure TEdit.KeyPress(var Key: Char);

  function InvalidKey: boolean;
  begin
     InvalidKey :=
       (
         (Key = '0') and
           (
             ((SelStart = 0) and (Length(Text) - SelLength <> 0))
             or
             ((SelStart = 1) and (Text[1] = '0'))
           )
       )
       or
       (
         not (Key in ['0'..'9', #8, ^Z, ^X, ^C, ^V])
       )
  end;

begin
  inherited;

  if InvalidKey then
  begin
    beep;
    Key := #0;
  end else if (SelStart = 1) and (Text[1] = '0') then
  begin
    Text := Copy(Text, 2);
  end;
end;

procedure TEdit.WMPaste(var Message: TWMPaste);    
var
  ClipbrdText: string;

  function ValidText: boolean;
  var
    i: Integer;
  begin
    result := true;
    for i := 1 to Length(ClipbrdText) do
      if not (ClipbrdText[i] in ['0'..'9']) then
      begin
        result := false;
        break;
      end;
  end;

  function RemoveLeadingZeros(const S: string): string;
  var
    NumLeadingZeros: integer;
    i: Integer;
  begin
    NumLeadingZeros := 0;
    for i := 1 to Length(S) do
      if S[i] = '0' then
        inc(NumLeadingZeros)
      else
        break;
    result := Copy(S, NumLeadingZeros + 1);
  end;

begin
  if Clipboard.HasFormat(CF_TEXT) then
  begin

    ClipbrdText := Clipboard.AsText;

    if not ValidText then
    begin
      beep;
      Exit;
    end;

    if SelStart = 0 then
      ClipbrdText := RemoveLeadingZeros(ClipbrdText);

    SelText := ClipbrdText;

  end
  else
    inherited;
end;

这看起来很复杂,但所有这些逻辑都是必要的。例如,代码可以很好地处理所有这些情况:

  • 您只能输入数字。

  • 如果SelStart = 0并且不是每个字符都被选中,则不能输入0,因为那样你会得到一个前导零。

  • 如果SelStart = 0并且选择了每个字符,您可以输入0。因为您应该能够输入这个有效号码。

    • 特殊情况:如果有零个字符,那么当然会选择零个字符,因此通过简单的逻辑,您能够从状态输入0空字符串!
  • 如果 SelStart = 1Text[1] = '0' [if SelStart = 1,则 Text[1]存在,所以我们这里依靠 bool 短路求值],那么你就不能输入0

  • 如果编辑字段的内容为 0 并且您在零后添加一个非零字符,则零将被删除(并且不会干扰插入符号位置) .

  • 您只能粘贴数字。如果SelStart = 0,则丢弃前导零(在剪贴板数据中)。

事实上,为了使行为变得完美,您需要更多代码。例如,假设编辑字段的内容是123000456。现在,您可以选择前三个字符 (123),然后按 BackspaceDelete 来获取无效文本 000456 。解决方案是添加额外的代码来删除这两个操作中的任何一个所产生的前导零。 更新:我一直在思考,并意识到最好实现这个(为什么?)。

然而,一个捷径是在未聚焦时“美化”编辑的内容,因为当未聚焦时,您不太可能通过使用编辑内容。

例如,您可以执行类似的操作

function PrettifyNumber(const S: string): string;
var
  NumLeadingZeros: integer;
  i: Integer;
begin
  NumLeadingZeros := 0;
  for i := 1 to Length(S) do
    if S[i] = '0' then
      inc(NumLeadingZeros)
    else
      break;
  result := Copy(S, NumLeadingZeros + 1);
  if length(result) = 0 then
    result := S;
end;

然后在失去键盘焦点时用其美化版本替换编辑字段的内容。当然,您应该考虑将此功能添加到派生编辑类中,但为了进行测试,您可以简单地使用 OnExit 事件:

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  Edit1.Text := PrettifyNumber(Edit1.Text);
end;

我想您希望在主要应用程序(或不那么主要)的大量编辑中使用此功能。因此,您实际上将编写自己的子类化控件。那么我想您还需要其他类型的验证,而不仅仅是删除前导零?因此,您必须将此代码与其余代码很好地集成。如果事实上您将在大型应用程序中的任何地方使用此编辑“子类”,您还可以考虑向编辑控件类添加快捷方式,以便您可以根据需要美化/验证文本,而不仅仅是在退出时(这如果编辑控件单独存在于其窗体上,则特别困难!)

更新

根据要求,这是一个效果不佳的简单解决方案:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = '0') and (Edit1.SelStart = 0) then Key := #0;
end;

我将其作为练习来找出这种方法的问题。如果您在发现问题时一一解决这些问题,您将得到上面我的长代码!

关于delphi - 如何使编辑控件不接受 0 作为第一位数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16201121/

相关文章:

delphi - 文档Delphi DLL导出

delphi - 如何引用在运行时而不是在表单设计器中创建的组件?

delphi - getwindowtext 不检索文本

delphi - 如果 Windows/Delphi/IDE 暗示小端顺序,我如何从大端二进制文件中读取整数?

delphi - 在 Delphi 7 中从字符串中去除非字母数字字符的最快方法是什么?

web-services - 如何在 THTTPRIO 中设置反馈?

delphi - 将旧的 Delphi 7 代码迁移到 Delphi XE - 未找到 QForms.dcu

delphi - TFrame 内的事件处理程序?

delphi - Spring4D 无法对有序字典进行排序

Delphi 7 企业版或 Delphi 2010 专业版