我参考例子写了下面代码:
显示函数:
void CCorpEmpEditDlg::DrawPhoto()
{
UpdateData(TRUE);
if(DrawYes == TRUE)
{
CWnd *pWnd = GetDlgItem(IDC_EMPPHOTO);
CRect rect;
pWnd->GetClientRect(&rect);
CDC *pDC = pWnd->GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC); IStream *ps;
CFileStatus fstatus;
CFile file;
LONG cb;
IPicture *pPic; if(iSelectEmpID != 0)
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, pStm->GetSize());
LPVOID pvData = NULL;
if (hGlobal != NULL)
{
if ((pvData = GlobalLock(hGlobal)) != NULL)
{
char * m_pBMPBuffer = new char[pStm->GetSize()+1];//分配必要的存储空间
char *pBuf = NULL;
varBLOB = pStm->Read(adReadAll);
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(pvData,pBuf,pStm->GetSize()); //复制数据到缓冲区 m_pBMPBuffer
SafeArrayUnaccessData (varBLOB.parray);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &ps);
}
}
if(SUCCEEDED(OleLoadPicture(ps,pStm->GetSize(),TRUE,IID_IPicture,(LPVOID*)&pPic)))
{
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
if(FAILED(pPic->Render(*pDC,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL)))
{
ps->Release();
pPic->Release();
AfxMessageBox(_T("图像绘制失败!"));
}
ps->Release();
pPic->Release();
}
else
{
AfxMessageBox(_T("从流中装载图像失败!"));
return;
}
}
else
{
if (!strPhotoPathName.IsEmpty())
{
/*
IPicture* p=NULL;
IStream* s=NULL;
HGLOBAL hG;
void* pp;
FILE* fp;

// Read file in memory
//USES_CONVERSION;
//LPCSTR lpcstr = W2A(strPhotoPathName);
fp = _tfopen(strPhotoPathName, _T("rb"));
if (!fp)
return;
fseek(fp,0,SEEK_END);
int fs = ftell(fp);
fseek(fp,0,SEEK_SET);
hG = GlobalAlloc(GPTR,fs);
if (!hG)
{
fclose(fp);
return;
}
pp = (void*)hG;
fread(pp,1,fs,fp);
fclose(fp);
CreateStreamOnHGlobal(hG,false,&s);
if (!s)
{
GlobalFree(hG);
return;
}
OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);
if (!p)
{
s->Release();
GlobalFree(hG);
return;
}
s->Release();
GlobalFree(hG);
HBITMAP hB = 0;
p->get_Handle((unsigned int*)&hB);

// Copy the image. Necessary, because upon p's release,
// the handle is destroyed.
HBITMAP hBB = (HBITMAP)CopyImage( hB,IMAGE_BITMAP,0,0,LR_COPYRETURNORG );
p->Release();
c_EmpPhoto.SetBitmap(hBB);
}
   Invalidate();
*/
if (file.Open(strPhotoPathName,CFile::modeRead)&&file.GetStatus(strPhotoPathName,fstatus)&& ((cb = fstatus.m_size) != -1))
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
LPVOID pvData = NULL;
if (hGlobal != NULL)
{
if ((pvData = GlobalLock(hGlobal)) != NULL)
{
file.Read(pvData, cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &ps);
}
}
}
if(SUCCEEDED(OleLoadPicture(ps,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))
{
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
if(FAILED(pPic->Render(*pDC,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL)))
{
ps->Release();
pPic->Release();
AfxMessageBox(_T("渲染图像失败!"));
return;
}
ps->Release();
pPic->Release();
}
else
{
AfxMessageBox(_T("从流中装载图像失败!"));
return;
}
}
}
//InvalidateRect(&rect);
pWnd->ReleaseDC(pDC);
}
}选择图片按钮响应函数:
void CCorpEmpEditDlg::OnBnClickedSetphoto()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
static TCHAR BASED_CODE szFilter[] = _T("BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||");
CFileDialog dlg(TRUE, _T("BMP"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
if (dlg.DoModal() == IDOK)
{
strPhotoPathName = dlg.GetPathName();
DrawYes = TRUE;
//Invalidate();
}
UpdateData(TRUE);
}对话框显示:
void CCorpEmpEditDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting

// TODO: 在此处添加消息处理程序代码
DrawPhoto();
EraseYes = FALSE;
// 不为绘图消息调用 CDialog::OnPaint()
}
存JPG图像至SQL数据库:
if(!strPhotoPathName.IsEmpty())
{
m_strSQL = _T("SELECT * FROM CorpEmp WHERE EmpName='") + v_strEmpName + _T("' AND EmpNamePY='") + v_strEmpNamePY + _T("'");
try
{
// 使用ADO创建数据库记录集
ado.m_pRecordset.CreateInstance(__uuidof(Recordset));
ado.m_pRecordset->Open((_variant_t)m_strSQL, _variant_t((IDispatch*)ado.m_pConnection, true), adOpenStatic, adLockOptimistic, adCmdText);
if(!ado.m_pRecordset->adoEOF)
{
pStm.CreateInstance(_T("ADODB.Stream"));
variant_t varOptional(DISP_E_PARAMNOTFOUND,VT_ERROR);
long lDataSize = ado.m_pRecordset->GetFields()->GetItem(_T("Photo"))->ActualSize;
pStm->PutType(adTypeBinary);
pStm->Open(varOptional, adModeUnknown, adOpenStreamUnspecified, _bstr_t(), _bstr_t());
// 读入文件
pStm->LoadFromFile((_bstr_t)(LPCTSTR)strPhotoPathName);
varBLOB = pStm->Read(adReadAll);
// 保存到数据集对象
ado.m_pRecordset->GetFields()->GetItem(_T("Photo"))->Value = varBLOB;
ado.m_pRecordset->MoveNext();
}
pStm->Close();
if(ado.m_pRecordset != NULL)
ado.m_pRecordset->Close();
}
// 捕捉异常
catch (_com_error e)
{
#ifdef _DEBUG
CATCH_ERROR;
#endif
#ifdef _RELEASE
AfxMessageBox(e.Description());
#endif
return;
}
}从SQL读JPG图像:
m_strSQL = _T("SELECT ISNULL(Photo, 0x0f) AS Photo FROM CorpEmp WHERE EmpName='") + dlg.v_strEmpName + _T("' AND EmpNamePY='") + dlg.v_strEmpNamePY + _T("'");
try
{
// 使用ADO创建数据库记录集
ado.m_pRecordset.CreateInstance(__uuidof(Recordset));
ado.m_pRecordset->Open((_variant_t)m_strSQL, _variant_t((IDispatch*)ado.m_pConnection, true), adOpenStatic, adLockOptimistic, adCmdText);
// 判断记录是否为空
if(!ado.m_pRecordset->adoBOF && !ado.m_pRecordset->adoEOF)
{
// 如果不为空,则检查 Photo 是否为空
_variant_t var = ado.m_pRecordset->GetCollect(_T("Photo"));
CString str = (LPCTSTR)(_bstr_t)var;
if(str != 0x0f)
{
// 需要绘图
dlg.DrawYes = TRUE;
dlg.pStm.CreateInstance(_T("ADODB.Stream"));
variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
dlg.pStm->PutType(adTypeBinary);//类型为二进制
// 得到字段内容的大小
// long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;
// m_pRecordset为一个打开的纪录集对象,含有photo这个blob字段
dlg.pStm->Open( varOptional, adModeUnknown, adOpenStreamUnspecified, _bstr_t(), _bstr_t());
// 打开 pStm
dlg.pStm->Write(_variant_t(ado.m_pRecordset->GetFields()->GetItem(_T("Photo"))->Value));
//dlg.varBLOB = dlg.pStm->Read(adReadAll);
// 把 Photo 字段的内容写入pStm
dlg.pStm->SaveToFile(_T("pub.jpg"), adSaveCreateOverWrite);
//pStm->Close();
}
else
dlg.DrawYes = FALSE;
}
else
dlg.DrawYes = FALSE;
if(ado.m_pRecordset != NULL)
ado.m_pRecordset->Close();
}
// 捕捉异常
catch (_com_error e)
{
#ifdef _DEBUG
CATCH_ERROR;
#endif
#ifdef _RELEASE
AfxMessageBox(e.Description());
#endif
return;
}
我代码从SQL的读写JPG图像都没有问题,但显示有问题,在选择图片时,如果选择图片的窗口遮住了显示图片控件的一部分区域,则该区域不能正常显示图片(没有擦除和重新显示图片),在加载数据库成功读出JPG图片后,图片在对话框上一闪就不见了(也是没有擦除和重新显示图片),想请教问题出在哪里?可有这方面的例子?

解决方案 »

  1.   

    读取数据库记录的功能不应放在OnPaint函数里面。
      

  2.   

    没有放在OnPaint函数里面,我放在初始化函数里面,在我的OnPaint函数里面处理的只是绘制图像,具体流程如下:
    1、判断是否应该显示,如果应该显示,则判断是否是新增加的人员
    2、如果是新增加的人员,则从对话框选择图片按钮所取得的图片路径显示图片
    3、如果不是新增加的人员(即修改人员),则根据从数据库中读出的pStm流显示图片。CSDN没有排版功能,我贴了详细的代码,只是我自己都不知道怎么看了。
      

  3.   

    在选择图片时,如果选择图片的窗口遮住了显示图片控件的一部分区域,则该区域不能正常显示图片(没有擦除和重新显示图片)在选择图片窗口完后
    Invalidate 
    UpdateWindow
      

  4.   

    首先你把读出来的图片载入内存中,用CBitamp对象的Attach附加上去,记住CBitamp必须是一个成员对象(作用是为了防止重复载入图片),在窗口的OnPaint中将它绘制出来.