用VC处理ACCESS中的位图数据

来源:互联网 发布:网络高手黑客怎么联系 编辑:程序博客网 时间:2024/05/17 08:59
用VC处理ACCESS中的位图数据

癫侠于2000-08-17下午05:49:58发表:
----比较复杂的数据库中一般会有位图数据(比如相片)。虽然这类“OLE对象”的插入、删除以及替换操作在ACCESS里容易实现,在VC中却显得复杂而且颇费周折。以下把作者用VC处理ACCESS数据库中的位图数据的体会简单叙述一下,以请教于大家。
----在CdaoRecordset派生类的对象中,VC自动为ACCESS的“OLE对象”域生成一个CLongBinary对象。该类虽然较简单,在程序里却需要使用全局函数GlobalAlloc()和GlobalFree()处理与它的内存句柄m_hData有关操作,访问数据前后要调用GlobalLock()和GlobalUnlock(),而且还要给它的m_dwDataLength赋值,使用起来相对复杂,所以一般推荐使用CByteArray类。这只需要在CdaoRecordset派生类对象的数据说明里修改一下,并把DoFieldExchange()里的DFX_LongBinary()改成DFX_Binary()即可。
----作者定义了一个以CObject为基类的CDib类(CDaoRecordView的派生类里定义了CDib对象成员m_DIB),其中包括一下成员和方法:
CByteArray m_bufDIB;
BOOL Create(CByteArray& ba);
BOOL Create(CFile& bmpFile);
BOOL Paint(HDC hDC);
----m_bufDIB是存储位图数据的缓冲区。为简便起见,它不包含包装信息和BITMAPFILEHEADER结构。这样对数据库更新后,原有的“OLE对象”类型将变成“长二进制数据”,不能在ACCESS里查看了。
----第一个Create()重载方法的参数ba是记录集的位图数据(比如m_image),使用CByteArray::Copy()把数据复制给m_bufDIB;第二个Create()方法的参数bmpFile是已打开的位图文件,使用CFile::ReadHuge()把文件里的数据读入m_bufDIB(放弃前面的BITMAPFILEHEADER结构):
DWORDdwBufSize;
dwBufSize=bmpFile.GetLength();//获得文件长度
bmpFile.Seek((long)sizeof(BITMAPFILEHEADER),
CFile::begin);//放弃文件头
dwBufSize-=sizeof(BITMAPFILEHEADER);
m_bufDIB.SetSize(dwBufSize);//设置缓冲区大小
file.ReadHuge((LPSTR)(m_bufDIB.GetData()),dwBufSize);
……
----Paint()方法调用了SetDIBitsToDevice()函数(根据情况也可以使用StretchDIBits()),参数hDC是CDaoRecordview的资源中的一个静态控制的设备句柄,作为SetDIBitsToDevice()的第一个参数。如果不是16或24位的位图,还需要建立和设置调色板。Paint()方法除了在CDaoRecordView派生类的OnMove()里调用外,也被OnPaint()调用(最好不在OnDraw()里调用):
void CDerivedView::OnPaint()
{
CPaintDC dc(this);
CClientDC dc1(&m_ctlImage);
if(m_DIB.Create(m_pSet->m_image))
m_DIB.Paint(dc1.m_hDC);
}
----作者首先采用的方法是,每当打开一个位图文件,调用m_DIB.Create()和m_DIB.Paint(),然后复制给m_pSet->m_image,再设置“脏”标识:
if(m_DIB.Create(bmpFile))
{
CClientDC dc(&m_ctlImage);
m_DIB.Paint(dc.m_hDC);
(m_pSet->m_image).Copy(m_DIB.m_bufDIB);
SetFieldDirty(&(m_pSet->m_image));
}
----记录滚动时,OnMove()调用Update()对数据进行更新。
----但是这样做的结果是,只有在域的内容不为空(NULL)的时候才能更新数据。也就是说,添加“长二进制数据”不能实现。
----最后发现使用SeieldValue()可以实现添加和替换。但由于作者未知的原因,还需要把另外某个域设置为“脏”才行:
if(m_DIB.Create(bmpFile))
{
CClientDC dc(&m_ctlImage);
m_DIB.Paint(dc.m_hDC);
(m_pSet->m_image).Copy(m_DIB.m_bufDIB);
// 只 为OnPaint() 调 用 时 使 用
m_pSet->SetFieldValue(_T("[image]"),
COleVariant(m_DIB.m_bufDIB));
m_pSet->SetFieldDirty(&(m_pSet->m_name));
// 任 意 另 外 一 个 域
}
----如果打算删除数据库里的位图数据,可以把一个“空”的CByteArray对象替换原来的就行了。
北京联大应用文理学院
苏鸿瑞
*****
原创粉丝点击