我的项目 – 图书馆管理系统(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();
}
//