VC++連接數據庫SQL2000應用實例及登陸退出

我自己做了個用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();
}
}

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/wujiabin587/archive/2009/05/01/4142003.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章