Text限制用户输入

 

(一)TEdit、TDBEdit、TComboBox、TDBComboBox的输入分三种类型限制:
(1)任意输入
(2)整数输入
(3)浮点数输入
限制的项目如下:
(1)整数输入只能输入数字0-9、+、-
(2)浮点输入只能输入数字0-9、+、-、.
(3)+和-只能有其一,并且只能出现在最前面
(4).只能有一个
(5)限制小数位数
函数如下:
procedure MxFormatKeyPress(Text:string;SelStart,SelLength:integer; var Key:Char;EditType:integer;Digits:integer);
begin
    if (Key=#27) or (Key=#8) or (EditType=1) then exit;


    if EditType=2 then if not (Key in ['0'..'9','+','-'] ) then Key:=#0;


    if EditType=3 then if not (Key in ['0'..'9','+','-','.'] ) then Key:=#0;
   

    //控制+-
    if (Key ='-') or (Key='+' ) then begin
      if ((Pos('-',Text) > 0) or (Pos('+',Text) > 0 )) and (SelLength=0 ) then Key:=#0;
      if SelStart > 0 then Key:=#0;
    end;


    //控制.
    if (Key = '.') and (EditType=3 ) then begin
      if (Pos('.',Text) > 0) and (not((SelStart=Pos('.',Text) ))) then Key:=#0;
     

  if SelStart=0 then Key:=#0;
     

  if (Digits>0) and (SelStart+SelLength0) and (EditType=3) then
     

  if (pos('.',Text )>0 ) and (SelStart>=pos('.',Text)) then if length(Text)-pos('.',Text )>=Digits then Key:=#0;
end;

此函数在所限制组件的OnKeyPress事件中调用。

Key即为OnKeyPress携带的Key:Char参数;

EditType为限制的类型:1-任意输入;2-整数输入;3-浮点输入;

Digits为浮点数输入时小数的位数,如果是零,则可输入任意位数。另外,此函数只适用于有Text、SelStart、SelLength等属性的TWinControl类的派生类。具体限制各组件的二级函数如下:

限制TEdit、TDBEdit:
procedure MxFormatEditKeyPress(Edit:TCustomEdit;var Key:Char;EditType:integer; Digits:integer);
begin
    MxFormatKeyPress(Edit.Text,Edit.SelStart,Edit.SelLength,Key,EditType,Digits);
end;

限制TComboBox:
procedure MxFormatComboKeyPress(Combo:TComboBox;var Key:Char;EditType:integer; Digits:integer);
begin
    MxFormatKeyPress(Combo.Text,Combo.SelStart,Combo.SelLength,Key,EditType,Digits);
end;

限制TDBComboBox:
procedure MxFormatDBComboKeyPress(Combo:TDBComboBox;var Key:Char; EditType:integer;Digits:integer);
begin
    MxFormatKeyPress(Combo.Text,Combo.SelStart,Combo.SelLength,Key,EditType,Digits);
end;

调用示例:

假如Form1上有一ComboBox1,让用户只输入浮点数,并且小数位数为两位。则可以在ComboBox1的OnKeyPress事件中调用上面的函数:
procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
begin
    MxFormatComboKeyPress(Combobox1,Key,3,0);
end;

如果你的窗体上有多各TComboBox,并且限制类型一致,则不必每个TComboBox都
书写代码,只需为其中一个编写事件处理代码,其它作连接即可。
procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
begin
    MxFormatComboKeyPress(Sender as TComboBox,Key,3,0);
end;
其它组件调用方法同上。

(二)时间的输入
限制类型:
(1)时分
(2)时分秒
组件采用TMaskEdit,数据敏感采用TDBEdit。
限制项目如下:
(1)小时只能输入0-23
(2)分钟不超过59
(3)秒不超过59
(4)用户只能全删,而不能只删某一位数据
(5)箭头键可以更改时间
需要在组件的OnKeyPress和OnKeyDown事件中分别书写代码。

procedure MxFormatTimeKeyPress(ctl:TCustomMaskEdit;TimeFormat:integer;
          var Key:Char;dts:TDataSource);
var
    TextSave:string;
    EditingPos:integer;//1-h 2-m 3-s
    i:integer;
    NumChars:set of Char;
    SelStartSave,SelLengthSave:integer;
    CharValid:boolean;
begin
    NumChars:=['0'..'9'];
    if Key=^V then Key:=#0;
    if not (Key in NumChars ) then exit;
    TextSave:=ctl.Text;
    SelStartSave:=ctl.SelStart;
    SelLengthSave:=ctl.SelLength;
    case ctl.SelStart of
      0,1: EditingPos:=1;
      3,4: EditingPos:=2;
      6,7: EditingPos:=3;
      else EditingPos:=0;
    end;
    ///////////////////////////////////////
    CharValid:=true;
    case EditingPos of
      1: begin
        if SelStartSave=0 then begin
          if not (Key in ['0'..'2']) then CharValid := False;
          if (Key ='2' )    and (TextSave[2] in ['4'..'9']) then
            CharValid:=false;
        end;
        if (SelStartSave = 1) and (TextSave[1] = '2') and
                (not (Key in ['0'..'3'])) then CharValid := False;
      end;
      2: if (SelStartSave = 3) and not (Key in ['0'..'5']) then CharValid := False;
      3: if (SelStartSave = 6) and not (Key in ['0'..'5']) then CharValid := False;
    end;
    if not CharValid then begin
      Key:=#0;exit;
    end;
    if dts<>nil then dts.DataSet.Edit;
    if not (SelStartSave in [2,5]) then TextSave[SelStartSave+1]:=Key;
    if SelLengthSave>1 then begin
      for i:=SelStartSave+2 to SelStartSave+SelLengthSave do
        if i in [1,2,4,5,7,8] then TextSave[i]:='0';
      SelLengthSave:=1;
    end;
    for i:=1 to length(TextSave) do
      if (i in [1,2,4,5,7,8]) and (not (TextSave[i] in NumChars ) ) then
        TextSave[i]:='0';
    ////////////////////////////////////
    if SelStartSave in [1,4] then
      SelStartSave :=SelStartSave+2
    else if SelStartSave=length(TextSave)-1 then
      SelStartSave :=SelStartSave
    else SelStartSave :=SelStartSave+1;
    /////////////////////////////////////
    ctl.Text :=TextSave;
    ctl.SelStart :=SelStartSave;
    ctl.SelLength :=SelLengthSave;
    Key:=#0;
end;

//此函数分割时间,因为有时候会遇到非法的时间字符串,所以不采用DecodeTime。
function MxSplitStr(SourceStr,SplitStr:string;var ResultArray:array of string):integer;
var
    i:integer;
    strTmp:string;
begin
    strTmp:=SourceStr;
    i:=0;
    while pos(SplitStr,strTmp)>0 do begin
      ResultArray[i]:=copy(strTmp,1,pos(SplitStr,strTmp)-1);
      strTmp:=copy(strTmp,pos(SplitStr,strTmp)+length(SplitStr),length(strTmp)-
          pos(SplitStr,strTmp));
      i:=i+1;
    end;
    ResultArray[i]:=strTmp;
    result:=i+1;
end;
//此函数检查字符串是否为合法的时间
function TimeValid(TimeStr:string;TimeFormat:integer):boolean;
var
h,m,s:string;
ary:array[0..2] of string;
SplitRet:integer;
i:integer;
begin
    result:=true;
    SplitRet:=MxSplitStr(TimeStr,':',ary);
    if SplitRet<2 then begin
      result:=false; exit;
    end;
    for i:=0 to 2 do begin
      if length(ary[i])>2 then begin
        result:=false; exit;
      end;
      ary[i]:=trim(ary[i]);
    end;
    h:=ary[0];m:=ary[1];
    if TimeFormat=3 then s:=ary[2];
    ///////////////////////////////
    if (h='') or (strtoint(h)>23 ) then begin
      result:=false; exit;
    end;
    if (m='' ) or (strtoint(m)>59) then begin
      result:=false; exit;
    end;
    if (TimeFormat=3) then
      if (s='') or (strtoint(s)>59) then begin
        result:=false; exit;
      end;
end;
//此函数对时分秒进行加减运算
function IncTime(ATime: TDateTime; Hours, Minutes, Seconds,
    MSecs: Integer): TDateTime;
begin
    Result := ATime + (Hours div 24) + (((Hours mod 24) * 3600000 +
      Minutes * 60000 + Seconds * 1000 + MSecs) / MSecsPerDay);
    if Result < 0 then Result := Result + 1;
end;
//时分秒加减运算的二级函数
function TimeAdd(TimeStr:string;TimeFormat:integer;
          HStep,MStep,SStep:integer):string;
var
    dt:Tdatetime;
begin
    if not TimeValid(TimeStr,TimeFormat) then
      if TimeFormat=2 then begin result:='00:00'; exit; end
      else begin result:='00:00:00';exit; end;
    dt:=strtotime(TimeStr);
    if TimeFormat=2 then
      result:=FormatDateTime('hh:mm',IncTime(dt,HStep,MStep,SStep,0))
    else
      result:=FormatDateTime('hh:mm:ss',IncTime(dt,HStep,MStep,SStep,0))
end;
//限制组件的OnKeyDown
procedure MxFormatTimeKeyDown(ctl:TCustomMaskEdit;TimeFormat:integer;
          var Key:word;Shift: TShiftState;dts:TDataSource);
var
    TextSave:string;
    SelStartSave,SelLengthSave:integer;
    EditingPos:integer;//1-h 2-m 3-s
    i:integer;
begin
    if (ssShift in Shift) and (Key<>vk_delete ) then exit;
    if not (Key in [vk_delete,vk_back,vk_up,vk_down] ) then exit;
    if (dts<>nil ) and (not dts.DataSet.Active    ) then exit;
    if (dts<>nil) and (not dts.DataSet.Modified ) then
      dts.DataSet.Edit;
    //////////////////////////////////////
    TextSave:=ctl.Text;
    SelStartSave:=ctl.SelStart;
    SelLengthSave:=ctl.SelLength;
    case SelStartSave of
      0,1: EditingPos:=1;
      3,4: EditingPos:=2;
      6,7: EditingPos:=3;
      else EditingPos:=0;
    end;
    if SelStartSave=length(TextSave) then
      EditingPos:=TimeFormat;
    if Key=vk_delete then begin
      if SelLengthSave=length(TextSave) then TextSave:=''
      else begin
        if not (SelStartSave in [2,5]) then TextSave[SelStartSave+1]:='0';
        if SelLengthSave>1 then begin
          for i:=SelStartSave+2 to SelStartSave+SelLengthSave do
            if i in [1,2,4,5,7,8] then TextSave[i]:='0';
          SelLengthSave:=1;
        end;
      end;
      Key:=0;
    end;
    if Key=vk_back then begin
      if SelLengthSave=length(TextSave) then TextSave:=''
      else if SelLengthSave<=1 then begin
        if not (SelStartSave in [3,6]) then begin
          TextSave[SelStartSave]:='0';
          SelStartSave:=SelStartSave-1;
        end else begin
          TextSave[SelStartSave-1]:='0';
          SelStartSave:=SelStartSave-2;
        end;
        SelLengthSave:=1;
      end else begin
        for i:=SelStartSave+1 to SelStartSave+SelLengthSave do
          if i in [1,2,4,5,7,8] then TextSave[i]:='0';
        SelLengthSave:=1;
      end;
      Key:=0;
    end;
    ///////////////////////////////////////
    if (Key=vk_up) or (Key=vk_down ) then begin
      if trim(TextSave)=':' then begin
        if TimeFormat=2 then TextSave:='00:00'
        else TextSave:='00:00:00'
      end else begin
        if Key=vk_up then
          case EditingPos of
            1: TextSave:=TimeAdd(TextSave,TimeFormat,1,0,0);
            2: TextSave:=TimeAdd(TextSave,TimeFormat,0,1,0);
            3: TextSave:=TimeAdd(TextSave,TimeFormat,0,0,1);
          end;
        if Key=vk_down then
          case EditingPos of
            1: TextSave:=TimeAdd(TextSave,TimeFormat,-1,0,0);
            2: TextSave:=TimeAdd(TextSave,TimeFormat,0,-1,0);
            3: TextSave:=TimeAdd(TextSave,TimeFormat,0,0,-1);
          end;
      end;
    end;
    ///////////////////////////////////////
    ctl.Text :=TextSave;
    ctl.SelStart :=SelStartSave;
    ctl.SelLength :=SelLengthSave;
end;
以上函数的TimeFormat参数代表时间的类型:1-时:分;2-时:分:秒
要完成对时间的输入限制,只需调用上面的MxFormatTimeKeyPress,
MxFormatTimeKeyDown两个函数。
调用示例:
(1)TMaskEdit
procedure TForm1.MaskEdit1KeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
begin
    MxFormatTimeKeyDown(Sender as TCustomMaskEdit,2,Key,Shift,nil);
end;

procedure TForm1.MaskEdit1KeyPress(Sender: TObject; var Key: Char);
begin
    MxFormatTimeKeyPress(Sender as TCustomMaskEdit,2,Key,nil);
end;
并且,TMaskEdit的EditMask属性设为'99:99'
(2)TDBEdit

procedure TForm1.DBEdit1KeyPress(Sender: TObject; var Key: Char);
begin
    MxFormatTimeKeyPress(Sender as TCustomMaskEdit,2,Key,(Sender as TDBEdit).DataSource);
end;

procedure TForm1.DBEdit1KeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
begin
    MxFormatTimeKeyDown(Sender as TCustomMaskEdit,2,Key,Shift,(Sender as TDBEdit).DataSource);
end;
在TDBEdit所连接的数据源打开后,设定所连字段的EditMask属性为99:99:
    DBEdit1.Field.EditMask :='99:99';

(三)日期的输入
采用Rx的日期组件TDateEdit、TDBDateEdit。如果你还没安装,请在本站下载。
无需对日期的输入作限制,只需方便用户的输入。即:箭头键可以改变相应的
日期元素,因为Rx五次功能。函数如下:
procedure MxSpinRxDateEdit(Edit:TCustomDateEdit;Key:word;Shift:TShiftState;
          dts:TDataSource);
var
    DateStr,Mark,str:string;
    MarkPos1,MarkPos2:integer;
    DateOrd:TDateOrder;
    DateFlag,step:integer;
    OldSelStart:integer;
begin
    if Shift<>[] then exit;
    if not (Key in [vk_up,vk_down] ) then exit;
    if (dts<>nil ) and (not dts.DataSet.Active    ) then exit;
    if (dts<>nil ) and (not dts.DataSet.Modified) then
      dts.DataSet.Edit;
    OldSelStart:=Edit.SelStart;
    DateStr:=Edit.EditText;
    Mark:=GetDateMark(DateStr);
    MarkPos1:=pos(Mark,DateStr);
    str:=copy(DateStr,MarkPos1+1,length(DateStr)-MarkPos1);
    MarkPos2:=MarkPos1+pos(Mark,str);
    DateOrd:=GetDateOrder(ShortDateFormat);
    DateFlag:=GetDateFlag(MarkPos1,MarkPos2,Edit.SelStart,DateOrd);
    if Key=vk_up then step:=1
    else if Key=vk_down then step:=-1
    else step:=0;
    case DateFlag of
      1: Edit.Date := IncYear(Edit.Date ,step);
      2: Edit.Date := IncMonth(Edit.Date ,step);
      3: Edit.Date := IncDay(Edit.Date ,step);
    end;
    Edit.SelStart :=OldSelStart;
end;

此函数在组件的OnKeyDown事件中调用,对于TDateEdit,DataSoure参数为nil。
记着引用Rx的单元ToolEdit和DateUtil。
调用示例:
procedure TForm1.DateEdit1KeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
begin
    MxSpinRxDateEdit(Sender as TCustomDateEdit,Key,Shift,nil);
end;

procedure TForm1.DBDateEdit1KeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
begin
    MxSpinRxDateEdit(Sender as TCustomDateEdit,Key,Shift,(Sender as TDBDateEdit).DataSource);
end;

posted @ 2016-09-09 13:39  德芙70  阅读(393)  评论(0编辑  收藏  举报