自动收集信息控件组






3.60/5 (4投票s)
2002年12月27日
6分钟阅读

127130

682
一套用于批量输入、验证和打包用户数据的类。
引言
我写了一个界面上有数千个参数的程序。我发现编写这种对话框并检查数据来完成任务很麻烦。收集所有参数并提交到数据库是很简单的,但这是一个耗时的工作。经过几个月的头疼,我发现这个任务具有普遍性。我编写了这个控件组来自动收集和检查数据。
使用场景
每个程序都需要用户通过用户界面输入大量数据。特别是对于MIS系统,人们必须填写一个大表单,通过代码编写所有数据控件的初始化、获取数据和检查数据是非常麻烦的。
要求
分析整个过程,我发现数据输入操作有四个部分:数据控件初始化、控件状态改变时的活动、数据检查和根据设计规范将数据打包成数据包。
初始化
当您初始化表单中的数据控件时,可能会完成以下事项:
在使用MFC时,条件A将通过DoDataExchange
完成。条件B必须由用户从其工作中获得才能完成。条件C和D是所有需要根据其控件类型进行编码的程序的通用要求。
控件的活动
当控件状态被用户更改时,用户界面会根据用户的数据或选择发生一些变化。这被称为控件状态改变的活动。在Microsoft® Windows®中,这些操作将使用控件的通知。我们将在MFC应用程序中通过重写OnMsg
来完成它。
检查数据(验证)
用户完成数据输入后,应用程序必须根据其业务检查数据的有效性。一般来说,业务数据是以下数据类型中的一种或组合:int
, long
, double
, float
, date
/time
, string
等。
四种数值数据类型(int
、long
、double
、float
)将在指定的业务模型中拥有其域。这些域由程序员根据其业务给出。字符串更复杂,它包括空字符串和字符串的长度。有时,可能必须遵守字符串的格式。我写了一篇文章一套通用数据检查函数来解决这个问题(有些人可能认为它微不足道)。在那篇文章中,我分析了我们在输入数据时可能遇到的所有可能条件。
在Windows中使用组合框时有一个特殊的检查。通常,组合框将由用户定义的字典填充。有时,字典只是数据集的提示,有时我们必须从选项列表中的数据集中选择。至少有两种方法可以实现此功能,使编辑框只读或检查用户输入的数据是否在字典中。在此版本中,我们选择第二种方法。
数据交换
当我们使用MFC时,将数据设置到控件和从控件获取数据都是使用DoDataExchange
。我们为我们的控件组做同样的事情。有几点我们需要处理。没有直接的方法可以从字典中获取项目代码。为了解决这个问题,我写了一篇文章一个使用XML作为字典的组合框。创建了一组单选按钮。在MFC标准方式中,每个单选按钮的值从0开始,并根据它们在表单上的创建顺序递增。实际上,每个单选按钮可能关联有其他值。与组合框的项目不同,您不能将lParam
附加到单选按钮,您必须自己处理这种情况。
数据包
如果数据正常,我们可以提交到数据库。您需要将用户输入的所有数据打包成SQL格式来完成命令。在此控件中,输出将是一个XML文件。使用MSXML和XSL样式表中的接口,您可以非常容易地将XML转换为其他形式。
实现
通用控件
根据对优点的分析,我发现我们可以抽象出一个通用控件。在这个通用控件中,我们可以根据通用控件中的成员值生成各种实际使用的控件。通用控件的信息由控件本身的描述、关联变量名、检查信息、提示等组成。它为控件组提供了从初始化、数据交换、检查和打包完成任务所需的所有信息。
class CNT_Control { public: // data type int m_iDataType; // control type int m_iCntType; // id of control UINT m_uiID; // xml name of variable CString m_strName; // the max value CString m_strMax; // the min_value CString m_strMin; // prompt name of variable CString m_strPrompt; // the data check information flag int m_iCheckFlag; // The default value CString m_strDefault; // The value CString m_strValue; // The color COLORREF m_Cr; // The Transparent BOOL m_bTransparent; // The dictioary CString m_strDict; // The label can be used UINT m_uiLabel; CNT_Control(int dt,int ct,UINT nid,UINT nLab, const CString &name , const CString &max, const CString &min,int chk, const CString &def=_T(""),COLORREF cr=RGB(0,0,0),BOOL t=TRUE); CNT_Control(); CNT_Control( const CNT_Control &ctl); CNT_Control& operator= ( const CNT_Control& ctl); public: void WriteParamDict(CXMLResult & res); void ReadFromResult ( int i ,CXMLResult &rst); void WriteToResult (CXMLResult &rst); };
初始化
我们可以手动(硬编码)或通过程序初始化控件信息。我们支持这两种方式。
// Initialize control group using specific file // If ini = TRUE means to construct control using give data in the file. // Otherwise , just initialize data in control group, // but no construct the actual control void InitFromFile( const CString & path,BOOL ini =TRUE); // Add a data control. to control group // All parameter's meaning is same as the // functions with this kind result before. void AddDate(UINT nID, UINT lab, const CString &name, const CString &def, int chkmask, const CString &min1, const CString &max1); // Add a comboxBox to control group // parameters meaning is same as above. void AddComboBox(UINT nID, UINT lab, int dt, int ct, const CString &name, const CString &def, const CString &dict); // Add a label to control group. // cr : the color of lable. // tran: set to TRUE is transparent background void AddLabel(UINT nID, COLORREF cr=RGB(0,0,0), BOOL trans= TRUE); // Add a edit control to control group. // all meanings of parameter is same as above. // dt : data type , see definitions // ct: control type, see definitioins. void AddEdit ( UINT nID,UINT lab, int dt, int ct, const CString &name,const CString & def, int chkmask, const CString& min1, const CString &max1); // Add a button to control group. void AddButtons(UINT nID); // Clear the all inputted data to default condition.
这些函数获取每个控件的信息,但根据MFC请求,控件并不存在。我们通过以下函数进行初始化,调用后,控件的状态就准备好了。
void InitCotrols(CWnd *pParent,CXMLDict *dict);
控件与变量之间的数据交换
一项重要的事情是在控件和变量之间交换数据。我们使用MFC的标准方法——DoDataExchange
函数来交换数据。因此,控件中的所有值都会与变量进行交换,反之亦然。
void DoDataExchange(CDataExchange *pDX);
验证
要验证数据,您可以调用
// Check all data in the window, // if somebody does not satisfied , prompt user. BOOL CheckData(CWnd *wnd );
如果系统中发生错误,CheckData
将返回FALSE
。同时,它将根据初始化时设置的条件提示用户发现了一个错误。
XML 表示
这些控件组中的所有数据文件都使用XML。关于如何操作XML,请参阅我的Windows SDK DOM 接口的包装类文档。我已经将CXMLFile
类扩展到CXMLResult
和CXMLCmd
。数据控件初始化使用CXMLResult
。它具有以下格式:
<answer>
<recordset>
<record>
</record>
…………
<record>
</record>
<recordset>
</answer>
在“…………”部分,您可以编写任何带有值的标签。
CXMLCmd
的格式如下:
<__command>
<__parameter/>
<__group/>
<__order/>
</__command>
如何使用
使用控件组非常简单。您可以按照以下步骤操作:
- 步骤1。在表单声明中声明一个控件组
class CChldInfantLang : public CBitmapInnerDlg { CControlGroup m_cntGroup;
- 步骤2。声明本系统或对话框中使用的字典。
CXMLDict* m_pDict;
- 步骤3:添加一个函数作为初始化控件组的入口。
void PreInit();
- 步骤4:在表单的构造函数中添加初始化控件组和字典。
CChldInfantLang::CChldInfantLang(CWnd* pParent /*=NULL*/) : CBitmapInnerDlg(CChldInfantLang::IDD, pParent) { m_pDict = NULL; PreInit(); }
- 步骤5:在对话框的
DoDataExchange
函数中添加DoDataExchage
函数void CChldInfantLang::DoDataExchange(CDataExchange* pDX) { CBitmapInnerDlg::DoDataExchange(pDX); m_cntGroup.DoDataExchange (pDX); …………………………………. }
- 步骤6:调用控件组的
InitControl
完成控件组的初始化。BOOL CChldInfantLang::OnInitDialog() { CBitmapInnerDlg::OnInitDialog(); SetBitmap(IDB_BITMAP_PAPER); m_cntGroup.InitCotrols (this, m_pDict); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
- 步骤7:使用
CXMLResult
格式的配置文件在PreInit
函数中将初始化数据设置到控件。void CChldInfantLang::PreInit() { CString strPath = theApp.m_Path +_T("\\chldInfantLang.xml"); m_cntGroup.InitFromFile (strPath); }
- 步骤8:调用更新控件并以字符串格式获取XML数据以供进一步使用。
CString xml; CXMLCmd m_Cmd; UpdateData(); if(!CheckData ()) return; m_Cmd.InitCmd (); m_cntGroup .AddToXML (cmd); m_Cmd.GetXML (xml);
有待完善
- 支持更多控件,包括
ListBox
、TreeView
和ListView
控件。 - 处理诸如组禁用或组启用等操作。
- 处理如果控件中的某些内容发生变化,控件组将自动执行程序想要的操作并将控件设置为相应的状态。
- 支持Visual C++ .NET中的
CdhtmlDialog
。它与MFC的通用对话框有很大不同。
致谢
我采用了网络上许多现有的代码。我将列出我收集的所有内容,如果有人未被提及,请通知我。谢谢各位专家。
HMXCheckBox
,HMXEdit
,HMXNumEdit
- Massimo Colurcio - m.colurcio@softhor.comCXShadebutton
- ing.davide.pizzolato@libero.itCLabel
- 抱歉,我忘记了。CcoobBtn
- 抱歉,我忘记了。
就是这样。