| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2825 人关注过本帖
标题:[原创]VC++联接数据库SQL2000应用实例及登陆退出(较全)-->永夜的极光转移 ...
只看楼主 加入收藏
赵博闻
Rank: 1
等 级:新手上路
帖 子:47
专家分:0
注 册:2007-9-20
收藏
 问题点数:0 回复次数:3 
[原创]VC++联接数据库SQL2000应用实例及登陆退出(较全)-->永夜的极光转移

*/ --------------------------------------------------------------------------------------
*/ 出自: 编程中国 http://www.bc-cn.net
*/ 作者: 赵博闻
*/ 时间: 2007-10-29 编程论坛首发
*/ 声明: 尊重作者劳动,转载请保留本段文字
*/ --------------------------------------------------------------------------------------


我自己做了个用SQL2000联接的例子,请大家帮我看看,有什么不足还望指教。如能得到您的点滴指点
都将万分感谢。

这个例子现在只能操作一张表,要想操作整个库也不难,就是改SQL语句,然后配好数据库,建议使用存储过程

正文:

简易数据库系统

第一部分:用ADO连接SQL Server 2000
1 在STDafx.h中加入动态连接库msado15.dll,并重命名EOF为adoEOF,加在该文件后面(蓝色#endif后面,要是编译时有错误说明位置不对)
#import "D:\Program Files\Common Files\System\ado\msado15.dll"\
no_namespace rename("EOF","adoEOF")
2 在App类中定义连接字符串。我的是CADOApp,文件是ADO.h
_ConnectionPtr m_pConnection;
3 在数据操作类InitInstance()中初始化COM类库
//这就是初始化COM库
//应用程序主类的InitInstance成员函数里初始化OLE/COM库环境
if (!AfxOleInit()) {
AfxMessageBox("OLE/COM初始化失败");
return FALSE;
}

theApp.m_pConnection.CreateInstance(__uuidof(Connection));
要在其它操作前面初始化,我的是dlg,原来在它后面初始化的结果走不到那一步,所以m_pConnection总是为NULL/0x000000000
4 再要操作的地方初始化结果集和连接字符串,我的是在一个按钮里
void CADOAccessDlg::OnBtnExec()
{
m_pRecordset.CreateInstance(__uuidof(Recordset));
CString strLink;//连接字符串
try
{ strLink.Format("Provider=SQLOLEDB;server=ZHAOPENG;UID=sa;PWD=sa;database=MD200");
theApp.m_pConnection->Open((_bstr_t)strLink,"","",NULL);
}
catch(_com_error e)
{
AfxMessageBox("连接SQL Server失败!");
return;
}
//UpdateData(true);
theApp.m_pConnection->Close();
}
如果要在文件中使用theApp,不要忘记在文件头部(不是头文件)加上extern CADOAccessApp theApp
以上就是连接数据库的简单方法。
第二部分:向ListCtrl中添加数据库中表的数据
1先写两个方法用于添加表头,和内容,ListCtrl要用Report格式
//初始化列表框
void CADOAccessDlg::InitReport()
{
m_List.InsertColumn(0,_T("音乐名称"),LVCFMT_LEFT,120,-1);
m_List.InsertColumn(1,_T("作者/歌手"),LVCFMT_LEFT,90,-1);
m_List.InsertColumn(2,_T("备注"),LVCFMT_LEFT,110,-1);
m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT |LVS_EX_GRIDLINES);
}
//显示列表框里的内容,从MidoSond表中
void CADOAccessDlg::UpdataReport()
{
m_List.DeleteAllItems();
//查询
m_pRecordset.CreateInstance(__uuidof(Recordset));
CString strLink;
try
{
strLink.Format("Provider=SQLOLEDB;server=ZHAOPENG;UID=sa;PWD=sa;database=MidoText");
theApp.m_pConnection->Open((_bstr_t)strLink,"","",NULL);
}
catch(_com_error e)
{
AfxMessageBox("连接SQL Server失败!");
return;
}
UpdateData(true);
try
{
m_pRecordset->Open("select * from TextSond",theApp.m_pConnection.GetInterfacePtr(),
adOpenDynamic,//动态
adLockOptimistic,//乐观封锁法
adCmdText);//文本查询
}
catch (_com_error e)
{
CString strErr="Select语句执行失败!";
AfxMessageBox(e.ErrorMessage()+strErr);
}
_variant_t vat;
CString MusicName,ZhuoZhe,SomethingAbout;
CString strDomainName;
while (!m_pRecordset->adoEOF)
{//获取一个字段
vat = m_pRecordset->GetCollect("音乐名称");
if (vat.vt != VT_NULL) {
MusicName = (LPCSTR)_bstr_t(vat);
MusicName.TrimLeft();//清除左边的空格
}
vat = m_pRecordset->GetCollect("作者/歌手");
if (vat.vt != VT_NULL) {
ZhuoZhe = (LPCSTR)_bstr_t(vat);
ZhuoZhe.TrimLeft();
}
vat = m_pRecordset->GetCollect("备注");
if (vat.vt != VT_NULL) {
SomethingAbout = (LPCSTR)_bstr_t(vat);
SomethingAbout.TrimLeft();
}
int pos,id=1;
pos = m_List.InsertItem(id,strDomainName);
m_List.SetItemText(pos,0,MusicName);
m_List.SetItemText(pos,1,ZhuoZhe);
m_List.SetItemText(pos,2,SomethingAbout);
m_pRecordset->MoveNext();
}
m_pRecordset->Close();
theApp.m_pConnection->Close();
}
2在ShowWindow事件中调用,因为该事件先于其它任何事件所以在这一个就建立了数据库连接(连接写在第二个方法里)
void CADOAccessDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);

