本文中的validator.cpp存在2个bug,见"客户端数据校验器中的2个bug"一文.(2014-6-27)
1.用途
简化客户端输入/编辑操作的编程。可大幅减少代码量,并易于维护和扩展。.支持从对象直接加载到控件和把控件数据更新到对象
.自动根据校验规则控制输入
.支持TEdit,TComboBox,TDatetimePicker
限制:
.仅支持对象的成员类型为基本数据类型和string
2..定义
头文件:validator.h
名字空间:ns_validator
#include <vcl.h>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <vector>
#include <ComCtrls.hpp>
#pragma hdrstop
#include "NullForm.h"
#include "auto_pointer.h"
#include "code_table_mgr.h"
using namespace std;
//---------------------------------------------------------------------------
namespace ns_validator {
//---------------------------------------------------------------------------
///< 有效字符类型
///< 1-数字(0-9) 2-字母(a-z,A-Z) 9-指定字符(若干)
enum VALID_CHARSET_TYPE { CS_DIGIT=1,CS_ALPHA=2,CS_STRING=9};
//---------------------------------------------------------------------------
///< 有效字符规则
struct CValidCharSet {
VALID_CHARSET_TYPE type_;
string chars_; ///< 当type_==9时,表示有效的字符
};
//---------------------------------------------------------------------------
///< 数据绑定控件基类
class CBindControl {
public:
virtual int CheckInput(char ch) { return 1; }
virtual int CheckInput(char ch,char **out) { return 1; }
virtual string GetValue() = 0; ///< 获取控件的值
virtual void SetValue(const char *value) = 0; ///< 设置控件值
virtual void SetOnKeyPress(TKeyPressEvent e) {}
virtual void SetFocus() = 0;
};
//---------------------------------------------------------------------------
///< CEdit编辑框控件
class CEdit : public CBindControl {
TEdit *control_;
public:
CEdit(TEdit *control);
void SetOnKeyPress(TKeyPressEvent e);
int CheckInput(char ch,char **out);
string GetValue();
void SetValue(const char *value);
void SetFocus() { control_->SetFocus(); }
};
//---------------------------------------------------------------------------
///< 通用码表类
struct CCodeTableBase {
string code_; ///< 编码
string name_; ///< 名称
CCodeTableBase(const char *code,const char *name):code_(code),name_(name) {
}
};
//---------------------------------------------------------------------------
///< CComboBox组合框控件
class CComboBox : public CBindControl {
short flag_; ///< 0-不使用码表 1-使用码表的code_值 2-使用码表的name_值
CCodeTableMgr<CCodeTableBase,string> *code_table_; ///< 码表
TComboBox *control_;
public:
CComboBox(TComboBox *control,short flag=0,CCodeTableMgr<CCodeTableBase,string> *code_table=0);
string GetValue();
void SetValue(const char *value);
void SetFocus() { control_->SetFocus(); }
};
//---------------------------------------------------------------------------
///< CDateTimePicker日期时间选取控件
class CDateTimePicker : public CBindControl {
TDateTimePicker *control_;
short flag_; ///< 1-日期时间 2-日期 3-时间
public:
CDateTimePicker(TDateTimePicker *control,int flag=1);
string GetValue();
void SetValue(const char *value);
void SetFocus() { control_->SetFocus(); }
};
//---------------------------------------------------------------------------
///< 校验器基类
class CValidatorBase {
protected:
CAutoVector<CValidCharSet*> v_ch_set_; ///< 有效字符限定,如果为空则表示允许任何字符
unsigned int max_len_; ///< 最大长度(0:表示不限制)
unsigned int min_len_; ///<最小长度(0:表示不限制)
bool null_flag_; ///< 是否允许为空
TfrmNull *null_form_; ///< 用于检查按键的窗体(内部隐藏)
public:
CBindControl *control_; ///< 绑定的控件
public:
CValidatorBase();
virtual ~CValidatorBase();
///< 设置最小长度
void SetMinLength(unsigned int min_len) { min_len_ = min_len; }
///< 设置最大长度
void SetMaxLength(unsigned int max_len) { max_len_ = max_len; }
///< 取最小长度
unsigned int GetMinLength() const { return min_len_; }
///< 取最大长度
unsigned int GetMaxLength() const { return max_len_; }
///< 设置有效字符
void AddValidChar(VALID_CHARSET_TYPE type);
void AddValidChar(const char *s);
///< 设置允许空标志
void SetNullFlag(bool flag) { null_flag_ = flag; }
///< 取允许空标志
bool GetNullFlag() const { return null_flag_; }
///< 绑定控件
void BindControl(CBindControl *control);
///< 获取控件内容
int GetText(string &text);
///< 设置控件内容
void SetText(const char *text);
int CheckChar(char ch); ///< 检查字符的有效性
virtual int CheckInput(char ch); ///< 检查是否可以接受输入字符
virtual int Check(void *val,int flag=1) = 0; ///< 校验值有效性 1-有效 0-无效
virtual int CheckText(const char *text,int flag) = 0; ///< 校验值的有效性 flag=0时不检查最小值和最小长度(输入过程中)
};
//---------------------------------------------------------------------------
///< 数值范围模板类
template <class T> class CNumberRange {
protected:
short range_prop_; ///< 值范围属性 bit-0: 是否有最大限制 bit-1:是否有最小限制 bit-2:最大限制是否排除边界值(0-不排除 1-排除) bit3-最小限制是否排除边界值
T max_value_; ///< 最大值
T min_value_; ///< 最小值
public:
CNumberRange() {
range_prop_ = 0;
max_value_ = 0;
min_value_ = 0;
}
///< 设置最大值
void SetMaxValue(T value,short flag=0) {
max_value_ = value;
range_prop_ |= 1; ///< 有最大限制
if (flag)
range_prop_ |= 1<<2; ///< 是否排除边界值
}
///< 设置最小值
void SetMinValue(T value,short flag=0) {
min_value_ = value;
range_prop_ |= 1<<1;
if (flag) {
range_prop_ |= 1<<3;
}
}
///< 取最大值
T GetMinValue() const { return min_value_; }
///< 取最小值
T GetMaxValue() const { return max_value_; }
///< 取范围属性
short GetRangeProp() const { return range_prop_; }
///< 检查一个值是否在范围内
///< flag=0不检查最小值
bool Check(T value,short flag) {
if (range_prop_&1) { ///< 有最大值限制
if (range_prop_&(1<<2)) {///< 排除边界值
if (value>max_value_)
return false;
}
else {
if (value>=max_value_)
return false;
}
}
if (flag) {
if (range_prop_&(1<<1)) { ///< 有最小值限制
if (range_prop_&(1<<3)) {///< 排除边界值
if (value<min_value_)
return false;
}
else {
if (value<=min_value_)
return false;
}
}
}
return true;
}
};
//---------------------------------------------------------------------------
///< 整数校验器
class CIntValidator : public CValidatorBase,public CNumberRange<long> {
public:
CIntValidator();
int Check(void *val,int flag); ///< 校验合法性
int CheckText(const char *text,int flag);
};
//---------------------------------------------------------------------------
///< 小数数值校验器
///< 长度包括符号位和小数点
class CDecimalValidator : public CValidatorBase,public CNumberRange<double> {
unsigned short scale_; ///< 最大小数位数
public:
CDecimalValidator();
///< 设置最大小数位数
void SetScale(unsigned short scale) { scale_ = scale; }
///< 取最大小数位数
unsigned short GetScale() const { return scale_; }
int Check(void *val,int flag);
int CheckText(const char *text,int flag);
};
//---------------------------------------------------------------------------
///< 字符串校验器
/// @todo 引入正则表达式,支持各种文本模式
class CStringValidator : public CValidatorBase {
public:
CStringValidator();
CStringValidator(unsigned int min_len,unsigned int max_len);
int Check(void *val,int flag);
int CheckText(const char *text,int flag);
};
//---------------------------------------------------------------------------
///< 对象校验成员绑定信息
struct CValidatorBindInfo {
unsigned short offset_; ///< 成员在对象中的偏移
string desc_; ///< 成员描述
string var_type_; ///< 变量类型,字段类型
CValidatorBase *validator_; ///< 校验器
CBindControl *control_; ///< 控件
CValidatorBindInfo(unsigned short offset,const char *val_type,CValidatorBase *validator,const char *desc):offset_(offset),var_type_(val_type),validator_(validator),control_(0) {
if (desc) desc_ = desc;
}
~CValidatorBindInfo() {
if (control_) delete control_;
}
};
//---------------------------------------------------------------------------
#define ORM_FIELD_TYPE_INT "int"
#define ORM_FIELD_TYPE_UINT "uint"
#define ORM_FIELD_TYPE_SHORT "short"
#define ORM_FIELD_TYPE_USHORT "ushort"
#define ORM_FIELD_TYPE_LONG "long"
#define ORM_FIELD_TYPE_ULONG "ulong"
#define ORM_FIELD_TYPE_INT64 "int64"
#define ORM_FIELD_TYPE_UINT64 "uint64"
#define ORM_FIELD_TYPE_CHAR "char"
#define ORM_FIELD_TYPE_UCHAR "uchar"
#define ORM_FIELD_TYPE_STRING "string"
#define ORM_FIELD_TYPE_BOOL "bool"
#define ORM_FIELD_TYPE_FLOAT "float"
#define ORM_FIELD_TYPE_DOUBLE "double"
#define ORM_FIELD_TYPE_INT1 "int1"
#define ORM_FIELD_TYPE_UINT1 "uint1"
#define OFFSETOF(TYPE,VAR) (int)&(((TYPE*)0)->VAR)
#define NEW_VALIDATOR_BIND(TYPE,VAR,VAL_TYPE,CHECKER,DESC) \
new CValidatorBindInfo(OFFSETOF(TYPE,VAR),VAL_TYPE,CHECKER,DESC)
//---------------------------------------------------------------------------
///< 对象校验器
template <class T> class CObjectValidator {
vector<CValidatorBindInfo*> bind_info_;
int err_code_; ///< 校验失败的错误码(@todo 待定义)
CValidatorBindInfo *err_vbi_; ///< 校验失败的绑定项
bool auto_hint_; ///< 校验失败时自动提示
bool auto_focus_; ///< 自动设置焦点
///< 查找指定成员对应的绑定信息
CValidatorBindInfo* Find(int offset);
public:
CObjectValidator():err_code_(0),err_vbi_(0),auto_hint_(true),auto_focus_(true) {
}
~CObjectValidator() {
vector<CValidatorBindInfo*>::iterator iter = bind_info_.begin();
while(iter!=bind_info_.end()) {
delete *iter;
iter++;
}
}
///< 设置(校验失败时)自动提示标志
void SetAutoHint(bool value) { auto_hint_ = value; }
///< 设置(校验失败时)自动设置输入焦点标志
void SetAutoFocus(bool value) { auto_focus_ = value;}
///< 设置指定成员的校验器
int SetValidator(CValidatorBindInfo* v) {
bind_info_.push_back(v);
return 0;
}
///< 绑定成员与控件
int BindControl(int offset,CBindControl *control);
///< 控件支持: TEdit,
int Update(T *obj); ///< 把控件内容更新对象
int Load(T *obj); ///< 把对象内容加载到控件
int Check(T *obj); ///< 检查对象值的有效性,@return 0-无效 1-有效
string GetErrorInfo(); ///< 获取校验错误信息
};
//---------------------------------------------------------------------------
template <class T> string CObjectValidator<T>::GetErrorInfo() {
string err;
if (err_vbi_==0)
return err;
err += "数据项'";
err += err_vbi_->desc_.c_str();
err += "'无效";
return err;
}
//---------------------------------------------------------------------------
template <class T> CValidatorBindInfo* CObjectValidator<T>::Find(int offset) {
vector<CValidatorBindInfo*>::iterator iter = bind_info_.begin();
while(iter!=bind_info_.end()) {
CValidatorBindInfo *vbi = *iter;
if (vbi->offset_==offset)
return vbi;
iter++;
}
return 0;
}
//---------------------------------------------------------------------------
template <class T> int CObjectValidator<T>::BindControl(int offset,CBindControl *control) {
CValidatorBindInfo* vbi = Find(offset);
if (vbi==0)
return -1;
vbi->control_ = control;
vbi->validator_->BindControl(control);
return 0;
}
//---------------------------------------------------------------------------
template <class T> int CObjectValidator<T>::Update(T *obj) {
vector<CValidatorBindInfo*>::iterator iter = bind_info_.begin();
while(iter!=bind_info_.end()) {
CValidatorBindInfo *vbi = *iter;
if (vbi->control_==0) { ///< 如果成员未与控件绑定则不处理
iter++;
continue;
}
char *p = (char*)obj+vbi->offset_;
string sVal;
vbi->validator_->GetText(sVal);
string type_name = vbi->var_type_.c_str();
if (type_name==ORM_FIELD_TYPE_LONG||type_name==ORM_FIELD_TYPE_ULONG) {
*(long*)p = atol(sVal.c_str());
}
else if (type_name==ORM_FIELD_TYPE_INT||type_name==ORM_FIELD_TYPE_UINT) {
*(int*)p = atoi(sVal.c_str());
} else if (type_name==ORM_FIELD_TYPE_SHORT||type_name==ORM_FIELD_TYPE_USHORT) {
*(short*)p = (short)atoi(sVal.c_str());
} else if (type_name==ORM_FIELD_TYPE_INT1||type_name==ORM_FIELD_TYPE_UINT1) {
*p = sVal[0];
}
else if (type_name==ORM_FIELD_TYPE_FLOAT) {
*(float*)p = (float)atof(sVal.c_str());
} else if (type_name==ORM_FIELD_TYPE_DOUBLE) {
*(double*)p = atof(sVal.c_str());
} else if (type_name==ORM_FIELD_TYPE_STRING) {
*(string*)p = sVal.c_str();
} else if (type_name==ORM_FIELD_TYPE_CHAR||type_name==ORM_FIELD_TYPE_UCHAR) {
strcpy(p,sVal.c_str());//,fb->fld_size_);
} else if (type_name==ORM_FIELD_TYPE_INT64||type_name==ORM_FIELD_TYPE_UINT64) {
*(__int64*)p = _atoi64(sVal.c_str());
} else if (type_name==ORM_FIELD_TYPE_BOOL) {
*(bool*)p = sVal[0]=='1';
}
else {
iter++; ///< 不支持的数据类型
continue;
}
iter++;
}
return 0;
}
//---------------------------------------------------------------------------
template <class T> int CObjectValidator<T>::Load(T *obj) {
vector<CValidatorBindInfo*>::iterator iter = bind_info_.begin();
while(iter!=bind_info_.end()) {
CValidatorBindInfo *vbi = *iter;
char *p = (char*)obj+vbi->offset_;
string type_name = vbi->var_type_.c_str();
char buffer[20];
if (type_name==ORM_FIELD_TYPE_LONG||type_name==ORM_FIELD_TYPE_ULONG) {
sprintf(buffer,"%d",*(long*)p);
vbi->validator_->SetText(buffer);
}
else if (type_name==ORM_FIELD_TYPE_INT||type_name==ORM_FIELD_TYPE_UINT) {
sprintf(buffer,"%d",*(int*)p);
vbi->validator_->SetText(buffer);
} else if (type_name==ORM_FIELD_TYPE_SHORT||type_name==ORM_FIELD_TYPE_USHORT) {
sprintf(buffer,"%d",*(short*)p);
vbi->validator_->SetText(buffer);
} else if (type_name==ORM_FIELD_TYPE_INT1||type_name==ORM_FIELD_TYPE_UINT1) {
sprintf(buffer,"%c",*p);
vbi->validator_->SetText(buffer);
}
else if (type_name==ORM_FIELD_TYPE_FLOAT) {
vbi->validator_->SetText(p);
} else if (type_name==ORM_FIELD_TYPE_DOUBLE) {
sprintf(buffer,"%.3f",*(double*)p); ///< @todo: 根据长度定义确定格式
vbi->validator_->SetText(buffer);
} else if (type_name==ORM_FIELD_TYPE_STRING) {
string s = *(string*)p;
vbi->validator_->SetText(s.c_str());
} else if (type_name==ORM_FIELD_TYPE_CHAR||type_name==ORM_FIELD_TYPE_UCHAR) {
vbi->validator_->SetText(p);
} else if (type_name==ORM_FIELD_TYPE_INT64||type_name==ORM_FIELD_TYPE_UINT64) {
sprintf(buffer,"%I64d",*(__int64*)p);
vbi->validator_->SetText(buffer);
} else if (type_name==ORM_FIELD_TYPE_BOOL) {
sprintf(buffer,"%d",*(bool*)p);
vbi->validator_->SetText(buffer);
}
else {
iter++; ///< 不支持的数据类型
continue;
}
iter++;
}
return 0;
}
//---------------------------------------------------------------------------
template <class T> int CObjectValidator<T>::Check(T *obj) {
vector<CValidatorBindInfo*>::iterator iter = bind_info_.begin();
while(iter!=bind_info_.end()) {
CValidatorBindInfo *vbi = *iter;
char *p = (char*)obj+vbi->offset_;
string type_name = vbi->var_type_.c_str();
int ret = 0;
if (type_name==ORM_FIELD_TYPE_LONG||type_name==ORM_FIELD_TYPE_ULONG) {
ret = vbi->validator_->Check((void*)*(long*)p);
}
else if (type_name==ORM_FIELD_TYPE_INT||type_name==ORM_FIELD_TYPE_UINT) {
ret = vbi->validator_->Check((void*)*(int*)p);
} else if (type_name==ORM_FIELD_TYPE_SHORT||type_name==ORM_FIELD_TYPE_USHORT) {
ret = vbi->validator_->Check((void*)*(short*)p);
} else if (type_name==ORM_FIELD_TYPE_INT1||type_name==ORM_FIELD_TYPE_UINT1) {
ret = vbi->validator_->Check((void*)*p);
}
else if (type_name==ORM_FIELD_TYPE_FLOAT) {
ret = vbi->validator_->Check((void*)p);
} else if (type_name==ORM_FIELD_TYPE_DOUBLE) {
ret = vbi->validator_->Check((void*)p);
} else if (type_name==ORM_FIELD_TYPE_STRING) {
string s = *(string*)p;
ret = vbi->validator_->Check((void*)s.c_str());
} else if (type_name==ORM_FIELD_TYPE_CHAR||type_name==ORM_FIELD_TYPE_UCHAR) {
ret = vbi->validator_->Check((void*)p);
} else if (type_name==ORM_FIELD_TYPE_INT64||type_name==ORM_FIELD_TYPE_UINT64) {
ret = vbi->validator_->Check((void*)*(__int64*)p);
} else if (type_name==ORM_FIELD_TYPE_BOOL) {
ret = vbi->validator_->Check((void*)*(bool*)p);
}
else {
iter++; ///< 不支持的数据类型
continue;
}
if (ret==0) {
err_vbi_ = vbi;
if (auto_hint_) {
string err_msg = GetErrorInfo();
ShowMessage(err_msg.c_str());
}
if (auto_focus_) {
vbi->validator_->control_->SetFocus();
}
return 0;
}
iter++;
}
return 1;
}
};
3.实现
实现文件:validator.cpp
#pragma hdrstop
#include "validator.h"
#include "NullForm.h"
using namespace ns_validator;
#pragma package(smart_init)
//---------------------------------------------------------------------------
CValidatorBase::CValidatorBase():max_len_(0),min_len_(0),control_(0),null_form_(0),null_flag_(true) {
}
//---------------------------------------------------------------------------
CValidatorBase::~CValidatorBase() {
if (null_form_) delete null_form_;
}
//---------------------------------------------------------------------------
int CValidatorBase::CheckChar(char ch) {
if (v_ch_set_.empty())
return 1;
CAutoVector<CValidCharSet*>::iterator iter = v_ch_set_.begin();
while(iter!=v_ch_set_.end()) {
CValidCharSet *vcs = *iter;
switch(vcs->type_) {
case CS_DIGIT:
if (isdigit(ch))
return 1;
case CS_ALPHA:
if (isalpha(ch)==0)
return 1;
default:
if (strchr(vcs->chars_.c_str(),ch))
return 1;
}
iter++;
}
return 0;
}
//---------------------------------------------------------------------------
int CValidatorBase::CheckInput(char ch) { ///< 检查当前输入字符
if (CheckChar(ch)==0) { ///< 字符是否有效
return 0;
}
char *Buffer = 0;
if (control_->CheckInput(ch,&Buffer)==0) {
return 0;
}
int Size = strlen(Buffer);
if (max_len_) {
if (Size>max_len_) {
delete []Buffer;
return 0;
}
}
int ret = CheckText(Buffer,0);
delete []Buffer;
return ret;
}
//---------------------------------------------------------------------------
///< 设置有效字符
void CValidatorBase::AddValidChar(VALID_CHARSET_TYPE type) {
CValidCharSet *vcs = new CValidCharSet;
vcs->type_ = type;
v_ch_set_.push_back(vcs);
}
//---------------------------------------------------------------------------
void CValidatorBase::AddValidChar(const char *s) {
CValidCharSet *vcs = new CValidCharSet;
vcs->type_ = CS_STRING;
vcs->chars_ = s;
v_ch_set_.push_back(vcs);
}
//---------------------------------------------------------------------------
void CValidatorBase::BindControl(CBindControl *control) {
control_ = control;
null_form_ = new TfrmNull(0);
null_form_->Visible = false;
null_form_->SetValidator(this);
control_->SetOnKeyPress(null_form_->EditKeyPress);
}
//---------------------------------------------------------------------------
int CValidatorBase::GetText(string &text) {
text = control_->GetValue();
return 0;
}
//---------------------------------------------------------------------------
void CValidatorBase::SetText(const char *text) {
control_->SetValue((char*)text);
}
//---------------------------------------------------------------------------
CIntValidator::CIntValidator() {
AddValidChar(CS_DIGIT);
}
//---------------------------------------------------------------------------
int CIntValidator::Check(void *val,int flag) { ///< 校验合法性
long nval = (long)val;
return CNumberRange<long>::Check(nval,flag);
}
//---------------------------------------------------------------------------
int CIntValidator::CheckText(const char *text,int flag) {
long val = atol(text);
return Check((char*)val,flag);
}
//---------------------------------------------------------------------------
CDecimalValidator::CDecimalValidator():scale_(2) {
AddValidChar(CS_DIGIT);
AddValidChar("."); ///< 允许小数点
}
//---------------------------------------------------------------------------
int CDecimalValidator::Check(void *val,int flag) {
double fval = *(double*)val;
return CNumberRange<double>::Check(fval,flag);
}
//---------------------------------------------------------------------------
int CDecimalValidator::CheckText(const char *text,int flag) {
double val = atof(text);
if (Check((void*)&val,flag)==0)
return 0;
if (scale_) {
///< 检查小数长度
const char *p = strchr(text,'.');
if (p) {
int scale_n = strlen(p)-1;
if (scale_n>scale_)
return 0;
}
}
return 1;
}
//---------------------------------------------------------------------------
CStringValidator::CStringValidator(){
}
//---------------------------------------------------------------------------
CStringValidator::CStringValidator(unsigned int min_len,unsigned int max_len) {
min_len_ = min_len;
max_len_ = max_len;
}
//---------------------------------------------------------------------------
int CStringValidator::Check(void *val,int flag) {
const char *sz_val = (const char*)val;
int len = strlen(sz_val);
if (flag) {
if (min_len_) {
if (len<min_len_)
return 0;
}
}
if (max_len_) {
if (len>max_len_)
return 0;
}
if (!v_ch_set_.empty()) { ///< 检查是否是有效字符
const char *p = sz_val;
while(*p!='\0') {
if (CheckChar(*p)==0)
return 0;
p++;
};
}
return 1;
}
//---------------------------------------------------------------------------
int CStringValidator::CheckText(const char *text,int flag) {
return Check((char*)text,flag);
}
//---------------------------------------------------------------------------
CEdit::CEdit(TEdit *control):control_(control) {
}
//---------------------------------------------------------------------------
void CEdit::SetOnKeyPress(TKeyPressEvent e) {
control_->OnKeyPress = e;
}
//---------------------------------------------------------------------------
int CEdit::CheckInput(char ch,char **out) {
int Size = control_->GetTextLen(); ///< 当前已接收内容的长度
int sel_pos = control_->SelStart;
///< 对接受此输入后的结果进行检查(不检查最小值和最小长度:因正在输入过程)
char *Buffer = new char[Size+2];
control_->GetTextBuf(Buffer,Size+2);
int sel_len = control_->SelLength;
if (sel_len>0) {
memcpy(&Buffer[sel_pos],&Buffer[sel_pos+sel_len],Size-sel_pos-sel_len+1);
Size = strlen(Buffer);
}
int k = Size;
while(k>=sel_pos) {
char ch = Buffer[k];
Buffer[k+1] = ch;
k--;
}
Buffer[sel_pos] = ch;
Buffer[Size+1] = '\0';
*out = Buffer;
return 1;
}
//---------------------------------------------------------------------------
string CEdit::GetValue() {
return control_->Text.c_str();
}
//---------------------------------------------------------------------------
void CEdit::SetValue(const char *value) {
control_->Text = value;
}
//---------------------------------------------------------------------------
CComboBox::CComboBox(TComboBox *control,short flag,CCodeTableMgr<CCodeTableBase,string> *code_table)
:control_(control),flag_(flag),code_table_(code_table) {
}
//---------------------------------------------------------------------------
string CComboBox::GetValue() {
// assert(control_->ItemIndex!=-1);
if (control_->ItemIndex==-1) {
return string();
}
if (flag_==1) {
int count = code_table_->GetSize();
for (int i=0;i<count;i++) {
CCodeTableBase *item = (*code_table_)[i];
if (stricmp(item->name_.c_str(),control_->Text.c_str())) {
return item->code_;
}
}
}
return control_->Text.c_str();
}
//---------------------------------------------------------------------------
void CComboBox::SetValue(const char *value) {
if (flag_==1) {
int count = code_table_->GetSize();
for (int i=0;i<count;i++) {
CCodeTableBase *item = (*code_table_)[i];
if (stricmp(item->name_.c_str(),control_->Text.c_str())) {
control_->ItemIndex = i;
return;
}
}
}
control_->ItemIndex = -1;
}
//---------------------------------------------------------------------------
CDateTimePicker::CDateTimePicker(TDateTimePicker *control,int flag):control_(control),flag_(flag) {
}
//---------------------------------------------------------------------------
string CDateTimePicker::GetValue() {
TDateTime dt = control_->DateTime;
AnsiString result;
switch(flag_) {
case 1:
result = dt.FormatString("yyyy-mm-dd hh:nn:ss");
break;
case 2:
result = dt.FormatString("yyyy-mm-dd");
break;
case 3:
result = dt.FormatString("hh:nn:ss");
break;
}
return result.c_str();
}
//---------------------------------------------------------------------------
void CDateTimePicker::SetValue(const char *value) {
AnsiString s(value);
TDateTime dt(s);
control_->DateTime = dt;
}
NullForm.cpp
void __fastcall TfrmNull::EditKeyPress(TObject *Sender, char &Key) {
if (iscntrl(Key)) { ///< 删除等操作
return;
}
assert(validator_!=0);
if (validator_->CheckInput(Key)==0) {
Key = 0;
return;
}
}
4.示例:
#include "validator.h"
using namespace ns_validator;
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
///< 商品GTIN:不能为空,并且必须是13个字符宽
CStringValidator *sv = new CStringValidator;
sv->SetMinLength(13);
sv->SetMaxLength(13);
sv->SetNullFlag(false); ///< 不允许为空
sv->AddValidChar(CS_DIGIT);
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods, m_strGoodsid,ORM_FIELD_TYPE_STRING,sv,"商品GTIN"));
///< 零售价:小数数值,长度(8,3)--长度8位(含小数点和小数位),小数位最大3位,只能是正数,有效字符:0-9,'.'
CDecimalValidator *dv = new CDecimalValidator;
dv->SetMaxLength(8);
dv->SetScale(3);
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods,m_dRetailPrice,ORM_FIELD_TYPE_DOUBLE,dv,"建议零售价"));
///< 装箱数
CIntValidator *iv = new CIntValidator;
iv->SetMaxLength(6);
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods,m_iBoxCount,ORM_FIELD_TYPE_INT,iv,"装箱数"));
///< 税率
dv = new CDecimalValidator;
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods,m_dTaxRate,ORM_FIELD_TYPE_DOUBLE,dv,"税率"));
sv = new CStringValidator;
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods,m_strOrderBegin,ORM_FIELD_TYPE_STRING,sv,"订单开始日期"));
sv = new CStringValidator;
ov_.SetValidator(NEW_VALIDATOR_BIND(CGYBGoods,m_strOrderEnd,ORM_FIELD_TYPE_STRING,sv,"订单截止日期"));
///< 绑定控件
ov_.BindControl(OFFSETOF(CGYBGoods, m_strGoodsid),new CEdit(edtGTIN));
ov_.BindControl(OFFSETOF(CGYBGoods, m_dRetailPrice),new CEdit(edtPrice));
ov_.BindControl(OFFSETOF(CGYBGoods, m_iBoxCount),new CEdit(edtBoxNum));
///< 税率绑定的是TComboBox
ov_.BindControl(OFFSETOF(CGYBGoods, m_dTaxRate),new CComboBox(cbTaxRate,1,&tax_rate_code_tbl_));
///< 销售开始和截止日期绑定的是TDatTimePicker
ov_.BindControl(OFFSETOF(CGYBGoods, m_strOrderBegin),new CDateTimePicker(dtpSaleBegin,2));
ov_.BindControl(OFFSETOF(CGYBGoods, m_strOrderEnd),new CDateTimePicker(dtpSaleEnd,2));
///< 初始化税率码表
tax_rate_code_tbl_.Add("1",new CCodeTableBase("1","0.015"));
tax_rate_code_tbl_.Add("2",new CCodeTableBase("2","0.013"));
int item_num = tax_rate_code_tbl_.GetSize();
for (int i=0;i<item_num;i++) {
CCodeTableBase *item = tax_rate_code_tbl_[i];
cbTaxRate->Items->AddObject(item->name_.c_str(),(TObject*)item);
}
return;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnOkClick(TObject *Sender)
{
int ret = 0;
///< 把控件内容更新到对象
ret = ov_.Update(&goods_);
///< 从对象加载到控件
goods_.m_strGoodsid = "134";
goods_.m_dRetailPrice = 12.01;
goods_.m_iBoxCount = 120;
goods_.m_dTaxRate = 1;
goods_.m_strOrderBegin = "2013-1-1";
goods_.m_strOrderEnd = "2014-1-15";
ret = ov_.Load(&goods_);
///< 校验对象数据
ret = ov_.Check(&goods_);
return;
}