摘要:本文主要介绍了一种通过控件聚合技术来为网格控件FlexGrid增添PickList
功能的
方法。
@H_
502_5@
@H_
502_5@
前言
@H_
502_5@
@H_
502_5@ 在对
数据库进行数据录入时,PickList
功能能极大的方便
用户,在dELPHI
程序中的DBgrid控件就直接提供了PickList
功能,但VB和VC下的DBgrid和MSFlexGrid却没有提供相应的
功能,FlexGrid甚至连直接编辑网格的能力都没有提供。经过笔者的探索,在VC++下通过标准控件和ActiveX控件相聚合的技术成功地为FlexGrid控件
增加了编辑和PickList的能力,使之成为真正
功能强大的网格控件。
@H_
502_5@
@H_
502_5@
方案设计
@H_
502_5@
@H_
502_5@ 由于FlexGrid控件不允许对网格单元进行编辑,因此如果要在其上实现PickList
功能就首先要有一组合框来与其配合共同实现该
功能:在鼠标或光标(即当前焦点)移到FlexGrid的某个网格时,通过事件响应来激发组合框的
显示,并且要求组合框在位置、大小等方面与FlexGrid的当前网格完全重合。
显示的组合框的当前值为其所在网格原先的取值,在
用户通过鼠标完成对
内容的选择后再将
用户的选择结果输送回网格。而一旦该网格不再需要编辑(即失去焦点)时组合框应当隐藏。从整个设计过程来看,FlexGrid并不是直接同
用户进行交互的,而是通过组合框的中介来完成的。FlexGrid只负责数据的
显示和组织,PickList
功能是由动态
显示的组合框来完成。
用户丝毫不会意识到两个控件的存在,唯一的感觉只会是FlexGrid控件增添了PickList
功能。
@H_
502_5@
@H_
502_5@ 控件聚合的过程中有两个地方是比较关键的,也是程序实现的重点:一个是当鼠标点击网格单元时,能通过事件的触发在网格上覆盖一个与其等大的组合框,并完成网格数据向组合框的传送;另一点是当
用户完成对组合框
内容的选择后能将组合框从当前位置隐藏,并将
用户选择的结果返回与其对应的网格单元。
@H_
502_5@
@H_
502_5@
编码实现
@H_
502_5@
@H_
502_5@ 在进行程序编码之前首先要通过
添加组件和控件的方式向程序中
添加FlexGrid控件,Visual Stu
dio 提供有此控件--Microsoft FlexGrid Control,version 6.0。由于在程序中需要准确地将组合框同网格控件的单元格相聚合,因此手工拖动FlexGrid到对话框是无法同组合框准确定位的,因此需要通过SetWindowPos()
函数在像素级上动态设定网格控件在对话框中的具体位置:
@H_
502_5@
@H_
502_5@
//获取客户区矩形@H_502_5@ CRect rcBounds;@H_502_5@ GetClientRect(&rcBounds);@H_502_5@ //设定FlexGrid控件在对话框中的位置和大小@H_502_5@ m_ctlMSFlexGrid.SetWindowPos(&wndTop,rcBounds.left,rcBounds.top,rcBounds.Width(),@H_502_5@ rcBounds.Height(),NULL); |
@H_
502_5@ 用来接受
用户输入的组合框控件在程序运行之初,如果
用户进行输入操作,是
不显示的,只有在
用户发出鼠标单击的消息需要进行编辑时才将其
显示,因此需要将组合框控件的初始
属性设为不可见。通过前面的方案设计可以看出,整个操作的全过程无非是对鼠标和焦点的消息响应和处理。通过FlexGrid控件响应鼠标单击的事件可以得知
用户是否进行编辑操作,并在捕获到该操作后,通过对消息的响应完成
用户输入信息从组合框到网格单元的复制:
@H_
502_5@
@H_
502_5@
//对FlexGrid控件的单击响应@H_502_5@ BEGIN_EVENTSINK_MAP(CFlexGridDlg,CDialog)@H_502_5@ //{{AFX_EVENTSINK_MAP(CFlexGridDlg)@H_502_5@ ON_EVENT(CFlexGridDlg,IDC_MSFLEXGRID,-600 /* Click */,OnClickMsflexgrid,VTS_NONE)@H_502_5@ //}}AFX_EVENTSINK_MAP@H_502_5@ END_EVENTSINK_MAP()@H_502_5@ ……@H_502_5@ //鼠标单击消息的响应处理@H_502_5@ //计算被选中的单元格的坐标,以便组合框能恰好与之吻合@H_502_5@ long lRow = m_ctlMSFlexGrid.GetRowSel(); @H_502_5@ long lCol = m_ctlMSFlexGrid.GetColSel();@H_502_5@ ……@H_502_5@ // MSFlexGrid 控件的函数的长度单位是"缇(twips)",@H_502_5@ //需要将其转化为像素,1440 缇 = 1 英寸@H_502_5@ int nTwipsPerDotX = 1440 / pDC->GetDeviceCaps(LOGPIXELSX) ;@H_502_5@ int nTwipsPerDotY = 1440 / pDC->GetDeviceCaps(LOGPIXELSY) ;@H_502_5@ ……@H_502_5@ //将缇转换为像素@H_502_5@ long lCellWidth = m_ctlMSFlexGrid.GetCellWidth()/ nTwipsPerDotX;@H_502_5@ long lCellHeight = m_ctlMSFlexGrid.GetCellHeight()/ nTwipsPerDotY;@H_502_5@ long lCellLeft = m_ctlMSFlexGrid.GetCellLeft() / nTwipsPerDotX;@H_502_5@ long lCellTop = m_ctlMSFlexGrid.GetCellTop() / nTwipsPerDotY; |
@H_
502_5@ 在完成对网格单元的坐标计算及转换后,需要动态调整组合框的坐标位置及大小,使其能与当前网格单元相配,同时把焦点由当前的网格单元转移到组合框上,从而实现两控件的聚合:
@H_
502_5@
@H_
502_5@
//设置组合框坐标@H_502_5@ m_ctlPickList.SetWindowPos(&wndTop,lCellLeft,lCellTop,lCellWidth,lCellHeight,NULL);@H_502_5@ //将焦点转移到组合框@H_502_5@ m_ctlPickList.SetFocus();@H_502_5@ //将改动完毕的组合框变为可视@H_502_5@ m_ctlPickList.ShowWindow(SW_SHOW); |
@H_
502_5@ 如果此时的网格原先已有
内容,此时亦应当将
内容转移到组合框中,在
用户修改后再作回存处理:
@H_
502_5@
@H_
502_5@
CString sData = m_ctlMSFlexGrid.GetText(); //获取原先的内容@H_502_5@ if(sData=="紧急") //网格内容为"紧急"@H_502_5@ m_ctlPickList.SetCurSel(0); //设置组合框显示第一项内容"紧急"@H_502_5@ else if(sData=="一般") //网格内容为"一般"@H_502_5@ m_ctlPickList.SetCurSel(1); //设置组合框显示第二项内容"一般"@H_502_5@ else //网格内容为"暂缓"@H_502_5@ m_ctlPickList.SetCurSel(2); //设置组合框显示第三项内容"暂缓" |
@H_
502_5@ 此时只能接收
用户的输入,当对下一单元进行编辑时输入过的数据并没有保存到网格中,因此在组合框控件失去焦点时应完成当把当前
用户修改过的
内容回存到单元格的处理。具体来说,是对组合框ON_KILLFOCUS消息的响应:
@H_
502_5@
@H_
502_5@
int i=m_ctlPickList.GetCurSel(); //根据组合框的当前选项决定回存的内容@H_502_5@ if(i==0)@H_502_5@ sInputData="紧急";@H_502_5@ if(i==1)@H_502_5@ sInputData="一般";@H_502_5@ if(i==2)@H_502_5@ sInputData="暂缓";@H_502_5@ ……@H_502_5@ m_ctlMSFlexGrid.SetText(sInputData);//将用户的选择写入网格控件@H_502_5@ m_ctlPickList.ShowWindow(SW_HIDE); //隐藏组合框 |
@H_
502_5@ 通过以上几步编码基本上实现了对FlexGrid控件和组合框控件的聚合,并通过这种聚合技术成功地为FlexGrid控件增添了PickList
功能,不仅方便了
用户的使用,也使人机界面更为友好。下图就是一个使用了本文所述控件聚合技术实现的具有PickList能力的程序界面,从界面上和使用
效果看根本感觉不出是两种各自相互独立组件的作用结果,同Delphi提供的DBGrid控件在
效果上很相似:
@H_
502_5@
@H_
502_5@
@H_
502_5@
小结 本文所述控件聚合
方法具有很好的通用性和可扩展性,不仅在本文可以实现PickList
功能,也可以通过类似的
方法来实现Windows标准控件同自己或是第三方开发的ActiveX控件的聚合,来拓展原有控件的
功能。甚至还可将聚合后的控件编写为一个新的Active X控件作为一个完整的控件以备频繁使用。综上所述,利用控件聚合技术可以在较小编码量的前提下大大扩展基本控件的
功能,有着很好的应用前景。本文所述程序在Windows 98下,由Microsoft Visual C++ 6.0编译通过。