實際開發常需儲存圖片、音訊等二進位大物件。本文介紹利用 ADO 存取 BLOB 資料的完整實作,並提供圖片存取顯示的完整範例專案。
CREATE TABLE [dbo].[userphoto] (
[id] [int] IDENTITY(1,1) NOT NULL,
[username] [varchar](50) NULL,
[old] [int] NULL,
[photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
建立資料表,欄位 photo 設為 OLE 物件 類型。範例專案已內建 Access 2000 資料庫。
Field::AppendChunk(_variant_t Data) — 需將二進位資料封裝為 VT_ARRAY | VT_UI1 的 VARIANTField::GetChunk(long Length) — 傳回含資料的 VARIANT,再用 SafeArrayAccessData 取得指標// 假設 m_pBMPBuffer 指向長度為 m_nFileLen 的二進位資料
char* pBuf = m_pBMPBuffer;
VARIANT varBLOB;
SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
m_pRecordset->AddNew();
m_pRecordset->PutCollect(_T("username"), _variant_t(_T("小李")));
m_pRecordset->PutCollect(_T("old"), _variant_t((long)28));
if (pBuf)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = m_nFileLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); // 建立 SAFEARRAY
for (long i = 0; i < (long)m_nFileLen; i++)
SafeArrayPutElement(psa, &i, pBuf++); // 複製資料
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
m_pRecordset->GetFields()->GetItem(_T("photo"))->AppendChunk(varBLOB);
}
m_pRecordset->Update(); // 寫入資料庫
long lDataSize = m_pRecordset->GetFields()->GetItem(_T("photo"))->ActualSize;
if (lDataSize > 0)
{
_variant_t varBLOB = m_pRecordset->GetFields()->GetItem(_T("photo"))->GetChunk(lDataSize);
if (varBLOB.vt == (VT_ARRAY | VT_UI1))
{
char* pBuf = NULL;
SafeArrayAccessData(varBLOB.parray, (void**)&pBuf); // 取得資料指標
// ***** 在此處理 pBuf 指向的圖片資料 *****
// 例如:建立 CBitmap、顯示於 Picture Control
SafeArrayUnaccessData(varBLOB.parray);
}
}
提供的範例專案實作:
char* 指向的 BMP 資料建立 CBitmap 並顯示感謝上一篇讀者的支持與指正,歡迎繼續批評指教。