Office中国论坛/Access中国论坛

标题: 用代码插入图片到OLE对象的2种方法 [打印本页]

作者: t小宝    时间: 2013-7-26 17:42
标题: 用代码插入图片到OLE对象的2种方法
Access中的Ole对象总感觉是个神秘的东西,功能好象很强大,既可以显示图片,还可显示Word文档、Excel表格等,但对它的控制却不象其它对象那么容易,联机帮助中讲的不多,仅有的一点帮助看得也是一头雾水。
拿Ole字段储存图片来说,通过菜单操作在Ole字段中插入图片后,在表中会以文字显示,可能是“图片”,又可能是“位图图像”,还可能是“包”,绑定到窗体的Ole对象框后,有的显示图片,有的是显示一个图标加上文件名。总之各种情况,有点让人望而却步,玩不起不玩总可以吧~

不过有时候我们还不得不用它,比如要在连续窗体每一行显示一个图片时,就可以用ole字段来显示图片了。红尘如烟大侠大家都知道吧,他做的通用平台里的图标编辑窗口就是这样的。

那么怎样在ole字段中插入图片文件,绑定到窗体时能显示为图片?有下面两个方法:
1、象上面说的用Access自身提供的插入对象操作,插入图片文件,但只有位图文件能显示图片。
2、把图片插入到Access的图片框中,再复制图片框粘贴到ole对象框,或者把图片插入到Word中,再把Word中的图片复制粘贴到ole对象框。这种方法可以显示大部分格式的图片,jpg、gif、png、ico等都可以,并且还可以保持透明哦~

这些大家可能都懂了,我只是总结一下,呵呵...

但是,昨天岭南王子给我下任务了,说要用纯代码插入图片到ole对象框...王子的命令不得不执行啊...
不过王子的要求很合理,封装好的程序给别人使用,要添加图片,总不能让人打开Word把图片拷来拷去吧,显示得太不专业了。

