计算机世界日报
返回首页 产品报价 实用技巧 国产软件 技术天地 站点精选

计算机世界展览会日报

  综合要闻
  企业&人.com
  产品与技术
  网络与通信
  市场与渠道
  99全文检索

CCW网站

  网络世界
  微电脑世界
  IT经理世界
  CCW展览
  信息服务中心   家用电脑世界

兄弟刊物

  电子与信息化
  今日电子
  中国新闻科技
  电子知识产权
  电子产品世界

网上专递

  Linux园地
  友情链接
  冬涛谈法
Dongtao on Law

98内容总汇



实用技巧

用VC 处 理 ACCESS 中 的 位 图 数 据

北 京 联 大 应 用 文 理 学 院
苏 鸿 瑞

---- 比 较 复 杂 的 数 据 库 中 一 般 会 有 位 图 数 据( 比 如 相 片)。 虽 然 这 类“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 结 构):

DWORD dwBufSize;
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 对 象 替 换 原 来 的 就 行 了。
 
免 费 订 阅

实用技巧分类

Office应用
CAD
C、C++
数据库应用
Delphi
Internet应用
Java
Notes应用
操作系统应用
PowerBuilder
VB
Visual Foxpro
其他类
上周 排行榜
如 何 投 稿 ?

编者的话

在日常的工作生活中, 我们对计算机软硬件技术的应用开发肯定有许多的心得体会, 拿来和众人分享:让别人得到他们想要的,使自己找到苦苦寻觅的; 小的点点滴滴,大的工程系统,这里都需要。投稿 的关键在“技巧”二 字,知他人所不知,这样的稿件本栏最最欢迎! 大家公认的 好文章自然会有好的奖励。希望每个人 在这里都有所收获...

r2.gif (980 bytes)
  中国惠普
  3Com中国
  Motorola中国
  CA中国
  Cabletron
  Sony在中国
  西门子WinCC
  爱普生中国
  中国建设银行
  德州仪器(TI)
  问博医药


中国计算机世界出版服务公司版权所有