




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MS Flex Grid控件是微软的一个网格控件,可以用于显示数据库中的信息,对于一些比较简单的显示方式,还是比较方便的。 加入MS Flex Grid控件控件的方法: 在VC中选择Project|Add to Project|Conpenments and Controls 在弹出的对话框中选择Registered ActiveX Controls然后选择Microsoft FlexGrid Control, version 6.0。系统会提示你加入几个类进入你的工程。包括四个类:CMSFlexGrid,CRowCursor,COleFont,CPicture;同时在VC的Control面板上会显示出MS Flex Grid控件的图标,可以同其他普通控件一样操作这个控件。一、引言 MSFlexGrid控件是Visual C+中提供的已注册ActiveX控件,它常被用于显示和操作表格式数据,特别是数据库文件的显示及交互操作。在其他程序的交互界面中,对于不确定数目的同类大批量数据的输入而言,MSFlexGrid是十分有效的。利用MSFlexGrid可以将输入文件中的数据显示出来并作交互修改,通过功能扩展可将表格数据直接copy到Excel、Word及Origin中的表格内,利用右键菜单实现此功能。本文编程实现了上述类似功能,并将MSFlexGrid控件的一些调整操作(如行高、列宽、Cell内容的对齐方式等)加以外部按钮化,使其更为方便易用。 二、先行者对MSFlexGrid控件功能的扩充 王勇、李延平1提出在MSFlexGrid的当前网格单元(Cell)内创建同样尺寸的编辑框(CEdit)覆盖该Cell,并将Cell内的Text传给编辑框,通过此编辑框以实现MSFlexGrid的网格编辑功能。秦胜2提出用信息预解释(PreTranslate)方法,截留编辑框(CEdit)内的ESC键与回车键(Enter)按下消息,以防止在编辑框内不小心按下上述两按键之一时立刻关闭对话框,退出整个程序。李强3在此基础上作了一些改进:对MSFlexGrid控件的Scroll消息响应中,若存在编辑框,则将其销毁。编辑框内ESC与Enter键消息的PreTranslate,以防止退出整个对话框程序。使编辑框同MSFlexGrid使用的字体一致。“高亮度”显示动态创建的编辑框。魏会君4用控件聚合技术实现MSFlexGrid控件的Cell编辑与修改功能,并指出可将聚合后的控件编写为一个完整的新的ActiveX控件,以备频繁使用。网上一篇文章5在VB中实现了可间隔的多列(multi Columns)选取功能,通过将已“选中”列的颜色设置为正常选中颜色(BackColorSel)来实现之。 三、本文的改进之处 本文除实现上述功能外,另作了如下改进: (1) 通过在当前网格单元(Current Cell)处创建同样尺寸的编辑框(CEdit)来实现对Cell内容的交互修改,由消息预解释(PreTranslateMessage)拦截编辑框内的ESC与Enter键的按下消息。在Cell内按ESC键时,Cell内的值维持原值不变且EditBox销毁(DestroyWindow),但当前Cell仍具有焦点(focus);再次编辑该Cell时,不能直接生成新的编辑框,可在其附近的Cell中单击后,再单击该Cell即可生成新的编辑框。在Cell内按Enter键时,Cell的值更新为EditBox内的值,同时下一个Cell自动进入编辑状态;其顺序为自动转到同一列的下一行Cell,若已到最大行数处,则转到下一列的起始Cell (FixedColumns不包括在内),若到整个MSFlexGrid的最末一个Cell,则按Enter键时,该Cell处的EditBox销毁但该Cell仍具有焦点,再对该Cell进行编辑的方法同上。 (2) 网格数据自身内部及与外部表格式数据文件间的copy/paste操作功能。将外部表格式数据源(如Excel文件)内的数值直接copy/paste至MSFlexGrid中,可减少输入工作量;有时需将至MSFlexGrid的部分数值输出到Word文件的表格或Origin的DataSheet用于绘图。本文利用系统剪贴板(Clipboard)来传送数值,考虑到MSFlexGrid的行之间的换行符号为“n”,而Word与Origin中的换行符号为“nr”(Excel自动兼容两种格式)。故由MSFlexGrid数值copy至Clipboard时,预先将将其中的“n”符号替换为“nr”,由外部文件paste至MSFlexGrid时作相反的替换。具体操作时,先选中MSFlexGrid内感兴趣的区域(考虑到使用方便,FixedRows/Cols不计在内),在MSFlexGrid外部的主控界面按鼠标右键自动弹出右键菜单,选择Copy或Paste即可。详见源程序中。 (3) MSFlexGrid网格(Cell)属性调整操作的外部按钮化 a. 单元格内的文本对齐方式,选中感兴趣的Cell Range,按“CellAligment”按钮,弹出对齐方式对话框,由水平与垂直方向两个ComboBox组成,选择合适的选项即可。Cell内的对齐方式共有09十种,其具体功能见表1. 表1、MSFlexGrid控件的CellAlignment 属性常数值描述FlexAlignLeftTop0单元内容顶部左对齐。 FlexAlignLeftCenter 1单元内容中间左对齐。对字符串的缺省设置值。 FlexAlignLeftBottom2单元内容底部左对齐。 FlexAlignCenterTop3单元内容顶部居中。 FlexAlignCenterCenter4单元内容中间居中。 FlexAlignCenterBottom5单元内容底部居中。 FlexAlignRightTop6单元内容顶部右对齐。 FlexAlignRightCenter7单元内容中间右对齐。对数字的缺省设置值。 FlexAlignRightBottom8单元内容底部右对齐。 FlexAlignGeneral9单元内容一般对齐方式。对字符串中间左对齐而对数值中间右对齐。 对齐方式对话框的垂直方向ComboV,共有三项可供选择:靠上、居中与靠下;水平方向ComboH,共有四项可供选择:常规、靠左、居中与靠右。其中,“常规”选项相当于值为9的对齐方式(即默认对齐方式),若选择此项则自动将垂直方向ComboV设置为“居中”且ComboV 处于Disabled状态;若选择“常规”此项,程序将ComboH与ComboV的选中状态转换为数值08,然后返回此数值。而进入对齐方式对话框时,则根据Cell的当前对齐方式设置ComboH与ComboV的初始选中状态。 b. 修改Title of Fixed Columns 在Fixed Columns处,双击单元格可出现编辑框交互修改Title.同样实现ESC与Enter按键消息的拦截,不过按下上述两键中的任一个时,该单元格(Cell)相应编辑框消失,同时与其紧相邻的正常Cell具有焦点(同正常Cell内用ESC键退出编辑时仅具有焦点一致)。因本程序中Title of Fixed Rows采用行号,由程序自动设置,故不必手工修改。 c. 调整行高、列宽 选中某一行或列,再拖动Splider控件即可调整该行或列的尺寸,同时以ToolTip方式显示行高或列宽的值(本文利用一免费的控件CMFECToolTip6来实现此显示功能)。当Splider控件停止拖动操作2秒后,该ToolTip自动消失。可由设置定时(SetTimer)与Splider相应的消息映射(OnReleasedcapture)两种方式来控制ToolTip的消失,本文采用定时法且同时将Splider恢复至中位并将iWidth0/ iHeight0更新为当前相应新值。在Splider拖动过程中,为保持行高或列宽变动的平滑性,作为基数的iWidth0保持不变(Splider的Range为020,iWidth0/ iHeight0相当与中位处pos10,故相应放大/缩小倍数为02)。按下Splider紧下方的“Slider2Center”按钮可将Splider恢复至中位,此时作为基数的iWidth0/ iHeight0亦被更新为当前相应新值iWidth/ iHeight. d. 行插入/删除 在Fixed Rows处,双击单元格可出现右键菜单,分为删除该行、在该行之前插新行两种情形。新插入行的Cell格式同选中行一致。由于行标同Excel格式一样采用行号,故行插入/删除后,行标自动重新调整。 e. 设置选定区域的颜色 选中感兴趣的Cell Range,按“Color”按钮,弹出颜色设置对话框,选择合适的颜色即可。Cell中的颜色设置用到COLORREF,它是一个32-bit整型数值,代表一种颜色,可使用RGB函数来初始化COLORREF.如将当前Cell的背景色设置为ToolTip中的背景色,用m_gridCtrl.SetCellBackColor(RGB(0xFF,0xFF,0xE1)便可实现。本文给出的颜色设置功能较为简单,至于如何实现MSFlexGrid控件Properties的Color属性页中类似的选择方式,本文仅提供一个解决方案以作参考:可利用VC+中的图像列表功能及取得MSFlexGrid控件Color属性页中相应图块的RGB值,再结合CcolorDialog即可实现之。 本文程序中设置的Cell颜色,在其它相关操作中未作考虑,有可能被重置为正常颜色(即Cell的BackColor为白色,ForeColor为黑色)。 f. 清空选定区域的内容 选中感兴趣的Cell Range,按“ Clear”按钮,可清空选定区域的内容。 g. 实现可间隔多行/列(multi Rows/Columns)的“选中” 通过同时按下“Ctrl”键与Fixed Rows/Columns处的鼠标左键点击(Click)来实现。本文通过全局字符串变量来表征被选中的可间隔的多行/列,对列用“:”+列号组成的字符串strColSel,对行用“;”+行号组成的字符串strRowSel.对不是当前选中行/列的“已选中” 行/列,采用设置其Cell的BackColor与ForeColor分别为BackColorSel与ForeColorSel来实现“选中”效果。Excel中按住“Ctrl”键的同时若先后两次选中同一列,效果同单次选中一样;而Origin中按住“Ctrl”键的同时若先后两次选中同一列,则该列自动从“被选中列组”中消失(即该列恢复至正常颜色),更为实用一些,本文实现了类似Origin中的选取功能。Origin中的上述选取列功能,主要是为了以选中列组为数据源绘制曲线图。除上述多行/列选择的操作之外的操作,将导致“被选中列组”自动消失,且非当前选中列的原“被选中列组”内的列自动恢复至正常色;此时的选择效果同正常状态一致。 本文程序的尚需改进之处:Cell的合并(Merge)功能;当MSFlexGrid下部出现Hscroll时,若第一列数值不在Fixed Rows的紧右边(即Hscroll的滑块不处于最左端时),此时选中某一行,相应Fixed Rows的Cell有可能被正常Cell产生的EditBox遮蔽,从而影响行插入/删除等操作,将Hscroll的滑块拉至最左端即可;被设置为特殊色的Cell,在多行/列选中、行插入/删除、及MSFlexGrid自身内部的Copy/Paste等操作后,仍能保持原特殊色;Cell其他属性(如对齐方式等)的遗传保留;及类似Excel中的格式刷功能等。 四、应用实例 下面为一实用计算程序的输入/输出界面部分,该程序由VC+编制主控程序,调用Matlab完成矩阵运算与计算结果的可视化,并将计算结果传回至主控程序。输入/输出界面利用MSFlexGrid控件以输入大批量的同类数值,并可与外部表格式数据文件间直接作copy/paste操作以减少输入/输出工作量。可由给定的支点数自动确定MSFlexGrid所需行数,手工输入数值,其中最右边一列为计算结果(该列以其他不同的颜色表示)不需输入。MSFlexGrid内的数值,也可由数值文件读入及保存至另外的文件。读入时的数值文件中,以“*”开头的行为注释行(读入时自动跳过该行),每行数值间的分隔符可采用Tab、“,”、空格(space)中的任意一种,不过同一数值文件的行内分隔符应统一,否则出错;最下边的列表框显示数值文件的原内容。保存至另外的文件时,每行数值间以“,”作分隔符,且会提示是否保存最右边一列数值。对话框上的ToMatlab按钮原为形成调用Matlab程序的输入字符串,并调用Matlab计算与显示及取回计算结果,本文程序中将最右边的计算结果一列改为求前面六列相应每行的数值和。程序的运行界面见图2与图3. 五、结束语 本文在先行者对VC+中MSFlexGrid控件功能扩展的基础上,通过“二次开发”进一步扩展了其功能,使其更为方便易用。最后给出了一个具体的应用实例,示例表明本文的程序是实用可靠的,可作为模块应用到其他程序中及形成一完整的新控件。 说明:为简单起见,本文程序仅考虑FixedRows与FixedCols具为1的情形。 本文程序的调试及运行环境为:Windows 98与MSVisual C+6.0 Enterprise EditionVC6.0中基于MSFlexGrid的可编辑表格的制作及其若干问题的解决方案2009-11-16 10:32一、 概述在我们制作的用户界面中很多时候会用到表格,当然我们首先想到的是用控件,如MSFlexGrid。我们可以方便的调用控件自身的函数来对表格中的元素进行操作,但是如果要设计一个可以编辑的表格,我们该怎么办呢?事实上这种可编辑表格的应用还真的不少,主要是其用户操作的交互性较好。笔者在前一阶段开发项目时遇到了这个问题,以下介绍笔者的实现方案。二、 可编辑表格的初步实现1、 创建新类CCtrlEditGrid首先创建一个单文档工程EditGrid。接着在工程中加入MSFlexGrid控件。这是个ActiveX控件,选择AddToProject的Components and Controls Gallery选项可加入该控件。然后以MSFlexGrid为基类创建新类CCtrlEditGrid,并添加成员函数void InitGrid()(该函数目前只是空的)和成员变量 CEdit* m_pEdit; CSpinButtonCtrl* m_pSpinButtonCtrl;以后表格的实体类就是该类。2、 在工程文件的视图类中显示表格首先在视图类CEditGridView中添加成员变量CCtrlEditGrid* m_pCtrlEditGrid。接着添加CEditGridView的消息相应函数OnCreate,在其中创建表格m_pCtrlEditGrid = new CCtrlEditGrid;m_pCtrlEditGrid-Create(NULL,WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,ID_EDITGRID); m_pCtrlEditGrid-InitGrid ( ); 然后为了和视图的大小保持一致在CEditGridView的消息相应函数OnSize中添加代码 if ( m_pCtrlEditGrid != NULL ) m_pCtrlEditGrid-MoveWindow(0,0,cx,cy);3、 实现CCtrlEditGrid的InitGrid的函数InitGrid完成表格的属性设置,表格初始内容的填写,可编辑控件的创建。这里的可编辑控件如CEdit,CComboBox,CSpinButtonCtrl,CDateTimeCtrl。在本例中只使用CEdit和CSinButtonCtrl的结合这一种。如果表格中不同列之间的编辑控件不同,在程序中可以通过检测列号,来决定使用什么控件,事实上在笔者的项目中不同列之间也是使用不同编辑控件的。在此用一种控件来说明表格编辑的实现方法,读者想换其他的控件也很容易了。void CCtrlEditGrid:InitGrid() /设置行数,列数 SetCols( COL_INITNUMBER ); SetRows( ROW_INITNUMBER ); /设置为无边框 SetBorderStyle(0); /设置为可以改变行高列宽 SetAllowUserResizing(3); /设置行宽列宽 CDC* pDC = GetDC();SetRowHeightMin ( ( long )( ROW_HEIGHT_PIXEL * 1440.0 / pDC-GetDeviceCaps(LOGPIXELSY) );/坐标单位要转换 for ( int i = 0; i GetDeviceCaps(LOGPIXELSX) ) ); ReleaseDC(pDC); /设置列的文字对齐方式 for ( i = 0 ; i COL_INITNUMBER ; i + ) SetColAlignment ( i, 4 ); /设置固定行列的名称 for ( i = 1; i ROW_INITNUMBER; i + ) CString strNum; int nNum = i; strNum.Format (%d, i); SetTextMatrix (i, 0, strNum ); for ( i = 1; i COL_INITNUMBER; i + ) CString strNum; int nNum = i; strNum.Format (%d, i); SetTextMatrix (0, i, strNum ); /填充Grid中的原始内容 for ( i = 1; i ROW_INITNUMBER; i + ) for ( int j = 1; j Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL|ES_NUMBER,CRect(0,0,0,0),this,ID_CTRL_EDIT); m_pSpinButtonCtrl = new CSpinButtonCtrl(); m_pSpinButtonCtrl-Create (UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | WS_BORDER , CRect(0,0,0,0),this,ID_CTRL_SPIN);这里要解释说明的是MSFLEXGRID中的单位是缇(1缇=1/1440in),所以在我们要指定单元格的长宽等时,要将像素单位转换为缇。如ROW_HEIGHT_PIXEL * 1440.0 / pDC-GetDeviceCaps(LOGPIXELSY)。其中ROW_HEIGHT_PIXEL是一个表示行高的像素单位的宏,pDC-GetDeviceCaps(LOGPIXELSY)得到Y轴每inch的像素值。该式计算后的值就是相应的以缇为单位的值。4、 让表格可以编辑以上三点只是准备阶段,要想使表格编辑,我们还要响应用户的点击单元格事件和离开单元格事件,以使得当用户点击某一单元格时当前单元格处于编辑状态而离开时又处于非编辑状态。MSFLEXGRID控件提供的OnClick和OnLeaveCell事件正好是我们所需要的。由于CCtrlEditGrid不是MFC类,所以不能用类向导来添加事件。只好用手工添加了。首先在头文件中添加afx_msg void OnLeaveCell();afx_msg void OnClick();接着在CPP文件中添加事件映射表BEGIN_EVENTSINK_MAP(CCtrlEditGrid, CMSFlexGrid)/AFX_EVENTSINK_MAP(CEditGrid)ON_EVENT_REFLECT(CCtrlEditGrid, 72 /* LeaveCell */, OnLeaveCell, VTS_NONE)ON_EVENT_REFLECT(CCtrlEditGrid, -600 /* Click */, OnClick, VTS_NONE)/AFX_EVENTSINK_MAPEND_EVENTSINK_MAP()(如果用户觉得手工添加时间映射表有困难,可以先在应用程序中添加一个虚设对话框。接着在对话框中插入MSFlexGrid控件。然后使用ClassWizard将事件处理程序写入对话框,接下来就可以参照着对话框编写事件映射表了。记得最后要删除虚设对话框。)接着添加OnLeaveCell和OnClick的函数体。OnLeaveCell函数:如果现在m_pEdit是显示的,则说明单元格是在编辑状态,所以要将数据从m_pEdit框读到表格中,然后将m_pEdit和m_pSpinButtonCtrl隐藏。void CCtrlEditGrid:OnLeaveCell() if ( m_pEdit-IsWindowVisible() ) int nCol; int nRow; CString strContent; nCol = GetCol(); nRow = GetRow(); m_pEdit-GetWindowText(strContent); SetTextMatrix(nRow, nCol, strContent); m_pEdit-ShowWindow(SW_HIDE); m_pSpinButtonCtrl-ShowWindow(SW_HIDE); OnClick函数:要在点击的单元格中显示m_pEdit和m_pSpinButtonCtrl,并使输入焦点在m_pEdit中,这里要说明的一点是在计算编辑控件要显示的位置时,如果FlexGrid控件有边框,就应该考虑边框宽度对位置的影响,在本例中我们在InitGrid中设置为无边框,故不用考虑。void CCtrlEditGrid:OnClick() CDC* pDC = GetDC(); long x = ( GetCellLeft() * pDC - GetDeviceCaps ( LOGPIXELSX ) ) / 1440; long y = ( GetCellTop() * pDC - GetDeviceCaps ( LOGPIXELSY ) ) / 1440; long cx = ( GetCellWidth() * pDC - GetDeviceCaps ( LOGPIXELSX ) ) / 1440; long cy = ( GetCellHeight() * pDC - GetDeviceCaps ( LOGPIXELSY ) )/ 1440; ReleaseDC ( pDC ); CString strContent; strContent = GetText(); m_pEdit-SetWindowText(strContent); m_pEdit-MoveWindow(x,y,cx,cy,FALSE); m_pEdit-ShowWindow(SW_SHOW); m_pEdit-SetFocus ( ); m_pSpinButtonCtrl-SetBuddy (m_pEdit); m_pSpinButtonCtrl-SetRange32( 0, 100); m_pSpinButtonCtrl-MoveWindow ( x + cx 16, y, 16,cy,FALSE ); m_pSpinButtonCtrl-ShowWindow(SW_SHOW);也许OnEnterCell事件可以替代OnClick,但笔者发现用OnEnterCell实现起来会有一个问题:必须快速的点击,否则编辑框出现之后马上消失。所以笔者使用OnClick事件,该事件是在鼠标Up的时候才响应的。三、 若干问题的出现及解决方案通过以上的操作,我们可以在表格中点击某一个单元格进行编辑了,似乎我们已经实现了一个可编辑表格的制作。但在随后的测试过程中发现了如下讨厌的问题:a在当前某个单元格处于可编辑状态而我们试图改变列宽时,发现在单元格上的编辑控件的大小并没有改变。如下b在当前某个单元格处于可编辑状态而我们试图移动滚动条时,发现在单元格上的编辑控件的光标随之移动到了别的单元格。而且更加严重的是若点击前单元格部分显示,点击后再移动滚动条发现不只是光标移动还有控件本身也移动到了别的单元格中。如下c在点击上下控件时会触发垂直滚动条的移动,还间接导致b问题的发生。1、 a问题的解决首先想到的是在MSDN中寻找MSFLEXGRID的列宽改变的响应事件,很失望没找到。但发现可以采取以下措施:在CEditGridView中的PreTranslateMessage消息响应函数中捕捉鼠标左键是按下状态并且鼠标移动的消息,在这种状态下若发现编辑控件是显示的,就调用CCtrlEditGrid的Onleave函数(开放为PUBLIC)。这样虽然在改变列宽时原来的编辑状态变为了非编辑状态,但避免了显示上不同步改变大小的问题。BOOL CEditGridView:PreTranslateMessage(MSG* pMsg) if ( ( pMsg-message = WM_MOUSEMOVE ) & ( pMsg-wParam & MK_LBUTTON ) ) CWnd* pWnd = FromHandle ( pMsg-hwnd ); if ( pWnd-GetRuntimeClass ( )-IsDerivedFrom ( RUNTIME_CLASS ( CMSFlexGrid ) ) ) if ( m_pCtrlEditGrid-m_pEdit-IsWindowVisible() ) m_pCtrlEditGrid-OnLeaveCell(); return CView:PreTranslateMessage(pMsg);2、 b问题的解决首先想到的依然是在MSDN中寻找MSFLEXGRID的列宽改变的响应事件,很幸运找到了。在CCtrlEditGrid的头文件中添加 afx_msg void OnScroll();在CCtrlEditGrid的CPP文件的事件映射表中添加ON_EVENT_REFLECT(CTaskEditGrid, 73 /* Scroll */, OnScr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建设行业考试题库及答案
- 森林消防员课件
- 棋牌业务经理知识培训课件
- 桥涵水文教学课件
- 桥梁结构基础知识培训课件
- 2025年粮食检验领域专家级面试题答案详解及解析
- 2025年外贸经理人认证考试指南与预测题
- 2025建筑工程中级职称考试《专业基础知识》考试题库及答案
- 2025年公路水运工程试验检测师公共基础试题库(法规与技术标准)及答案
- 2025篮球裁判手势试题及答案
- 2025年北京市中考语文真题(含答案)
- 小学英语“教学评一体化”实施
- 中国移动网络割接管理办法(2020版)
- IATF16949质量体系年度过程指标范例
- 护理伦理与卫生法律法规高职PPT完整全套教学课件
- 广东建筑材料检测员上岗考试卷
- 游泳社会指导员专项理论考试复习题库汇总(附答案)
- 工程量确认单
- JJG 966-2010手持式激光测距仪
- 大数据与金融课件
- CS4000高级过程控制实验装置设备操作说明书
评论
0/150
提交评论