今天把上面说的两种手工插入图片的方法用代码实现了,把关键的第二种贴上来,做得匆忙请大家指正:
模块中:
  1. ' 示  例: 演示代码插入图片到Ole对象框的2种方法
  2. ' 作  者: t小宝(QQ:377922812)
  3. ' 日  期: 2013-07-26

  4. Private Type METAFILEPICT
  5.         mm As Long
  6.         hMF As Long
  7.         yExt As Long
  8.         xExt As Long
  9. End Type

  10. Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

  11. Private Declare Function SetEnhMetaFileBits Lib "gdi32" (ByVal cbBuffer As Long, lpData As Byte) As Long
  12. Private Declare Function SetMetaFileBitsEx Lib "gdi32" (ByVal nSize As Long, lpData As Byte) As Long
  13. Private Declare Function SetWinMetaFileBits Lib "gdi32" (ByVal cbBuffer As Long, lpbBuffer As Byte, ByVal hdcRef As Long, lpmfp As METAFILEPICT) As Long

  14. Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
  15. Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
  16. Private Declare Function GlobalSize Lib "kernel32.dll" (ByVal hMem As Long) As Long
  17. Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
  18. Private Declare Function GlobalFree Lib "kernel32.dll" (ByVal hMem As Long) As Long

  19. Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
  20. Private Declare Function CloseClipboard Lib "user32" () As Long
  21. Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
  22. Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
  23. Private Declare Function EmptyClipboard Lib "user32" () As Long

  24. Private Const CF_BITMAP = 2
  25. Private Const CF_DIB = 8
  26. Private Const CF_METAFILEPICT = 3
  27. Private Const CF_ENHMETAFILE = 14
  28. Private Const GMEM_MOVEABLE = &H2

  29. '----------------------------------------------------------------------------------------------------------------------------------
  30. ' 代码插入图片到Ole对象框之剪贴板法
  31. ' 原理:先加载图片到图片框,获取图片框的PictureData,根据其类型转为相应格式放到剪贴板,最后粘贴到Ole对象框。
  32. ' 这个方法相当于在设计视图中插入一幅图片到图片框,然后复制该图片框,再在窗体视图中粘贴到Ole对象框。
  33. ' 这种方法支持更多的格式,只要能加载到图片框的图片都可以插入到Ole对象框中并显示。
  34. ' 但透明的png图片会有锯齿,这没办法。因为Ole对象框只能显示位图和图元文件,增强型图元文件粘贴到Ole对象框中会转为图元文件。
  35. ' 另外,图片框能加载的图片格式及效果和电脑上安装的图形筛选器版本有关。
  36. ' 注意:对于2007或以上版本,须要在Access选项中将图片属性储存格式设置为:将所有图片数据转换成位图。否则使用此方法不成功。
  37. ' 也可用LoadPicture直接创建StdPicture对象来获取图像的句柄并处理,但不支持png图片,且gif图片也会丢失透明部分,非透明图片可用。
  38. '----------------------------------------------------------------------------------------------------------------------------------
  39. Public Function ImageToObjFrame(imgBox As Image, objFrame As BoundObjectFrame) As Boolean
  40. On Error GoTo ErrHandle

  41.     Dim bytArray() As Byte
  42.     Dim tMf As METAFILEPICT
  43.     Dim hGlobal As Long
  44.     Dim lHandle As Long
  45.     Dim lRet As Long

  46.     If IsNull(imgBox.PictureData) Then Exit Function

  47.     If OpenClipboard(0) Then                                                      ' 使用剪贴板前先打开
  48.         Call EmptyClipboard                                                       ' 为了不出意外清空剪贴板给自己用
  49.         bytArray() = imgBox.PictureData                                           ' 把图片框的数据放到数组备用

  50.         Select Case bytArray(0)                                                   ' 图片框中的图片有位图、图元文件、增强图元文件3种类型
  51.         Case 40  '位图(DIB)
  52.             hGlobal = GlobalAlloc(GMEM_MOVEABLE, UBound(bytArray) + 1)            ' 创建缓冲区,用于存放DIB数据
  53.             lHandle = GlobalLock(hGlobal)                                         ' 获取缓冲区读写指针,这个指针就是DIB的句柄了
  54.             CopyMemory ByVal lHandle, bytArray(0), UBound(bytArray) + 1           ' 复制字节数组内容(DIB数据)到缓冲区
  55.             GlobalUnlock hGlobal                                                  ' 解锁后才能使用
  56.             lRet = SetClipboardData(CF_DIB, lHandle)                              ' 把DIB放入剪贴板
  57.             GlobalFree hGlobal                                                    ' 释放分配的缓冲区空间,也可以不释放,系统会自己处理
  58.             
  59.         Case 3   '图元文件
  60. '            lHandle = SetMetaFileBitsEx(UBound(bytArray) + 1 - 24, bytArray(24))               ' 创建图元文件
  61. '            lRet = SetClipboardData(CF_METAFILEPICT, lHandle)                                  ' 把图元文件放入剪贴板,不成功,不知何故!

  62.             '上面的代码把图元文件放入剪贴板不成功,转成增强型图元文件就可以了
  63.             CopyMemory tMf, bytArray(8), Len(tMf)
  64.             lHandle = SetWinMetaFileBits(UBound(bytArray) + 24 + 1 - 8, bytArray(24), 0&, tMf)   ' 从图元文件数据创建增强型图元文件
  65.             lRet = SetClipboardData(CF_ENHMETAFILE, lHandle)                                     ' 把增强型图元文件放入剪贴板

  66.         Case 14  '增强图元文件
  67.             lHandle = SetEnhMetaFileBits(UBound(bytArray) + 1 - 8, bytArray(8))                  ' 创建增强型图元文件
  68.             lRet = SetClipboardData(CF_ENHMETAFILE, lHandle)                                     ' 把增强型图元文件放入剪贴板
  69.         Case Else
  70.         End Select
  71.         
  72.         Call CloseClipboard                                                       ' 必须关闭剪贴板才能复制
  73.         
  74.         If lRet Then
  75.             objFrame.SetFocus                                                     ' 把焦点移到Ole对象框
  76.             DoCmd.RunCommand acCmdPaste                                           ' 把上面放到剪贴板中的东东粘贴到Ole对象框中
  77.             Call OpenClipboard(0)                                                 ' 重新打开剪贴板以清空内容。也可以保留
  78.             Call EmptyClipboard                                                   ' 清空剪贴板
  79.             Call CloseClipboard                                                   ' 剪贴板用完要关闭,不然之后程序不能正常复制
  80.             ImageToObjFrame = True
  81.         End If

  82.     End If
  83. ErrHandle:
  84.    
  85. End Function
复制代码
窗体中:
  1. '----------------------------------------------------------------------------------------------------------------------------------
  2. ' 代码插入图片到Ole对象框之剪贴板法
  3. ' 原理:请看模块中的ImageToObjFrame函数
  4. '----------------------------------------------------------------------------------------------------------------------------------
  5. Private Sub Command2_Click()

  6.     Dim sFileName As String
  7.     Dim bytArray() As Byte
  8.     Dim tMf As METAFILEPICT
  9.     Dim hGlobal As Long
  10.     Dim lHandle As Long
  11.     Dim lRet As Long

  12.     sFileName = GetFileName(1, , "图片文件(*.bmp;*.jpg;*.gif;*.ico;*.tif;*.png;*.wmf;*.emf)BMP格式(*.bmp)JPG格式(*.jpg)GIF格式(*.gif)ICO格式(*.ico)TIFF格式(*.tif)PNG格式(*.png)WMF格式(*.wmf)EMF格式(*.emf)")
  13.     If Len(sFileName) = 0 Then Exit Sub

  14.     Me.Image0.Picture = sFileName
  15.    
  16.     If ImageToObjFrame(Me.Image0, Me.FPicture2) Then
  17.         Me.FName = Mid(sFileName, InStrRev(sFileName, "") + 1)
  18.     End If
  19.    
  20.     Me.Image0.Picture = ""
  21.    
  22. End Sub
