由于ID卡或者是其它的一些不同类型的卡,它们只是负责模拟键盘的录入,但是,它们在录入的时候没有一个很好的标识位可以让我们知道当前输入的是客户手工录入的字符串还是ID卡读入的字符串,我相信,很多人在做这样的开发时应该都遇到过这种郁闷的事,有些人的做法呢,就是在特定的位置录入字符串就算是ID卡的读取了,我想,这样的方法很多人都不喜欢的了,感觉很不科学。因此,这模块就是应这种要求而设计的,可以让你在任何情况下,应该说,限制很少的情况下,满足了题目的要求。废话不多说,先看看模块代码:
interface
uses
Windows,Dialogs;
type
TIDCheckOKEvent = procedure (IDCheckResult:string) of object;
TIDCheck = class (TObject)
protected
m_INTCheck:array of integer; // 结果的检测用
m_TimeCheck:array of integer; // 时间的检测用
m_Begin:integer; // 检测录入的字符第一个开始时间。
m_MaxTime:Smallint; // 超出该时间证明不是ID的录入时间范围
m_Length:integer; // 读取长度
m_LastResult:string; // 上一次读取的结果
FOnIDCheck: TIDCheckOKEvent;
FOnIDCheck_SP: TIDCheckOKEvent;
procedure DoClear; // 当检测到符合清空条件的,则还原所有变量
function CheckID:Boolean;
function GetIDResult:string;
procedure DoAddKey(var key:integer); // 符合条件的进行处理。
procedure SetOnIDCheckResult_SP(value:TIDCheckOKEvent);
public
function KeyDownCheck(var key:integer):string;
property IDLength:integer read m_Length;
property IDResult:string read GetIDResult;
property LastResult:string read m_LastResult;
constructor Create(MaxTime:integer = 50 ;Length:integer = 10 );
destructor Destroy; override;
procedure APPIntercept(var Msg:TMsg;var Handled:Boolean); // 截取程序的消息,改为自己的截取过程
property OnIDCheckResult: TIDCheckOKEvent read FOnIDCheck write FOnIDCheck; // 默认的事件
property OnIDCheckResult_SP: TIDCheckOKEvent read FOnIDCheck_SP write SetOnIDCheckResult_SP; // 特殊事件,当特殊事件存在时不会去执行默认事件的。
end;
var
IDCheckObj:TIDCheck;
implementation
uses
Forms,StdCtrls,Messages;
procedure TIDCheck.APPIntercept(var Msg: TMsg; var Handled: Boolean);
var
aStr:string;
begin
if Msg.message = WM_KEYDOWN then
begin
aStr: = KeyDownCheck(Msg.wParam);
if length(aStr) > 0 then
begin
Msg.wParam: = 0;
end
else // 没有完整返回ID的检测,下面是一些比较特殊的处理。
begin
if ((m_TimeCheck[ 1 ] > 0) and (m_TimeCheck[ 1 ] <= m_MaxTime) and not (Screen.ActiveForm.ActiveControl is TCustomEdit)) then
Msg.wParam: = 0;
end;
// 下面是屏蔽数字的快捷键的,因此数字快捷键必须使用数字键盘
if ((Msg.wParam >= 48 ) and (Msg.wParam <= 57 )) then
if not (Screen.ActiveForm.ActiveControl is TCustomEdit) then
Msg.wParam: = 0;
end;
end;
function TIDCheck.CheckID: Boolean;
begin
if m_INTCheck[m_Length - 1 ] < 0 then
result: = false
else
result: = true;
end;
constructor TIDCheck.Create(MaxTime: integer;Length:integer);
begin
m_MaxTime: = MaxTime;
m_Length: = Length;
SetLength(m_INTCheck,m_Length);
SetLength(m_TimeCheck,m_Length);
DoClear;
end;
destructor TIDCheck.Destroy;
begin
Finalize(m_INTCheck);
Finalize(m_TimeCheck);
inherited;
end;
procedure TIDCheck.DoAddKey(var key: integer);
var
i:Smallint;
begin
for i: = 0 to m_Length - 1 do
if m_INTCheck[i] < 0 then
begin
m_INTCheck[i]: = key;
m_TimeCheck[i]: = GetTickCount - m_Begin;
m_Begin: = GetTickCount;
break ;
end;
if i = m_Length then // 没有空间记录,把所有数据前移并把新的放在最后一位。
begin
for i: = 1 to m_Length - 1 do
begin
m_INTCheck[i - 1 ]: = m_INTCheck[i];
m_TimeCheck[i - 1 ]: = m_TimeCheck[i];
end;
m_INTCheck[m_Length]: = key;
m_TimeCheck[m_Length]: = GetTickCount - m_Begin;
m_Begin: = GetTickCount;
end;
if (m_TimeCheck[i] >= m_MaxTime) and (i > 0) then // 超出ID卡读取范围则清空
DoClear;
end;
procedure TIDCheck.DoClear;
var
i:integer;
begin
for i: = 0 to m_Length - 1 do
begin
m_INTCheck[i]: =- 1 ;
m_TimeCheck[i]: =- 1 ;
end;
m_Begin: = 0;
end;
function TIDCheck.GetIDResult: string;
var
i:Shortint;
begin
if CheckID then
begin
for i: = 0 to m_Length - 1 do
result: = result + char(m_INTCheck[i]);
end;
end;
function TIDCheck.KeyDownCheck(var key:integer):string;
var
aStr:string;
i:integer;
begin
result: = '' ;
case key of
48 .. 57 :DoAddKey(key);
13 :begin
if checkid then // 检测到结果则把结果返回
begin
result: = GetIDResult;
m_LastResult: = result;
if Screen.ActiveForm.ActiveControl is TCustomEdit then
begin
aStr: = TCustomEdit(Screen.ActiveForm.ActiveControl).Text;
Delete(aStr,length(aStr) - IDLength + 1 ,IDLength);
i: = TCustomEdit(Screen.ActiveForm.ActiveControl).SelStart;
TCustomEdit(Screen.ActiveForm.ActiveControl).Text: = aStr;
TCustomEdit(Screen.ActiveForm.ActiveControl).SelStart: = i;
end;
if assigned(OnIDCheckResult_SP) then
OnIDCheckResult_SP(result)
else
begin
if assigned(FOnIDCheck) then
FOnIDCheck(result);
end;
DoClear; // 清空重新处理。
end
else
DoClear; // 清空重新处理。
end;
else // 非数字的要清空并重新处理
DoClear;
end;
end;
procedure TIDCheck.SetOnIDCheckResult_SP(value: TIDCheckOKEvent);
begin
FOnIDCheck_SP: = value;
DoClear;
end;
initialization
IDCheckObj: = TIDCheck.Create;
finalization
IDCheckObj.Free;
end.
下面是它的使用方法:(对象不用创建的,引用了该模块就可以使用,应该它在模块引用的时候就已经创建出来的了。)
Application.OnMessage:=IDCheckObj.APPIntercept;(首先这里设置截获应用程序的消息。)
IDCheckObj.OnIDCheckResult:=OnIDCheckReturn;(设置检测到ID卡读取后要执行的事件。)
调用的方法就是这么简单了。
下面的是特殊情况下调用的方法:
IDCheckObj.OnIDCheckResult_SP:=OnIDCheckReturn;(OnIDCheckResult是默认的执行事件,如果你在某个窗体里面要求检测到ID卡读取后执行比较特殊的事件,而不执行默认事件的话,就要设置这个事件了,记得窗体不再激活的时候要把它设置为NULL哦,否者,其它地方会执行OnIDCheckResult_SP这个事件的)
介绍一个这个事件过程是如何定义的:procedure OnIDCheckReturn(IDCheckResult:string);
下面是我的默认事件所执行的过程,可以参考一下:
procedure TMainForm.OnIDCheckReturn(IDCheckResult: string);
var
frm_IDCardCon:Tfrm_IDCardControl;
begin
frm_IDCardCon:=Tfrm_IDCardControl.Create(IDCheckResult);
if frm_IDCardCon.VIP_NO<>'' then
frm_IDCardCon.ShowModal
else
frm_IDCardCon.Free;
end;
IDCheckResult:就是检测到的那串字符串。我这里是检测到就弹出窗体。不知道我这东西是否适合大家使用呢?不管适用与否,我都已经用在客户那里啦,反应挺好的。
原创作品出自努力偷懒,转载请说明文章出处:http://blog.csdn.net/kfarvid或 http://www.cnblogs.com/kfarvid/