TXLDlg.cpp
// TXLDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "TXL.h"
#include "TXLDlg.h"
#include "afxdialogex.h"
// CTXLDlg 对话框
struct infomation
{
long long BH; //编号
CString bh; //编号 数据库
CString XM; //姓名
CString XB; //性别
CString XH; //学号
CString DH; //电话
CString QQ; //QQ
CString ZH; //住址
}stinfo[10];
IMPLEMENT_DYNAMIC(CTXLDlg, CDialogEx)
CTXLDlg::CTXLDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_DIALOG2, pParent)
{
}
CTXLDlg::~CTXLDlg()
{
}
void CTXLDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TXL_LIST, m_TXLList);
}
BEGIN_MESSAGE_MAP(CTXLDlg, CDialogEx)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_TXL_LIST, &CTXLDlg::OnLvnItemchangedTxlList)
ON_NOTIFY(NM_CLICK, IDC_TXL_LIST, &CTXLDlg::OnNMClickTxlList)
ON_BN_CLICKED(IDC_DR_BUTTON, &CTXLDlg::OnBnClickedDrButton)
ON_BN_CLICKED(IDC_DC_BUTTON, &CTXLDlg::OnBnClickedDcButton)
END_MESSAGE_MAP()
// CTXLDlg 消息处理程序
BOOL CTXLDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加额外的初始化
m_TXLList.EnsureVisible(m_TXLList.GetItemCount() - 1, FALSE); //滚动条
bIsCreateEdit = false; // 还没有创建编辑框
bIsCreateCombobox = false; //还没有创建下拉列表框
CRect rect; //获取list的客户区,方便调节每一列的宽度
m_TXLList.GetClientRect(&rect);
m_TXLList.SetExtendedStyle(m_TXLList.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_TXLList.InsertColumn(0, _T("编号"), LVCFMT_LEFT, rect.right / 7, 0);
m_TXLList.InsertColumn(1, _T("姓名"), LVCFMT_LEFT, rect.right / 7, 1);
m_TXLList.InsertColumn(2, _T("性别"), LVCFMT_LEFT, rect.right / 7, 2);
m_TXLList.InsertColumn(3, _T("学号"), LVCFMT_LEFT, rect.right / 7, 3);
m_TXLList.InsertColumn(4, _T("电话"), LVCFMT_LEFT, rect.right / 7, 4);
m_TXLList.InsertColumn(5, _T("QQ"), LVCFMT_LEFT, rect.right / 7, 5);
m_TXLList.InsertColumn(6, _T("住址"), LVCFMT_LEFT, rect.right / 7, 6);
/*for (int i = 0; i <= 0; i++) { m_TXLList.InsertItem(i, _T("")); m_TXLList.SetItemText(i, 0, _T("")); m_TXLList.SetItemText(i, 1, _T("")); m_TXLList.SetItemText(i, 2, _T("")); m_TXLList.SetItemText(i, 3, _T("")); m_TXLList.SetItemText(i, 4, _T("")); m_TXLList.SetItemText(i, 5, _T("")); m_TXLList.SetItemText(i, 6, _T("")); }*/
//AfxOleInit(); //初始化COM并结束时关闭
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CTXLDlg::OnLvnItemchangedTxlList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
void CTXLDlg::OnNMClickTxlList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
NM_LISTVIEW *pEditCtrl = (NM_LISTVIEW *)pNMHDR; /////////// &&&&& important &&&////////////////////////////////////////////////
//printf("行:%d,列:%d\n", pEditCtrl->iItem, pEditCtrl->iSubItem);
if (pEditCtrl->iItem == -1)//点击到非工作区
{
if (bIsCreateEdit == true)//如果之前创建了编辑框就销毁掉
{
DistroyEdit(&m_TXLList, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
bIsCreateEdit = false;
}
if (bIsCreateCombobox == true)//如果之前创建了下拉列表框就销毁掉
{
DistroyCombobox(&m_TXLList, &m_ComBox, e_Item, e_SubItem);
bIsCreateCombobox = false;
}
}
else if (pEditCtrl->iSubItem != 2)//如果不是性别选项
{
if (bIsCreateCombobox == true)//如果之前创建了编辑框就销毁掉
{
DistroyCombobox(&m_TXLList, &m_ComBox, e_Item, e_SubItem);
bIsCreateCombobox = false;
}
if (bIsCreateEdit == true)
{
if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
{
DistroyEdit(&m_TXLList, &m_Edit, e_Item, e_SubItem);
bIsCreateEdit = false;
CreateEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, bIsCreateEdit);//创建编辑框
m_TXLList.InsertItem(pEditCtrl->iItem, _T("")); ///////***************************************************************
}
else//点中的单元格是之前创建好的
{
m_Edit.SetFocus();//设置为焦点
}
}
else
{
e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
CreateEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, bIsCreateEdit);//创建编辑框
m_TXLList.InsertItem(pEditCtrl->iItem, _T("")); //////***************************************************************
}
}
else//如果是性别选项,在单元格处生成下拉列表项
{
if (bIsCreateEdit == true)//如果之前创建了编辑框就销毁掉
{
DistroyEdit(&m_TXLList, &m_Edit, e_Item, e_SubItem);
bIsCreateEdit = false;
}
if (bIsCreateCombobox == true)
{
if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
{
DistroyCombobox(&m_TXLList, &m_ComBox, e_Item, e_SubItem);
bIsCreateCombobox = false;
CreateCombobox(pEditCtrl, &m_ComBox, e_Item, e_SubItem, bIsCreateCombobox);//创建编辑框
m_TXLList.InsertItem(pEditCtrl->iItem, _T("")); //////***************************************************************
m_ComBox.AddString(L"男"); ///*****
m_ComBox.AddString(L"女");
m_ComBox.ShowDropDown();//自动下拉
}
else//点中的单元格是之前创建好的
{
m_ComBox.SetFocus();//设置为焦点
}
}
else
{
e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
CreateCombobox(pEditCtrl, &m_ComBox, e_Item, e_SubItem, bIsCreateCombobox);//创建编辑框
m_TXLList.InsertItem(pEditCtrl->iItem, _T("")); //////***************************************************************
m_ComBox.AddString(L"男");
m_ComBox.AddString(L"女");
m_ComBox.ShowDropDown();//自动下拉
}
}
*pResult = 0;
}
void CTXLDlg::CreateEdit(NM_LISTVIEW *pEditCtrl, CEdit *CtEdit, int &Item, int &SubItem, bool &bIsCreateEdit)//创建单元格编辑框函数
//pEditCtrl为列表对象指针,CreateEdit为编辑框指针对象,Item为创建单元格在列表中的行,SubItem则为列,bIsCreateEdit为对象创建标记
{
Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
CtEdit->Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN,CRect(0, 0, 0, 0), this, IDC_EDIT_CREATEID);//创建编辑框对象,IDC_EDIT_CREATEID为控件ID号3000,在文章开头定义
bIsCreateEdit = true;
CtEdit->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
CtEdit->SetParent(&m_TXLList);//将list control设置为父窗口,生成的Edit才能正确定位,这个也很重要
CRect EditRect;
m_TXLList.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
EditRect.SetRect(EditRect.left + 1, EditRect.top + 1, EditRect.left + m_TXLList.GetColumnWidth(e_SubItem) - 1, EditRect.bottom - 1);//+1和-1可以让编辑框不至于挡住列表框中的网格线/////////////////////// EditRect.top - 1? EditRect.bottom + 1?*******************************************
CString strItem = m_TXLList.GetItemText(e_Item, e_SubItem);//获得相应单元格字符 可能之前有字符
CtEdit->SetWindowText(strItem);//将单元格字符显示在编辑框上
CtEdit->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
CtEdit->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
CtEdit->SetFocus();//设置为焦点
CtEdit->SetSel(-1);//设置光标在文本框文字的最后
}
void CTXLDlg::DistroyEdit(CListCtrl *list, CEdit* DyEdit, int &Item, int &SubItem)
{
CString meditdata;
DyEdit->GetWindowText(meditdata); //*******************************************************************************************************************************************GetWindowsTextW???
list->SetItemText(Item, SubItem, meditdata);//获得相应单元格字符
DyEdit->DestroyWindow();//销毁对象,有创建就要有销毁,不然会报错
}
void CTXLDlg::CreateCombobox(NM_LISTVIEW *pEditCtrl, CComboBox *CtCombobox, int &Item, int &SubItem, bool &bIsCreateCombox)//创建单元格下拉列表框函数
//pEditCtrl为列表对象指针,CreateCcombobox为下拉列表框指针对象,
//Item为创建单元格在列表中的行,SubItem则为列,bIsCreateEdit为对象创建标记
{
Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
CtCombobox->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_OEMCONVERT, CRect(0, 0, 0, 0), this, IDC_COMBOX_CREATEID);
bIsCreateCombox = true;
CtCombobox->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
CtCombobox->SetParent(&m_TXLList);//将list control设置为父窗口,生成的Combobox才能正确定位,这个也很重要
CRect EditRect;
m_TXLList.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
EditRect.SetRect(EditRect.left + 1, EditRect.top + 1, EditRect.left + m_TXLList.GetColumnWidth(e_SubItem) - 1, EditRect.bottom - 1);//+1和-1可以让编辑框不至于挡住列表框中的网格线//******* EditRect.top - 1?*********************************************************
CString strItem = m_TXLList.GetItemText(e_Item, e_SubItem);//获得相应单元格字符
CtCombobox->SetWindowText(strItem);//将单元格字符显示在编辑框上
CtCombobox->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
CtCombobox->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
}
void CTXLDlg::DistroyCombobox(CListCtrl *list, CComboBox* DyCombox, int &Item, int &SubItem)
{
CString meditdata;
DyCombox->GetWindowText(meditdata); //*******************************************************************************************************************************************GetWindowsTextW???
list->SetItemText(Item, SubItem, meditdata); //更新相应单元格字符
DyCombox->DestroyWindow(); //销毁对象,有创建就要有销毁,不然会报错
}
void CTXLDlg::OnOK()
{
}
void CTXLDlg::OnKillfocusEdit()
{
if (bIsCreateEdit == true)//如果之前创建了编辑框就销毁掉
{
DistroyEdit(&m_TXLList, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
bIsCreateEdit = false;
}
if (bIsCreateCombobox == true)//如果之前创建了下拉列表框就销毁掉
{
DistroyCombobox(&m_TXLList, &m_ComBox, e_Item, e_SubItem);
bIsCreateCombobox = false;
}
}
void CTXLDlg::OnKillfocusCcomboBox()
{
if (bIsCreateEdit == true)//如果之前创建了编辑框就销毁掉
{
DistroyEdit(&m_TXLList, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
bIsCreateEdit = false;
}
if (bIsCreateCombobox == true)//如果之前创建了下拉列表框就销毁掉
{
DistroyCombobox(&m_TXLList, &m_ComBox, e_Item, e_SubItem);
bIsCreateCombobox = false;
}
}
void CTXLDlg::OnBnClickedDrButton()
{
// TODO: 在此添加控件通知处理程序代码
/////////////////////////////////////////////////////////////////////////////////////
//ADO 打开数据库
_ConnectionPtr m_pConnection;//数据库 智能指针
AfxOleInit(); //初始化COM并结束时关闭
m_pConnection.CreateInstance(__uuidof(Connection));
//打开TXL.mdp
try
{
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Sourse=TXL.mdp","","",adModeUnknown);
}
catch(_com_error e)
{
MessageBox(_T("数据库连接失败,请检查数据库TXL.mdp路径是否正确!"));
return ;
}
////////////////////////////////////////////////////////////////////////////////
//打开数据表
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));
try
{
m_pRecordset->Open("SELECT *FORM 通讯录",/*theApp.*/m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
}
catch (_com_error e)
{
AfxMessageBox(_T("表内数据为空!"));
return;
}
//////////////////////////////////////////////////////////////////
//获取字段 编号 姓名 性别 学号 电话 QQ 住址
//将表内数据全部读出并显示在列表框内
//如果没有遇到表结束标志adoEOF,则用GetCollect(字段名)或m_pRecordset->Fields->GetItem(字段名)->Value方法,来获取当前记录指针所指的字段值,
//然后再用MoveNext()方法移动到下一条记录位置
_variant_t var;
try
{
if (!m_pRecordset->BOF)
m_pRecordset->MoveFirst();
else
{
AfxMessageBox(_T("表内数据为空"));
return;
}
// 读入库中各字段并加入列表框中
while (!m_pRecordset->adoEOF)
{
var = m_pRecordset->GetCollect("编号"); //记录集返回值为结构体_variant_t,用vt成员判断是否为空
if (var.vt != VT_NULL)
stinfo[0].bh = (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("姓名");
if (var.vt != VT_NULL)
stinfo[0].XM = (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("性别");
if (var.vt != VT_NULL)
stinfo[0].XB = (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("学号");
if (var.vt != VT_NULL)
stinfo[0].XH= (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("电话");
if (var.vt != VT_NULL)
var = m_pRecordset->GetCollect("QQ");
if (var.vt != VT_NULL)
stinfo[0].QQ = (LPCSTR)_bstr_t(var);
var = m_pRecordset->GetCollect("住址");
if (var.vt != VT_NULL)
stinfo[0].ZH = (LPCSTR)_bstr_t(var);
//m_TXLList.AddString(stinfo[0].bh + " --> " + stinfo[0].XM + " --> " + stinfo[0].XB + " --> " + stinfo[0].XH + " --> " + stinfo[0].DH + " --> " + stinfo[0].QQ + " --> " + stinfo[0].ZH);//*****************************************************************
m_pRecordset->MoveNext();
}
// 默认列表指向第一项,同时移动记录指针并显示
//m_TXLList.SetCurSel(0);//**********************************************************************************************************************
}
catch (_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
//////////////////////////////////////////////////////////////
try
{
// 写入各字段值
m_pRecordset->AddNew();
m_pRecordset->PutCollect("编号", _variant_t(stinfo[0].BH));
m_pRecordset->PutCollect("姓名", _variant_t(stinfo[0].XM));
m_pRecordset->PutCollect("性别", _variant_t(stinfo[0].XB));
m_pRecordset->PutCollect("学号", _variant_t(stinfo[0].XH));
m_pRecordset->PutCollect("电话", _variant_t(stinfo[0].DH));
m_pRecordset->PutCollect("QQ", _variant_t(stinfo[0].QQ));
m_pRecordset->PutCollect("地址", _variant_t(stinfo[0].ZH));
m_pRecordset->Update();
AfxMessageBox(_T("插入成功!"));
}
catch (_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
// 移动记录指针。移动记录指针可以通过MoveFirst()方法移动到第一条记录、MoveLast()方法移动到最后一条记录、MovePrevious()方法移动到当前记录的前一条记录、MoveNext()方法移动到当前记录的下一条记录。但我们有时经常需要随意移动记录指针到任意记录位置时,可以使用Move(记录号)方法来实现,注意: Move()方法是相对于当前记录来移动指针位置的,正值向后移动、负值向前移动,如:Move(3),当前记录是3时,它将从记录3开始往后再移动3条记录位置。代码如下所示:
try
{
//int curSel = m_TXLList.GetCurSel();
// 先将指针移向第一条记录,然后就可以相对第一条记录来随意移动记录指针
m_pRecordset->MoveFirst();
//m_pRecordset->Move(long(curSel));
}
catch (_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
//修改记录中字段值。可以将记录指针移动到要修改记录的位置处,直接用PutCollect(字段名,值)将新值写入并Update()更新数据库既可。可以用上面方法移动记录指针,修改字段值代码如下所示:
try
{
// 假设对第二条记录进行修改
m_pRecordset->MoveFirst();
m_pRecordset->Move(1); // 从0开始
m_pRecordset->AddNew();
m_pRecordset->PutCollect("编号", _variant_t(stinfo[0].BH));
m_pRecordset->PutCollect("姓名", _variant_t(stinfo[0].XM));
m_pRecordset->PutCollect("性别", _variant_t(stinfo[0].XB));
m_pRecordset->PutCollect("学号", _variant_t(stinfo[0].XH));
m_pRecordset->PutCollect("电话", _variant_t(stinfo[0].DH));
m_pRecordset->PutCollect("QQ", _variant_t(stinfo[0].QQ));
m_pRecordset->PutCollect("地址", _variant_t(stinfo[0].ZH));
m_pRecordset->Update();
}
catch (_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
//删除记录。删除记录和上面修改记录的操作类似,先将记录指针移动到要修改记录的位置,直接用Delete()方法删除它并用Update()来更新数据库既可。代码如下所示:
try
{
// 假设删除第二条记录
m_pRecordset->MoveFirst();
m_pRecordset->Move(1); // 从0开始
m_pRecordset->Delete(adAffectCurrent); // 参数adAffectCurrent为删除当前记录
m_pRecordset->Update();
}
catch (_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
//关闭记录集。直接用Close方法关闭记录集并赋于其空值。代码如下所示:
m_pRecordset->Close();
m_pRecordset = NULL;
//////////////////////////////////////////////////////////////////
//关闭数据库连接
if (m_pConnection->State)
{
m_pConnection->Close();
}
m_pConnection = NULL;
//////////////////////////////////////////////////////
}
void CTXLDlg::OnBnClickedDcButton()
{
// TODO: 在此添加控件通知处理程序代码
}