分享
 
 
 

限制并方便用户输入

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

限制并方便用户输入(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+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;

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有