我的項目 – 圖書館管理系統(LMS) Write by Hifan: b033205_Wangqi 王琪
- 王琪
- 同濟大學 軟件學院2003級
寫在前面->我的項目是我自己經過n天的努力,一個人完成的
其中的代碼絕大部分是我自己寫的,也有很多是在Csdn上看別人的問題和自己問問題
或者自己看MSDN自己找到解決辦法~這也是一份比較辛苦的事情。
有一個類的代碼大部分是看別人的就是CMyPicture顯示圖片,可以顯示多種格式的Pic
源代碼很多有LMS[主應用程序] DLL/Picture,OtherFunc[dll]
代碼量大概有5000行~!
細節開始 [Start]
1. 多線程 (初始化連接數據庫 有自己的Splash 顯示圖片)
// Thread in MySplash Init
HWND hWnd=this->GetSafeHwnd();
m_pThread=AfxBeginThread(MyAdoConnect,hWnd,THREAD_PRIORITY_NORMAL);//啓動線程THREAD_PRIORITY_HIGHEST
m_pThread->m_bAutoDelete=FALSE; //線程爲手動刪除
// 線程函數
UINT MyAdoConnect(LPVOID pParam)
{
// COM初始化
::CoInitialize(0);
_ConnectionPtr pConn;
HRESULT hr;
hr = pConn.CreateInstance(__uuidof(Connection));
if(SUCCEEDED(hr))
{
try
{
pConn->ConnectionString = "Provider=OraOLEDB.Oracle.1;Password=LMS;Persist Security Info=True;User ID=LMS;Data Source=oradb1";//設置連接字符串
pConn ->ConnectionTimeout = 10; //設置連接的超時時間,可選
pConn ->CursorLocation = adUseServer; //設置光標的位置,可選
pConn ->Open("","","",-1);
}
catch(_com_error& e)
{
CString StrErr;
StrErr.Format("出錯,連接數據庫錯誤~/n錯誤:%s",e.ErrorMessage());
AfxMessageBox(StrErr);
::PostMessage( (HWND)pParam,WM_CLOSE,0,0);
bpConn = false;
return FALSE;
}
}
theApp.SetConn(pConn);
::PostMessage( (HWND)pParam,WM_CLOSE,0,0);
bpConn = true;
return TRUE;
}
2. 好玩的地方~ (讓窗口顯示的動態化~) MyLogin.Init; MySplash .Init
ShowWindow(SW_HIDE);
CRect rect;
this->GetClientRect(&rect);
CPoint CenterPt;
CenterPt.x = rect.Width()/2;
CenterPt.y = rect.Height()/2;
CRgn rgn;
this->ShowWindow(SW_HIDE);
int m = GetSystemMetrics(SM_CYSIZEFRAME);
for(int i=0;i<rect.Width()/2+m;++i)
{
rgn.CreateRectRgn(CenterPt.x-i,CenterPt.y-i,CenterPt.x+i,CenterPt.y+i);
SetWindowRgn( (HRGN)rgn.GetSafeHandle(),TRUE);
ShowWindow(SW_SHOW);
CenterWindow();
rgn.DeleteObject();
}
3. CMyPicture用來對圖片的處理 (*.jpg,*.jif,*.bmp) 此類是放在Picture.dll裏面的
避免了Bitblt不能顯示*.jpg,*.jif的缺點 和StrechBitblt的效果不好;[大部分是看別人的]
class AFX_EXT_CLASS CMyPicture
{
public:
CMyPicture();
virtual ~CMyPicture();
public:
void FreePictureData();
BOOL Load(CString sFilePathName);
BOOL Load(UINT ResourceName, LPCSTR ResourceType);
BOOL LoadPictureData(BYTE* pBuffer, int nSize);
BOOL SaveAsBitmap(CString sFilePathName);
BOOL Show(CDC* pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY);
BOOL Show(CDC* pDC, CRect DrawRect);
BOOL ShowBitmapResource(CDC* pDC, const int BMPResource, CPoint LeftTop);
BOOL UpdateSizeOnDC(CDC* pDC);
public:
IPicture* m_IPicture;
LONG m_Height;
LONG m_Weight;
LONG m_Width;
};
4. CMyStatic繼承了CStatic 來顯示圖片,處理了右鍵點擊 彈出對話框 保存圖片
// 彈出菜單
void CMyStatic::OnRButtonUp(UINT nFlags, CPoint point)
{
{
CMenu menu, *pMenu;
menu.LoadMenu(IDR_MENU1);
pMenu = menu.GetSubMenu(0);
ClientToScreen(&point);
pMenu->TrackPopupMenu(TPM_RIGHTBUTTON,point.x,point.y,this);
}
CStatic::OnRButtonUp(nFlags, point);
}
// 保存圖片
ON_COMMAND(IDC_MENU_SAVE, OnMenuSave)
void CMyStatic::OnMenuSave()
{
CString FilePathName;
CFileDialog Dlg(FALSE,NULL,NULL,0,
"Jpg Files (*.jpg)|*.jpg|Gif Files (*.jif)|*.gif|Bmp Files (*.bmp)|*.bmp||",
this);
if(Dlg.DoModal()==IDOK)
{
FilePathName = Dlg.GetFileName();
}
if( FilePathName!="" )
pPic->SaveAsBitmap(FilePathName);
}
5. 關於Ado的連接操作
// 主要用到以下
_ConnectionPtr pConn;
_CommandPtr pCmd;
_RecordsetPtr pRst;
_variant_t m_vTemp[10];
// 用pRst來遍歷
// 用pCmd來執行
// 可以存放圖片 顯示圖片
// 存入圖片 向數據庫中
try
{
CFile file;
if(file.Open(FilePathName, CFile::modeRead | CFile::typeBinary))
{
int nSize = file.GetLength();
BYTE * pBuffer = new BYTE [nSize];
if (file.Read(pBuffer, nSize) > 0 )
{
// 下面這一段代碼是把pBuffer裏的圖片數據寫到數據庫中
BYTE *pBuf = pBuffer;
VARIANT varBLOB;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];
pRst->AddNew();
if(pBuf)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nSize;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for(LONG i = 0; i <(LONG) nSize; i++)
SafeArrayPutElement(psa,&i,pBuf++);
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
// 要放在它(Pic)前面~
pRst->Fields->GetItem("SNO")->Value = m_Sno.AllocSysString();
pRst->GetFields()->GetItem("PIC")->AppendChunk(varBLOB);
// pRst->PutCollect("SNO",m_Sno.AllocSysString());
// pRst->PutCollect("Pic",varBLOB);
}
pRst->Update();
delete [] pBuffer;
pRst->Close();
pRst=NULL;
}
file.Close();
}
}
catch(_com_error e)
{
bret = false;
}
// 顯示圖片 從數據庫中讀取圖片並顯示~
str.Format("Select * from picture where sno=/'%s/'",m_Sno);
SqlStr = str.AllocSysString();
// First Clear.
if(m_Pic.m_IPicture!=NULL)
m_Pic.FreePictureData();
hr = pRst.CreateInstance(__uuidof(Recordset));
if(SUCCEEDED(hr))
{
try
{
pRst->Open(SqlStr,(IDispatch*)(theApp.Conn()),
adOpenDynamic,adLockOptimistic,adCmdText);
// 只能有一條紀錄 Con_Picture_Sno_Unique
if(!pRst->MyHiFanEOF)
{
long nSize = pRst->GetFields()->GetItem("Pic")->ActualSize;
if(nSize > 0)
{
_variant_t varBLOB;
varBLOB = pRst->GetFields()->GetItem("Pic")->GetChunk(nSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
if(BYTE *pBuffer = new BYTE [nSize+1]) {
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(pBuffer,pBuf,nSize); SafeArrayUnaccessData (varBLOB.parray);
m_Pic.LoadPictureData(pBuffer, nSize);
delete [] pBuffer;
CGuashi::SetPicThenShow();
}
}
}
}
}
catch(_com_error &e)
{
AfxMessageBox(,e.Description());
}
}
// 還有很多地方用到事務~ 源程序都有介紹
bool bret = false
hr = pConn.CreateInstance(__uuidof(Connection));
if(SUCCEEDED(hr))
{
pConn=theApp.Conn(); // 得到pConn
pConn->BeginTrans();
try
{
// 這些的語句在前面已經初始化~
pConn->Execute(_bstr_t(SqlInertIntoStudents),0,adExecuteNoRecords);
pConn->Execute(_bstr_t(SqlInertIntoCard),0,adExecuteNoRecords);
bret = true;
}
catch(_com_error& e) // Get Error
{
AfxMessageBox(e.ErrorMessage());
}
if (bret)
pConn->CommitTrans();
else
{
pConn->RollbackTrans();
CString StrErr;
StrErr.Format("%s出錯~!/n事務即將回滾~",OracleErrorStr);
AfxMessageBox(StrErr);
EndDialog(101); // 結束窗口,本窗口是模態的
return;
}
}
6. 關於dll
這個我也不想多說了,我寫了兩個dll,一個是Picture.dll,另一個是OtherFunc.dll
Picture.dll: AFX_EXT_CLASS CMyPicture因爲這個類經常用到,所以我把它放到dll中
OtherFunc.dll: 其他函數的dll
這個老師在課堂上講的我都會,所以沒有什麼可講的,其他深入的我也就沒有做~
7. 極小點
// Hide Window on Taskbar: [在任務欄上隱藏] 隱藏CMySplash
::SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,WS_EX_TOOLWINDOW);
// TopMost
1. SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); // In Init
2. void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) // In Show Window
{
CFrameWnd::OnShowWindow(bShow, nStatus);
// TopMost
SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
}
// 隨機數字的初始~ 後面就可以用rand()來得到隨機數~ [使程序更好玩]
srand( (unsigned) time(NULL) ); // Important
// 256色Toolbar
雖然我的Icon很醜,但是都是我自己畫的,而且可以是256色~
// 改變CStatic背景爲透明
HBRUSH CDlgLogin::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// HiFan
// For Change Static BkMode, and Text Color
if(nCtlColor==CTLCOLOR_STATIC) //還有類似的CTLCOLOR_BTN…
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(200,0,200));
return (HBRUSH) ::GetStockObject(NULL_BRUSH);
}
// End of Hifan
return hbr;
}
// 模態對話框和非模態對話框~
老師給我講了,我懂了一些~ 這些窗口被Close後並沒有完全的消失~
我所建的窗口大部分是非模態的~
// 窗口子項的使能~有必要~
CWnd * pCwnd = this->GetDlgItem(IDC_ID);
pCwnd->EnableWindow(TRUE);
// 還有我發現要使Edit中產生換行必須是”/r/n” 這個和C++中不一樣~
CString m_Info; // 是 /r/n; 不是/n,/n/r./r;
m_Info.Format(“我/r/n是/r/n王/r/n琪”);
this->UpdateData(FALSE);
// 多頁屬性框的創建
CTabCtrl m_Tab;
CPage1 page1;
CPage2 page2;
int CDelete::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
m_Tab.Create(WS_VISIBLE,CRect(0,0,500,370),this,IDC_TAB1);
m_Tab.InsertItem(0,"刪除學生");
m_Tab.InsertItem(1,"刪除舊書");
// 分頁~
page1.Create(IDD_DIALOG9_PAGE1,this);
page2.Create(IDD_DIALOG9_PAGE2,this);
page1.ShowWindow(SW_SHOW);
page2.ShowWindow(SW_HIDE);
return 0;
}
void CDelete::OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
switch(m_Tab.GetCurSel())
{
case 0:
page1.ShowWindow(SW_SHOW);
page2.ShowWindow(SW_HIDE);
break;
case 1:
page1.ShowWindow(SW_HIDE);
page2.ShowWindow(SW_SHOW);
break;
}
}
void CDelete::OnOK()
{
page1.DestroyWindow();
page2.DestroyWindow();
this->DestroyWindow();
}
//