vb6用MODI直接识别图片框里的图片文字不用磁盘文件用MODI.Document.Stream的完整代码
该专题还在整理中。
MODI(Microsoft Office Document Imaging)确实可以通过 MODI.Document 的 Stream 属性和 IPictureDisp / StdPicture 的交互来直接识别 PictureBox 里已经加载的图片,而不需要先保存成磁盘文件。核心思路是:把 PictureBox 的 Image 属性(StdPicture)通过 SavePicture 写入一个临时流,或者更常见的做法是用 ADODB.Stream 把 StdPicture 转成字节数组再喂给 MODI,但 MODI 本身并不直接接受 StdPicture,所以真正可行的路径只有两条:一是用 SavePicture 写临时文件再删(伪内存),二是用 MODI.Document.Create + Stream 写入图片二进制。后者需要借助 IPictureDisp 的 SaveAsFile 或者 GDI+ / WIA 把 StdPicture 转成流,纯 VB6 + MODI 原生对象模型下没有一步到位的内存识别接口。
先搞清楚 MODI 是什么、还能不能用
MODI 全称 Microsoft Office Document Imaging,是微软随 Office 2003 / Office 2007 附带的 OCR 与文档扫描组件,底层基于 ABBYY 的识别引擎。它提供了一组 COM 自动化对象,最常用的就是 MODI.Document,可以打开 TIFF、BMP、JPG 等图像,调用 OCR 方法后通过 MODI.Image.Layout.Text 拿到识别文字。
需要提醒的是:从 Office 2010 开始微软已移除 MODI,只有装了 Office 2003/2007 的「Document Imaging」组件,或者单独安装 MODI 独立包,才能引用 MODI.Document(在引用列表里显示为 Microsoft Office Document Imaging 12.0 Type Library 或 11.0)。所以在 Win10/Win11 上跑这段代码,第一件事是确认系统里还有 MDIVWCTL.DLL 和 MODI 类型库,否则连引用都加不上。
如果你只是想要 OCR 功能而不执着于 MODI,现在更稳的替代品是 Azure AI Vision 的 Read OCR、百度 OCR 或 ABBYY Cloud OCR SDK,它们都有 HTTP 接口,VB6 用 MSXML2.XMLHTTP 就能调,识别率和维护性远超 MODI。
为什么不能真的「零磁盘文件」
很多人搜这个问题,是希望 MODI.Document.Create 之后直接 Document.Stream = PictureBox.Image。但 VB6 的 StdPicture 不是 IStream,MODI 的 Stream 属性要的是 IStream 或 VARIANT 字节数组,两者类型不兼容。StdPicture 唯一的「导出」方法就是 SavePicture 或 IPictureDisp.SaveAsFile,而这两个本质上都是写文件。所以严格意义上的「完全不用磁盘文件」在纯 VB6 + MODI 下做不到。
能做到的是:不产生用户可见的持久文件,用临时文件 + 立即删除,或者用内存映射 / ADODB.Stream 做中转,让磁盘上只存在毫秒级的临时文件。下面给出两条完整可跑的代码路线。
路线一:临时文件法(最稳、代码最短)
这是实际项目里最常用的写法。PictureBox 里已经有图,先 SavePicture 到 %TEMP%,MODI 打开识别,读完文字立刻 Kill 掉临时文件。
先在 VB6 里添加引用:
- Microsoft Office Document Imaging 12.0 Type Library(或 11.0)
- 不需要额外引用 ADO,但建议加 Microsoft ActiveX Data Objects 2.8 Library 备用
窗体上放一个 PictureBox(名称 Picture1,AutoRedraw 可开可不开)、一个 CommandButton(Command1)、一个 TextBox(Text1,MultiLine=True,ScrollBars=2)。代码如下:
Option Explicit
Private Sub Command1_Click()
Dim tmpPath As String
Dim doc As MODI.Document
Dim img As MODI.Image
Dim i As Long
Dim s As String
If Picture1.Picture Is Nothing Then
MsgBox “图片框里没有图片”
Exit Sub
End If
tmpPath = Environ$(“TEMP”) & “modi_tmp_” & Format$(Timer, “0.000”) & “.bmp”
SavePicture Picture1.Picture, tmpPath
Set doc = New MODI.Document
doc.Create tmpPath
doc.OCR miLANG_CHINESE_SIMPLIFIED, True, True
For i = 0 To doc.Images.Count – 1
Set img = doc.Images(i)
s = s & img.Layout.Text & vbCrLf
Next i
Text1.Text = s
doc.Close
Set doc = Nothing
On Error Resume Next
Kill tmpPath
End Sub
关键点说明:
- doc.Create 接受文件路径,不直接接受流;这是 MODI 对象模型的硬限制。
- doc.OCR 第一个参数是语言常量,简体中文用
miLANG_CHINESE_SIMPLIFIED,英文用miLANG_ENGLISH,日文用miLANG_JAPANESE。第二个参数True表示识别后自动修正,第三个True表示显示进度。 - 识别结果在 img.Layout.Text,一个 Document 可能有多页,所以要循环 Images。
- Kill 前加
On Error Resume Next,防止文件被占用删不掉。
路线二:ADODB.Stream 内存中转 + MODI.Stream 写入
如果你坚持「不出现磁盘文件」,可以用 ADODB.Stream 把 StdPicture 的二进制读出来,再写入 MODI 的 Stream 属性。但注意:MODI.Document.Stream 是只写不读的,它用于把 Document 内容保存成流,而不是用流来创建 Document。真正能用流创建的是 MODI.Document.Create 只认文件路径,所以这条路走不通。
能走通的变体是:用 IPictureDisp.SaveAsFile 写到内存文件系统(如 ImDisk 虚拟盘)或者用 CreateFileMapping 做内存映射,再让 MODI.Create 去读这个「伪文件」。这已经超出纯 VB6 范畴,需要 API 声明,代码量翻倍,稳定性还下降。所以我的建议是:别折腾,用路线一。
MODI 常用常量与参数速查
| 项目 | 值 / 说明 |
|---|---|
| 简体中文语言常量 | miLANG_CHINESE_SIMPLIFIED |
| 英文语言常量 | miLANG_ENGLISH |
| 日文语言常量 | miLANG_JAPANESE |
| OCR 方法签名 | OCR(Language, AutoRotate, ShowProgress) |
| 取文字 | Document.Images(i).Layout.Text |
| 支持的输入格式 | TIFF、BMP、JPG、PNG、GIF、WMF 等 |
| 是否支持内存流创建 | 否,Create 只接受文件路径 |
常见坑与排查
- 「ActiveX 部件不能创建对象」:说明系统没装 MODI,去装 Office 2003/2007 的 Document Imaging 组件,或找 MODI 独立安装包。
- 识别出来是乱码:语言常量选错,中文图片必须用 miLANG_CHINESE_SIMPLIFIED,不能用默认英文。
- SavePicture 报错「无效图片」:PictureBox 的 Picture 属性为空,或者图片是 Icon / Metafile 类型,MODI 不认,先用 PaintPicture 画到标准位图再存。
- 识别速度慢:MODI 首次加载引擎会慢,第二次开始正常;另外图片分辨率太高也会拖慢,可先缩放到 300dpi 等效尺寸。
- 64 位系统:MODI 是 32 位 COM,VB6 本身也是 32 位,没问题;但如果你用 VB.NET 64 位调,会失败。
如果 MODI 实在装不上,替代方案
现在还在维护的 OCR 方案里,VB6 能直接调的有:
- Azure AI Vision Read OCR:REST 接口,识别率高,有免费额度。
- 百度 OCR:中文识别强,VB6 用 MSXML2.ServerXMLHTTP 发 POST 即可。
- ABBYY Cloud OCR SDK:MODI 底层就是 ABBYY,迁移过去识别效果最接近。
- Tesseract:开源本地引擎,VB6 可以通过命令行调用 tesseract.exe,把 PictureBox 存临时文件后识别,再读输出 txt。
如果只是偶尔识别,路线一 + MODI 足够;如果要长期维护、批量识别,建议直接换 Tesseract 或云 OCR,别在 MODI 上投入太多。
相关问题
1. MODI 在 Win10 上还能安装吗?
能,但需要找 Office 2003/2007 的 Document Imaging 组件或 MODI 独立包,安装后注册 MDIVWCTL.DLL 即可,官方已不再支持。
2. 为什么 MODI.Document.Stream 不能用来读取图片?
Stream 属性设计用途是把 Document 保存为流,不是从流创建 Document;创建只能用 Create 方法并传文件路径。
3. PictureBox 里的图片不存文件,能直接给 Tesseract 吗?
不能直接给,Tesseract 命令行只接受文件路径,仍需先 SavePicture 到临时文件,或用其 API 版本传内存指针。
4. MODI 识别中文准确率如何?
印刷体、清晰扫描件下约 90% 左右,手写体和低分辨率图片明显下降,和现代云 OCR 有差距。
5. 有没有纯 VB6 不依赖外部组件的 OCR?
没有可用的纯 VB6 OCR 实现,最轻量也是调用 Tesseract 命令行或走 HTTP 云接口。
内容由 AI 生成,产品信息请以官网为准。