复制代码
示例mdb是少不了的:





作者: t小宝    时间: 2013-7-26 17:47
坐个沙发
有图有真相,两种方法效果对比
[attach]52226[/attach]

作者: 岭南王子    时间: 2013-7-26 17:58
谢谢分享!

作者: smileyoufu    时间: 2013-7-26 18:06
好东西,板凳一个。
作者: xie62    时间: 2013-7-26 18:23
谢谢分享!

作者: tmtony    时间: 2013-7-26 22:34
精彩, 谢谢小宝分享!
作者: tmtony    时间: 2013-7-26 22:35
转播一下
作者: zhuyiwen    时间: 2013-7-27 05:52
顶一个,呵呵
作者: asklove    时间: 2013-7-29 16:16
收藏了,谢分享
作者: kangking    时间: 2013-8-26 10:39
学习
作者: yanwei82123300    时间: 2013-8-26 15:14
谢谢分享1!小宝老师真棒!
作者: wang1950317    时间: 2013-8-28 21:15
正好用的上,谢谢小宝大师!
作者: yedaoan    时间: 2013-9-12 11:09
好东西,就是一直在找的
作者: 轻风    时间: 2013-9-12 11:52
精彩
作者: yedaoan    时间: 2013-9-15 13:10
t小宝,测试了你的大作,发现一个问题,用方法2添加bmp,马上崩溃,其他图片格式没有问题,最近在用你的这个示列,但是我找不出问题在那里?
作者: yedaoan    时间: 2013-9-15 13:14
刚才又试了一下,不是所有的BMP格式图片都有问题,我这里有几张有问题(这个图片的来源是通过屏幕截图过来的),我发上来,你们研究一下
作者: efcndi    时间: 2013-9-16 14:38
看看
作者: zhao__feng    时间: 2013-9-20 21:36
谢谢分享!
作者: wuheng    时间: 2013-9-29 17:22
学习呀~~~~~```
作者: 大懒猫68    时间: 2013-10-3 14:59
好东西,板凳一个
作者: fcghw    时间: 2013-10-11 02:53
还是看不懂啊
作者: fcghw    时间: 2013-10-11 02:54
还是看不懂了
作者: 程研    时间: 2013-10-11 11:41

作者: XB2009    时间: 2013-11-13 16:29
看看
作者: 好运牛    时间: 2013-11-13 17:37
谢谢t小宝 大师的分享
作者: 好运牛    时间: 2013-11-13 17:48
非常感谢大师的指导

作者: sxb2007    时间: 2013-11-15 11:35
谢谢分享!
作者: 好运牛    时间: 2013-11-17 10:40
学做了实例,很有收获。顶
作者: 13601812106_01    时间: 2013-12-4 12:31
好好好

作者: leonshi    时间: 2014-1-8 08:46
学习

作者: justic    时间: 2014-2-8 10:33
正是我所需的
作者: louislee    时间: 2014-4-25 19:19
ding
作者: xiaowuo2    时间: 2014-4-25 20:05
看看效果如何,顶个
作者: lzh199    时间: 2014-5-16 13:50
学习学习啊
作者: zcg13051    时间: 2014-5-16 17:19
回复看看学习学习
作者: shuyangchao    时间: 2014-5-16 23:13
学习
作者: 小桥人家    时间: 2014-5-30 20:36
学习学习
作者: yjlchen    时间: 2014-5-30 21:49
谢谢分享
作者: lancet    时间: 2014-6-6 07:43
Thanks,that's my looking for
作者: layaman_999    时间: 2014-6-11 12:08
非常精彩,受教了
作者: ilikeu    时间: 2014-6-13 10:51
下来看看
作者: zpy2    时间: 2014-6-19 07:14
学习了!!!
作者: wx0000888    时间: 2014-9-6 16:33
真有这种方法,谢谢
作者: liumporite    时间: 2014-9-24 14:38
DDDDDDDDDDDDDDDDDDDDDDDD
作者: yanghua1900363    时间: 2014-9-24 22:48
谢谢分享必须的
作者: th2328646    时间: 2014-10-14 14:06
sdfsf
作者: znbcaozhiming    时间: 2014-10-17 00:30
初学,正好可以学习下
作者: sunwrsun    时间: 2014-10-29 22:09
看看
作者: herry2003aa    时间: 2014-10-31 01:11
查看事例是少不了的。
作者: dhlhmgc    时间: 2014-11-11 02:42
学习了,对OLE的处理不熟,感谢分享
作者: LiYuanqi    时间: 2014-12-16 19:50
谢谢楼主分享
作者: zxclen    时间: 2014-12-19 17:17

作者: lee2099    时间: 2015-1-13 09:31
有图有真相,两种方法效果对比

作者: 天涯沦落20131    时间: 2015-1-14 11:11
000000
作者: zhhporsche    时间: 2015-1-20 09:36
此贴不错,正是我所需要的,赞一个
作者: 水滴的邂逅    时间: 2015-1-21 16:03
learning how to do it
作者: 站到终点站    时间: 2015-2-6 21:54
学习了
作者: pstoto    时间: 2015-3-31 00:20
感谢分享技术
作者: 老榕树下    时间: 2015-5-23 15:09
找了好久,终于找到了
作者: ppppn    时间: 2015-5-31 16:41
学习
作者: 205226    时间: 2015-6-25 14:48
学习!!!
作者: YXH_YXH    时间: 2015-7-31 10:42
多谢分享!!!!!!!!
作者: 读书人2015    时间: 2015-7-31 22:45
这要好好看看
作者: huangqinyong    时间: 2015-8-13 16:18
好好学习一下
作者: ligand    时间: 2015-9-21 18:15
很棒。好好学习一下
作者: 魔天天自在    时间: 2015-10-24 22:56
学习了 太高深了
作者: 三毛流浪记    时间: 2015-10-25 18:00
666
作者: zhoubo780624    时间: 2015-12-7 02:08
学习 一下
作者: Joshui    时间: 2015-12-12 23:42
xuexie ~
作者: dmvpey    时间: 2015-12-22 19:31
1,建议楼主自己发帖的时候粘贴个图片效果出来
2,是否能支持缩放?
作者: xlb004    时间: 2016-1-7 19:00
1111111111111111111111111111111111
作者: jxlt    时间: 2016-1-10 11:34
测试一下。。。
作者: alphalau81    时间: 2016-2-25 16:37
看看O(∩_∩)O哈哈哈~
作者: spirityq    时间: 2016-2-26 16:36
找这个实例真的找了好久呀!
作者: 玉树TMD临风    时间: 2016-2-27 20:36
怎么这么麻烦的。
作者: 玉树TMD临风    时间: 2016-2-27 20:41
下载测试了一下都没成功,特别是方法二一试就停止响应。我的图片已经设置为将所有图片数据转换成位图,加载ICO、JPG和BMP都报错。
作者: hunrybecky    时间: 2016-2-28 01:35
正需要这个例子,找了很久
作者: yphxsjjlcq    时间: 2016-3-2 00:19
谢谢分享!
作者: shindo8888    时间: 2016-3-10 13:58
关注,学习中
作者: v1453213087    时间: 2016-3-10 16:32
看看

作者: leolifk    时间: 2016-3-14 14:50
感谢楼主,好好学习,天天向上
作者: baidu321    时间: 2016-3-15 10:15
哇  这个有用,想问下楼主,这个方法像占用数据库多大空间???
作者: guowj_sqi    时间: 2016-3-19 14:55
谢谢楼主分享!
作者: 雪山一支蒿    时间: 2016-3-26 20:53
学习学习
作者: csxt    时间: 2016-3-31 21:08
正是我想要的下来看看
作者: aslxt    时间: 2016-4-1 17:29
学习学习
作者: pwj2009    时间: 2016-4-5 23:56
感谢分享!!
作者: newglord    时间: 2016-4-7 16:10
回复好下载
作者: jianghu1    时间: 2016-4-7 17:39
下载来看看
作者: cityguy    时间: 2016-4-25 15:44

谢谢分享!!
作者: zhujie666    时间: 2016-4-28 10:09
真的是个好东西啊
作者: JohnYao    时间: 2016-5-31 12:13
对于小公司用作记录数据库文件当中的图片来说,真的很方便。
作者: wx0000888    时间: 2016-6-27 12:16
经过测试:

ACCESS2000版的  jpg格式的可以通过     bytArray(0-3591)    bytArray(0) =14
ACCESS2010版的  jpg格式的不能通过     bytArray(0-1405)    bytArray(0) =0   ,其他格式也不行.
作者: 唐金龙    时间: 2016-7-8 16:49
看一看学习一下.
作者: p51219    时间: 2016-7-10 00:13
好好好红啊红啊后
作者: COMEON    时间: 2016-7-20 16:52
this is what i want. thanks!

作者: jicheng    时间: 2016-8-17 14:26
学习
作者: MYDAAN    时间: 2016-9-5 21:00
好久没回来了,学习一下
作者: Dozen    时间: 2016-9-16 15:08
一大段代码,吓死人了。。。
作者: 飞鸿    时间: 2016-11-9 13:33
大大大大大大大大大大大大大




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3