基于MFC对话框的GridfCtrl显示SQL表格
2017-01-12 21:31
232 查看
mfc对话框显示表格有那么几种方法:使用微软的CListCtrl控件,使用Joe和chris编写的GridCtrl控件等。
GridCtrl更专业些。这款控件出世将近20年,使用也很广泛。但是用于显示SQL表格的帮助文件较少。在网上找到10年前Mazdak写的教程,尝试并实现,对他表示感谢。
Mazdak-Binding MFC Grid to database
1、新建MFC对话框 IDD_DataOut,类名CDataOut,生成DataOut.h和DataOut.cpp;
2、将GridCtrl.cpp、GridCtrl.h等文件加到工程中,并编译
添加GridCtrl_src下文件后,VS2010编译报错:
gridctrltest\memdc.h(26): error C2011: “CMemDC”:“class”类型重定义
解决办法重命名CMemDC为GCMemDC,记得同时修改MemDC.h及GridCtrl.cpp所有用到的CMemDC项。
编译通过。
3、在对话框IDD_DataOut中增加Custom Control,如下
控件属性如下,Class项要写MFCGridCtrl
4、在文件DataOut.h中增加成员
5、在DataOut.cpp文件里的函数DoDataExchange增加映射:
6、在对话框初始化函数中实现控件的显示,若没有控件显示程序,整个对话框都无法显示,这点困扰了我好长时间。
调用函数如下:
4、在DataOut.h中
第5步同上文
6、ADO方式连接数据库,简单介绍如下:
在stdafx.h中加入:#import “c:/program files/common files/system/ado/msado15.dll” no_namespace rename (“EOF”, “adoEOF”)
在项目头文件中添加
在项目cpp文件中添加
具体mfc连接sql中注意问题和连接字符串相关内容,后续补充补充内容链接。
然后在DataOut.cpph中调用Fillgrid()函数
CheckVariant()函数
记录复制函数如下,可以选中内容复制到excel中
效果图:
GridCtrl更专业些。这款控件出世将近20年,使用也很广泛。但是用于显示SQL表格的帮助文件较少。在网上找到10年前Mazdak写的教程,尝试并实现,对他表示感谢。
Mazdak-Binding MFC Grid to database
一、首先介绍GridCtrl应用于简单表格的建立。
GridCtrl原文教程和源码地址1、新建MFC对话框 IDD_DataOut,类名CDataOut,生成DataOut.h和DataOut.cpp;
2、将GridCtrl.cpp、GridCtrl.h等文件加到工程中,并编译
添加GridCtrl_src下文件后,VS2010编译报错:
gridctrltest\memdc.h(26): error C2011: “CMemDC”:“class”类型重定义
解决办法重命名CMemDC为GCMemDC,记得同时修改MemDC.h及GridCtrl.cpp所有用到的CMemDC项。
编译通过。
3、在对话框IDD_DataOut中增加Custom Control,如下
控件属性如下,Class项要写MFCGridCtrl
4、在文件DataOut.h中增加成员
#pragma once #include "GridCtrl.h" class CDataOut : public CDialogEx { DECLARE_DYNAMIC(CDataOut) public: CDataOut(CWnd* pParent = NULL); // 标准构造函数 virtual ~CDataOut(); CGridCtrl m_pGrid; void GridCtrlInit(); // 对话框数据 enum { IDD = IDD_DataOut };
5、在DataOut.cpp文件里的函数DoDataExchange增加映射:
void CDataOut::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_datagrid, m_pGrid); }
6、在对话框初始化函数中实现控件的显示,若没有控件显示程序,整个对话框都无法显示,这点困扰了我好长时间。
BOOL CDataOut::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 GridCtrlInit();//调用函数 return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE }
调用函数如下:
void CDataOut::GridCtrlInit() { m_pGrid.SetEditable(true); m_pGrid.SetTextBkColor(RGB(0xFF, 0xFF, 0xE0));//黄色背景 m_pGrid.SetRowCount(8); //初始为10行 m_pGrid.SetColumnCount(8); //初始化为11列 m_pGrid.SetFixedRowCount(1); //表头为一行 m_pGrid.SetFixedColumnCount(1); //表头为一列 for (int row = 0; row < m_pGrid.GetRowCount(); row++) for (int col = 0; col < m_pGrid.GetColumnCount(); col++) { //设置表格显示属性 GV_ITEM Item; Item.mask = GVIF_TEXT|GVIF_FORMAT; Item.row = row; Item.col = col; m_pGrid.SetRowHeight(row,25); //设置各行高 m_pGrid.SetColumnWidth(0,64); //设置0列宽 m_pGrid.SetColumnWidth(col,64); //设置各列宽 if(row==0&&col==0) //第(0,0)格 { Item.nFormat = DT_CENTER|DT_WORDBREAK; Item.strText.Format(_T("报表显示"),col); } else if (row < 1) //设置0行表头显示 { Item.nFormat = DT_CENTER|DT_WORDBREAK; Item.strText.Format(_T(" 项目%d"),col); } else if (col < 1) //设置0列表头显示 { if(row< m_pGrid.GetRowCount()) { Item.nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS; Item.strText.Format(_T("第%d次"),row); } } else { Item.nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS; Item.strText.Format(_T(""),2); } m_pGrid.SetItem(&Item); } }
二、显示SQL表格并复制某些行记录
前三步骤同上。4、在DataOut.h中
#include "GridCtrl_src\GridCtrl.h" #include "math.h" // CDataOut 对话框 class CDataOut : public CDialogEx { DECLARE_DYNAMIC(CDataOut) public: CDataOut(CWnd* pParent = NULL); // 标准构造函数 virtual ~CDataOut(); // CDataOut* m_dataout; void GridCtrlInit(); // 对话框数据 enum { IDD = IDD_DataOut }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 HICON m_hIcon; DECLARE_MESSAGE_MAP() public: virtual BOOL OnInitDialog(); CGridCtrl m_pGrid; CString m_strDataSource; CString m_strQuery; int FillGrid(void); _RecordsetPtr pRecordset; private: void CheckVariant(_variant_t vtFld,int propType); double dval; long lval; CY cyVal; CList<int,int> m_listIntegerCol; CList<int,int> m_listDateCol; _bstr_t str; COleDateTime date; BOOL bdate; BOOL bCY; BOOL blong; BOOL bfloat; public: afx_msg void OnBnClickedCopy(); };
第5步同上文
6、ADO方式连接数据库,简单介绍如下:
在stdafx.h中加入:#import “c:/program files/common files/system/ado/msado15.dll” no_namespace rename (“EOF”, “adoEOF”)
在项目头文件中添加
_ConnectionPtr m_pConnection; //+ ADO连接变量指针
在项目cpp文件中添加
CoInitialize(NULL); //初始化Com组件 m_pConnection.CreateInstance(__uuidof(Connection)); try { m_pConnection->Open("Provider=SQLOLEDB.1; Data Source=10.**.**.**\\SQLEXPRESS,1433;Database=maintenance;Persist Security Info=False;UID=sa;PWD=123456;","","",NULL);//连接字符串 } catch(_com_error e) //捕捉异常 { AfxMessageBox(e.ErrorMessage()); } CoUninitialize(); //释放com组件
具体mfc连接sql中注意问题和连接字符串相关内容,后续补充补充内容链接。
然后在DataOut.cpph中调用Fillgrid()函数
BOOL CDataOut::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // CDataOut m_gridctrl;//定义对象 FillGrid();//调用函数 // GridCtrlInit(); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE }
int CDataOut::FillGrid(void) { CString sqlStr; sqlStr = "select * from maintenance_record_tb"; //+打开数据库 pRecordset.CreateInstance(__uuidof(Recordset)); try { pRecordset->Open((_variant_t)sqlStr, theApp.m_pConnection.GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText); } catch(_com_error *e) { AfxMessageBox(e->ErrorMessage()); } m_pGrid.DeleteAllItems(); m_pGrid.SetListMode(true); m_pGrid.SetHeaderSort(true); try { FieldsPtr fs = pRecordset->GetFields(); int iCol = fs->Count+1; m_pGrid.SetColumnCount(iCol); m_pGrid.SetFixedRowCount(); m_pGrid.SetFixedColumnCount(); m_pGrid.SetColumnWidth(0,20); iCol = m_pGrid.GetColumnCount(); for(int i = 0 ; i < (int)fs->GetCount() ; i++) { _variant_t index; index.Clear(); index.vt = VT_I2; index.iVal = i ; CString str = (LPSTR) fs->GetItem(index)->GetName(); m_pGrid.SetItemText(0,i+1,str); } int iRow = 1; while(!pRecordset->adoEOF) { m_pGrid.InsertRow(""); for(int i = 0 ; i < (int)fs->GetCount() ; i++) { _variant_t index; index.Clear(); index.vt = VT_I2; index.iVal = i ; _variant_t vtFld; vtFld.Clear(); vtFld =pRecordset->Fields->GetItem(fs->GetItem(index)->GetName())->Value; int propType = (int)fs->GetItem(index)->GetType(); bdate=false; blong = false; bfloat = false; bCY= false; CheckVariant(vtFld,propType);//下文实现 if(blong!=false || bfloat!=false) { CString str1; if(blong) { m_pGrid.SetCellType(iRow,i+1, RUNTIME_CLASS(CGridCell)); str1.Format("%d",lval); } else str1.Format("%f",dval); m_pGrid.SetItemText(iRow,i+1,str1); m_listIntegerCol.AddTail((i+1)); } else if(bdate) { CString str1 = date.Format(_T("%d/ %m/ %Y")); m_listDateCol.AddTail(i+1); m_pGrid.SetItemText(iRow,i+1,str1); } else if(bCY) { COleCurrency cur = (COleCurrency)cyVal; m_listIntegerCol.AddTail((i+1)); m_pGrid.SetItemText(iRow,i+1,cur.Format()); } else { m_pGrid.SetItemText(iRow,i+1,str); str = ""; } } iRow++; pRecordset->MoveNext(); } } catch(_com_error e) { AfxMessageBox(e.ErrorMessage()); return E_FAIL; } return 0; }
CheckVariant()函数
void CDataOut::CheckVariant(_variant_t vtFld, int propType) { switch(vtFld.vt) { case VT_CY: { cyVal = vtFld.cyVal; bCY = true; break; } case VT_R4: { dval = vtFld.fltVal; bfloat=true; break; } case VT_R8: { dval = vtFld.dblVal; bfloat=true; break; } case VT_DECIMAL: { if(adDecimal==propType || adNumeric==propType) { dval = vtFld.decVal.Lo32; dval *= (vtFld.decVal.sign == 128)? -1 : 1; dval /= pow(10.0, vtFld.decVal.scale); bfloat=true; } else { lval = vtFld.decVal.Lo32; lval *= (vtFld.decVal.sign == 128)? -1 : 1; lval /= pow(10*1.0, vtFld.decVal.scale); blong=true; } break; } case VT_UI1: { lval = vtFld.iVal; blong=true; break; } case VT_BOOL: { lval = vtFld.boolVal; if(lval==-1) lval = 1; blong=true; break; } case VT_I2: { lval = vtFld.iVal; blong=true; break; } case VT_I4: { lval = vtFld.lVal; blong=true; break; } case VT_INT: { lval = vtFld.intVal; blong=true; break; } case VT_DATE: { date = (COleDateTime)vtFld.date; bdate = true; break; } case VT_NULL: case VT_EMPTY: { break; } default: str = vtFld.bstrVal; //break; } }
记录复制函数如下,可以选中内容复制到excel中
void CDataOut::OnBnClickedCopy() { // TODO: 在此添加控件通知处理程序代码 COleDataSource* pSource = m_pGrid.CopyTextFromGrid(); if (!pSource) return; pSource->SetClipboard(); MessageBox("复制成功,粘贴至别处","",0); }
效果图:
相关文章推荐
- MFC基于对话框的用Picture Control显示OpenGL
- 如何实现基于MFC对话框的PCL显示(1)
- 在基于对话框的MFC程序中,使程序在任务栏中不显示图标
- 给基于对话框的MFC程序添加状态栏并实时显示时间
- MFC 基于对话框的图片控件(picture)动态加载.bmp图片并显示
- 如何实现基于MFC对话框的PCL显示
- 基于对话框的MFC程序中,实现非模态子窗口在任务栏显示图标以及窗口左上角加图标
- MFC基于对话框的Media Player如何实现全屏显示功能?
- 给基于对话框的MFC程序添加状态栏并实时显示时间
- 给基于对话框的MFC程序添加状态栏并实时显示时间(转)
- 基于Dialog的MFC对话框上利用OpenCV 3.0显示图片
- Visual Studio 2013 MFC基于对话框的程序中加入TeeChart控件后,编译时显示不能实例化抽象类的问题
- 在基于对话框的MFC程序中,使程序在任务栏中不显示图标
- 在基于对话框的MFC创建状态栏以及添加时间显示
- VC6_基于对话框MFC程序最基础教程示例~
- MFC中基于对话框程序快捷键的实现
- 在MFC GridCtrl中使用CGridCellCheck类根据GetCheck()状态做不同处理的实现
- 基于对话框的图片打开与显示
- 将基于MFC的对话框应用程序修改为服务程序
- MFC 基于对话框 程序的打包有感!!!