// TODO: Add your message handler code here
this->InitReport();
this->UpdataReport();
}
第三部分:添加,修改,删除
这三项功能看似简单实则重要,使操作数据库系统的核心操作,可以扩展出许多其他功能。
分析:三项功能的本质在于1检索输入设备中输入的数据合法性,将其保存到相应的变量中。2调用命令函数,对连接的数据库进行操作。3将操作结果返回到输出设备上。
我们就按照这样的思想编成,以添加功能为例说明其它给出代码
//1检索输入设备中输入的数据合法性,将其保存到相应的变量中
void CADOAccessDlg::OnBtnAdd()
{
//判断是否有字符输入
if (ISEmpty()) {
return;
}
//不可以出现前两项一样的输入(正则表达式)
if (ISHaveString()==false) {
return;
}
//得到所输入的字符
BOOL IsUpdata = FALSE;
DataTable = "TextSond";//数据表名字
//这里我原来想作动态建库的所遗留了变量
CString strWeather;
CString strMusicName,strMen,strSomething;
((CEdit*)GetDlgItem(IDC_EdtMusicName))->GetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->GetWindowText(strMen);
((CEdit*)GetDlgItem(IDC_EdtSomething))->GetWindowText(strSomething);

//对所输入字符的合法性进行验证
if (strMusicName.GetLength()>50) {
MessageBox("音乐名称不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
if (strMen.GetLength()>30) {
MessageBox("作者或歌手不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
if (strSomething.GetLength()>40) {
MessageBox("备注不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
//判断要添加的行是否存在,存在就更新,不存在,就追加
for (int i=0;i<m_List.GetItemCount();i++) {
if (strWeather == m_List.GetItemText(i,0)) {
IsUpdata = TRUE;
break;
}
}

if (IsUpdata)
{
CString strUpdata;

strUpdata.Format("Updata '%s' set 音乐名称='%s',作者或歌手='%s',备注='%s'",
DataTable,strMusicName,strMen,strSomething);
_variant_t RecordAffected;
theApp.m_pConnection->Execute(_bstr_t(strUpdata),&RecordAffected,
adCmdText);
}
else
{
UpdateData();
m_pRecordset.CreateInstance(__uuidof(Recordset));
try
{
//查找所有行
CString sql;
sql.Format("select * from %s",
DataTable);
BSTR bstrSQL = sql.AllocSysString();
m_pRecordset->Open(_bstr_t(bstrSQL),
theApp.m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch (_com_error e) {
AfxMessageBox(e.ErrorMessage());
}
//添加
m_pRecordset->AddNew();
m_pRecordset->PutCollect("音乐名称",_variant_t(strMusicName));
m_pRecordset->PutCollect("作者或歌手",_variant_t(strMen));
m_pRecordset->PutCollect("备注",_variant_t(strSomething));
m_pRecordset->Update();
m_pRecordset->Close();
}
this->UpdataReport();
}
BOOL CADOAccessDlg::ISEmpty()
{
UpdateData(TRUE);
if (m_EdtMName == "") {
MessageBox("请输入音乐名称!","提示",MB_ICONINFORMATION);
return true;
}
if (m_Men == "") {
MessageBox("请输入作者或歌手!","提示",MB_ICONINFORMATION);
return true;
}
// if (m_SomeThing = "") {
// MessageBox("请输入音乐名称!","提示",MB_ICONINFORMATION);
// return;
// }
return false;
}
//判断编辑框里是否有字符,有择削去
BOOL CADOAccessDlg::ISHaveString()
{
CString strMusicName,strMen,strSomething;
CString strOldName,strOldMen;
((CEdit*)GetDlgItem(IDC_EdtMusicName))->GetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->GetWindowText(strMen);
for (int i=0;i<m_List.GetItemCount();i++)
{
strOldName = m_List.GetItemText(i,0);
strOldMen = m_List.GetItemText(i,1);
if ((strMusicName==strOldName)&(strMen==strOldMen))
{
AfxMessageBox("请不要重复添加记录!");
return false;//已经有了这样的字段
}
}
return true;
}
修改
void CADOAccessDlg::OnBtnUpdate()
{
// TODO: Add your control notification handler code here
//点击修改时将会更新数据表中的内容
if (ISEmpty()) {
return;
}
//得到所输入的字符
BOOL IsUpdata = FALSE;
CString strMusicName,strSomeOne,strSomeThing;
((CEdit*)GetDlgItem(IDC_EdtMusicName))->GetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->GetWindowText(strSomeOne);
((CEdit*)GetDlgItem(IDC_EdtSomething))->GetWindowText(strSomeThing);
//对所输入字符的合法性进行验证
if (strMusicName.GetLength()>50) {
MessageBox("音乐名称不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
if (strSomeOne.GetLength()>30) {
MessageBox("作者或歌手不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
if (strSomeThing.GetLength()>40) {
MessageBox("备注不能超过50个字节!","请您注意",MB_ICONINFORMATION);
return;
}
//判断是否选中了要修改的行
CString strOldName,strOldMen;
strOldName = m_List.GetItemText(m_nIndex,0);
strOldMen = m_List.GetItemText(m_nIndex,1);
CWnd* boFocus;
boFocus = m_List.GetFocus();
if (boFocus != NULL) //有焦点,先是高亮,更新
{
UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
m_List.SetItemState(m_nIndex, flag, flag);
CString strIndexName;
strIndexName = m_List.GetItemText(m_nIndex,0);
DataTable="TextSond";
CString strSQLUpdata;
_variant_t RecordAffected;
strSQLUpdata.Format("Update %s Set 音乐名称='%s',作者或歌手='%s',备注='%s' Where 音乐名称='%s' AND 作者或歌手='%s'",
DataTable,strMusicName,strSomeOne,strSomeThing,strOldName,strOldMen);
BSTR bstrSQL = strSQLUpdata.AllocSysString();
theApp.m_pConnection->Execute(_bstr_t(bstrSQL),&RecordAffected,adCmdText);
//重新显示列表框
UpdataReport();
}
else
{
MessageBox("请选则要修改的行!","请您注意",MB_ICONINFORMATION);
return;
}
}
删除
void CADOAccessDlg::OnBtnDelete()
{
// TODO: Add your control notification handler code here
CString strDelete;
CString DataTable;
CString MName;
DataTable = "TextSond";
MName = m_List.GetItemText(m_nIndex,0);
strDelete.Format("Delete %s Where 音乐名称='%s'",
DataTable,MName);
_variant_t RecordsAffected;
theApp.m_pConnection->Execute(_bstr_t(strDelete),&RecordsAffected,adCmdText);
this->UpdataReport();
}
第四部分:上下移动按钮
功能:当点击上下移动按钮时列表框中的被选中的一行会显示高亮,同时该亮度条会上移或下移一行,同时编辑框中的字段会随移动有相应变化。
如图:上移,一行

在相应的方法中添加代码
void CADOAccessDlg::OnClickListView(NMHDR* pNMHDR, LRESULT* pResult)
{//在上下移动前需要制定一个起始位置
// TODO: Add your control notification handler code here
POSITION pos = m_List.GetFirstSelectedItemPosition();
m_nIndex = m_List.GetNextSelectedItem(pos); // 得到项目索引

CString strMusicName,strSomeOne,strSomeThing;
strMusicName = m_List.GetItemText(m_nIndex,0);
strSomeOne = m_List.GetItemText(m_nIndex,1);
strSomeThing = m_List.GetItemText(m_nIndex,2);
((CEdit*)GetDlgItem(IDC_EdtMusicName))->SetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->SetWindowText(strSomeOne);
((CEdit*)GetDlgItem(IDC_EdtSomething))->SetWindowText(strSomeThing);

if (m_nIndex != -1) {
// m_List.SetFocus();
}
*pResult = 0;
}

void CADOAccessDlg::OnBtnUp()
{
// TODO: Add your control notification handler code here
//向上移动
m_List.SetFocus();
if (m_nIndex == -1) {
MessageBox("请选择一行再上移!","请注意",MB_ICONINFORMATION);
return;
}
// 判断所选项是否位于行首
if (m_nIndex == 0) {
MessageBox("已经位于第一行了!","请注意",MB_ICONINFORMATION);
return;
}

CString strMusicName,strSomeOne,strSomeThing;
strMusicName = m_List.GetItemText(m_nIndex,0);
strSomeOne = m_List.GetItemText(m_nIndex,1);
strSomeThing = m_List.GetItemText(m_nIndex,2);

m_List.DeleteItem(m_nIndex);
m_List.InsertItem(m_nIndex,strMusicName);
m_List.SetItemText(m_nIndex,1,strSomeOne);
m_List.SetItemText(m_nIndex,2,strSomeThing);
m_nIndex--;

strMusicName = m_List.GetItemText(m_nIndex,0);
strSomeOne = m_List.GetItemText(m_nIndex,1);
strSomeThing = m_List.GetItemText(m_nIndex,2);
((CEdit*)GetDlgItem(IDC_EdtMusicName))->SetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->SetWindowText(strSomeOne);
((CEdit*)GetDlgItem(IDC_EdtSomething))->SetWindowText(strSomeThing);

// 使得m_nIndex-1位置处项目高亮显示并获得焦点
UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
m_List.SetItemState(m_nIndex, flag, flag);
}

void CADOAccessDlg::OnBtnDown()
{
// TODO: Add your control notification handler code here
//向下移动
m_List.SetFocus();
if (m_nIndex == -1) {
MessageBox("请选择一行再上移!","请注意",MB_ICONINFORMATION);
return;
}
// 判断所选项是否位于行首
if (m_nIndex == m_List.GetItemCount()-1) {
MessageBox("已经位于最后一行了!","请注意",MB_ICONINFORMATION);
return;
}
CString strMusicName,strSomeOne,strSomeThing;
//获取该行字段付给编辑框
strMusicName = m_List.GetItemText(m_nIndex,0);
strSomeOne = m_List.GetItemText(m_nIndex,1);
strSomeThing = m_List.GetItemText(m_nIndex,2);

m_List.DeleteItem(m_nIndex);
m_List.InsertItem(m_nIndex,strMusicName);
m_List.SetItemText(m_nIndex,1,strSomeOne);
m_List.SetItemText(m_nIndex,2,strSomeThing);
m_nIndex++;
strMusicName = m_List.GetItemText(m_nIndex,0);
strSomeOne = m_List.GetItemText(m_nIndex,1);
strSomeThing = m_List.GetItemText(m_nIndex,2);
((CEdit*)GetDlgItem(IDC_EdtMusicName))->SetWindowText(strMusicName);
((CEdit*)GetDlgItem(IDC_EdtZZName))->SetWindowText(strSomeOne);
((CEdit*)GetDlgItem(IDC_EdtSomething))->SetWindowText(strSomeThing);
//显示高亮得到焦点
UINT falg = LVIS_SELECTED|LVIS_FOCUSED;
m_List.SetItemState(m_nIndex,falg,falg);
}
第五部分:登录

实质:1取得信息,验证,并存于相应变量。2在ini文件中存入这些变量。3调用命令函数查询数据库看是否通过。
给出核心代码,其余请参看源代码
void LogINDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);

// TODO: Add your message handler code here
CFileStatus Status;//文件身份
CString str;//“关闭”按钮文字
static CRect RtSmall;
if (CFile::GetStatus(".\\MyDB.ini",Status))
{
this->OnBtnCloseORMore();

m_SQLDomainName = m_Inif.GetSQLServerIPORName();
m_strSQLUserName = m_Inif.GetSQLServerUserName();
m_strSQLPassword = m_Inif.GetSQLServerPassWord();
if (m_strUserName == "") {
m_Save = false;// m_Save是CheckBox的变量
}
else
{
m_Save = true;
}
CString ifFind;
ifFind = m_SQLDomainName;
if (!ifFind.IsEmpty()) {
m_Save =true;
}
UpdateData(false);
}
}
1登录
void LogINDlg::OnBtnOK()
{
// TODO: Add your control notification handler code here
if (!IsEmpty())
{
m_Inif.SetSQLServerIP(m_SQLDomainName);
m_Inif.SetSQLServerUserName(m_strSQLUserName);
m_Inif.SetSQLServerPassword(m_strSQLPassword);
if (m_Save) {
m_Inif.SetUserName(m_strUserName);
m_Inif.SetPassWord(m_strPassWord);
}
else
{
m_Inif.SetUserName("");
m_Inif.SetPassWord("");
}
//连接数据库
CString strSQL;
strSQL.Format("Provider=SQLOLEDB;server=%s;uid=%s;pwd=%s;database=MidoText",
m_SQLDomainName,m_strSQLUserName,m_strSQLPassword);
try
{
theApp.m_pConnection->Open((_bstr_t)strSQL,"","",NULL);

}
catch (_com_error e)
{
AfxMessageBox("连接SQL Server失败!");
return;
}
UpdateData(true);
CString strSelect;
strSelect.Format("Select * From UserINIF Where UserName='%s' And \
PassWord='%s' And UserKind=1",m_strUserName,m_strPassWord);
m_pRecordset.CreateInstance(__uuidof(Recordset));
try
{
m_pRecordset->Open((_bstr_t)strSelect,theApp.m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch (_com_error e)
{
AfxMessageBox(e.ErrorMessage());
return;
}
_variant_t var;
CString strUserName;
if (!m_pRecordset->adoEOF)
{
theApp.LoginFlag = true;
theApp.UserName = strUserName;
m_pRecordset->Close();
CDialog::OnOK();
}
else
{
m_pRecordset->Close();
theApp.m_pConnection->Close();
AfxMessageBox("登陆失败!");
}
}
}

2详细…
void LogINDlg::OnBtnCloseORMore()
{
// TODO: Add your control notification handler code here
//改变文字
CString str;
if (GetDlgItemText(IDC_BtnCloseORMore,str),str=="关闭...") {
SetDlgItemText(IDC_BtnCloseORMore,"详细...");
}
else
{
SetDlgItemText(IDC_BtnCloseORMore,"关闭...");
}
//开辟对话框区域
static CRect RtLarger;
static CRect RtSmall;
if (RtLarger.IsRectEmpty())
{
//可变区域
CRect temp;
GetWindowRect(&RtLarger);
GetDlgItem(IDC_STATIC_Span)->GetWindowRect(&temp);//设定分界线以下为可变区域
//设置可变区域大小
RtSmall.left = RtLarger.left;
RtSmall.right = RtLarger.right;
RtSmall.top = RtLarger.top;
RtSmall.bottom = temp.bottom;
}
//按钮上显示“关闭。。。”时不显示附加区域
if (str=="关闭...") {
SetWindowPos(NULL,0,0,RtSmall.Width(),RtSmall.Height(),
SWP_NOMOVE | SWP_NOZORDER);//不改变当前的大小和位置
}
else
{
SetWindowPos(NULL,0,0,RtLarger.Width(),RtLarger.Height(),
SWP_NOMOVE | SWP_NOZORDER);
}
}
第六部分 退出

软件要退出时应该有个退出界面,让用户确认是否真的要退出
效果图

步骤:
1在主干文件中定义退出变量,就是和工程同名的那个文件我的是ObjectPlayer。Cpp
Public:
BOOL ExitFlag;//退出标志符
2建立基于退出对话框的相关类,因为要用到程序对象App,所以在程序开始处引用对象extern CObjectPlayerApp theApp;
填写相应方法
void ExitDlg::OnOK()
{
// TODO: Add extra validation here
theApp.ExitFlag = TRUE;
CDialog::OnOK();
}

void ExitDlg::OnCancel()
{
// TODO: Add extra cleanup here
theApp.ExitFlag = false;
CDialog::OnCancel();
}
3在需要调用该对话框的文件中(.cpp)引入#include "ExitDlg.h"
extern CObjectPlayerApp theApp;
调用WM_Close消息
void CObjectPlayerDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
ExitDlg dlgExit;
dlgExit.DoModal();//调用对话框
if (theApp.ExitFlag) //判断标志位
{
CDialog::OnClose();
}
}

搜索更多相关主题的帖子: 永夜 数据库 极光 实例 联接 
2007-10-29 14:55
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
收藏
得分:0 
发错区了。。我看看怎么帮你转

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-10-29 15:22
赵博闻
Rank: 1
等 级:新手上路
帖 子:47
专家分:0
注 册:2007-9-20
收藏
得分:0 
谢谢大哥,我初来乍到,连去的概念都没弄明白。
能不能给讲讲啊

2007-10-29 15:33
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
收藏
得分:0 
你这个帖子的内容是vc的,跟asp一点关系都没有,却发到了asp板块,所以我帮你移过来了

这个论坛首页,不是分了很多个分论坛吗?每个分论坛就是我说的一个“区”,或者“板块”,不同的区讨论的主要内容不同,所以要根据你自己发的帖子的主题,选择合适的区发帖,这样方便大家讨论和查找

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-10-29 15:37
快速回复:[原创]VC++联接数据库SQL2000应用实例及登陆退出(较全)-->永夜的极光 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016009 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved