3

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

我正在考虑制作一个变量“x”-> byte,它将计算编辑的长度并删除第一个数字,如果它是 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.

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

这是一个非常愚蠢的问题,因为答案简单明了,但是如果您太累了,很难找到它,很抱歉让您忙于这个问题,Andreas,感谢您的帮助和提示。

4

2 回答 2

10

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

这很好用,我认为:

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从空字符串的状态进入!
  • ifSelStart = 1Text[1] = '0'[if SelStart = 1, thenText[1]存在,所以我们这里依赖布尔短路评估],那么你不能输入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;

我把它作为一个练习来找出这种方法的问题。如果你一一解决问题,当你发现它们时,你最终会得到我上面的长代码!

于 2013-04-24T20:09:24.407 回答
1

您可以使用 TmaskEdit。这迫使用户输入数字。添加 eventchange 后删除第一个数字(如果为 0)。

例子.dfm

.
.
object MaskEdit1: TMaskEdit
  Left = 352
   Top = 8
   Width = 120
   Height = 21
   EditMask = '0999999;0;_'
   MaxLength = 7
   TabOrder = 3
   OnChange = MaskEdit1Change
end
.
.

例子.pas

.
.
Procedure TForm1.MaskEdit1Change(Sender: TObject);
Begin
  If Length(TMaskEdit(Sender).Text) > 1 Then
    TMaskEdit(Sender).Text := IntToStr(StrToInt(TMaskEdit(Sender).Text));
End;
.
.
于 2013-04-25T10:39:41.540 回答