人事系統需儲存員工大頭照。網路範例多以 BMP 為例,但 JPG 壓縮率高、體積小,更適合資料庫儲存。本文示範 VC6 + Access 2002 (Jet 4.0) + ADO + CPicture 類別 完整實作流程。

資料流向:JPG 檔案 → 記憶體緩衝區 → ADO AppendChunk 寫入 OLE Object 欄位 → 讀取 GetChunk → CPicture 解碼顯示。
// stdafx.h
#import "c:\program files\common files\system\ado\msado15.dll" \
no_namespace rename("EOF", "adoEOF")
// App 初始化
AfxOleInit();
HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");
hr = m_pConnection->Open(
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=wy.mdb", "", "", adModeUnknown);
// Access 97 請改用 Provider=Microsoft.Jet.OLEDB.3.51
// App 結束
if (m_pConnection->State) m_pConnection->Close();
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open("SELECT * FROM 客戶 ORDER BY 客戶id",
_variant_t((IDispatch*)theApp.m_pConnection, true),
adOpenStatic, adLockOptimistic, adCmdText);
void COneDlg::OnButton1()
{
CFileDialog dlg(TRUE, NULL, NULL, 0, _T("JPG Files (*.jpg)|*.jpg||"));
if (dlg.DoModal() != IDOK) return;
CString path = dlg.GetPathName();
CFile file;
if (!file.Open(path, CFile::modeRead | CFile::typeBinary)) return;
int nSize = (int)file.GetLength();
BYTE* pBuffer = new BYTE[nSize];
file.Read(pBuffer, nSize);
file.Close();
// 寫入資料庫
m_pRecordset->AddNew();
VARIANT varBLOB; VariantInit(&varBLOB);
SAFEARRAYBOUND rgsabound[1] = {{0, (ULONG)nSize}};
SAFEARRAY* psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < nSize; ++i)
SafeArrayPutElement(psa, &i, pBuffer + i);
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
m_pRecordset->GetFields()->GetItem("j")->AppendChunk(varBLOB);
m_pRecordset->Update();
// 顯示圖片
m_Pic.LoadPictureData(pBuffer, nSize);
delete[] pBuffer;
CClientDC dc(this);
m_Pic.UpdateSizeOnDC(&dc);
m_Pic.Show(&dc, CRect(200, 0, 200 + m_Pic.m_Width, m_Pic.m_Height));
}
IPicture 介面 (OLE 自動化)LoadPictureData(BYTE*, int)、Show(CDC*, CRect)、FreePictureData()CPicture.h/.cppAccess 表格欄位 j 設為 OLE 物件 (長二進位資料),而非文字/備註欄位。
完整專案含 CPicture 類別、ADO 封裝工具類、測試資料庫與詳細中文註解。