客户端数据校验器

来源:互联网 发布:手机淘宝网店怎么登陆 编辑:程序博客网 时间:2024/04/30 14:48

本文中的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;}


原创粉丝点击