限制并方便用户输入

    技术2022-05-11  142

    限制并方便用户输入(2002/12/03 三金 版权所有)

        防止用户误输入是软件开发的一项必不可少的工作,除才之外,还要为用户的使用提供最大方便。当然,我们可以利用或开发新的组件,以完成这些功能。但是,在团队开发中,每个成员都用自己认为不错的组件开发自己所承担的模块,会给软件的后期维护带来麻烦。交工的时候,项目负责人可不买你的帐。如果你用函数调用来完成这些功能,老盖也管不着。下面就是针对常用delphi组件的限制用户输入函数,但愿网友们能用的上。(一)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+SelLength 0) 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;

    更多文章请访问三金主页http://vip.6to23.com/tianmingxin


    最新回复(0)