|
前言:
在讨论主题以前让我们先来了解今天的主角「TWAIN」到底是什么?早期的Developer为了发展具备「截取图形」的应用程式,伤透了脑筋,他们必须从各个发展平台(plateform)的SDK(Software Development Kit)中寻求各厂牌扫描机的技术支援资料,也因此花费了许多的人力与时间。主要的原因是各家的标准不一。直到1992年春,业界的几个龙头∶Aldus, Caere, Eastman-Kodak, Hewlett-Packard, Logitech Corporations共同制定了一套标准技术来解决长期困扰的问题,(题外话∶台湾的罗技电子也在其中,大家是否与有荣焉?)业界称这个标准为TWAIN,它适用於MS-WIN, UNIX, MAC这几个平台。当然大家也知道∶尔後陆续发展出来的影像输入设备,几乎都支援这个标准;大约有175家软应体发展公司也加入这个组织。如果对它有兴趣的狐友可至www.twain.org去看看。当然我们今天讨论主题所使用的「EZTWAIN」也是由这个组织所发展的。狐友必须先到前面所提的web site 去download 「eztw105.zip」这支档案,才有办法去达成扫图的目的(假设您不采用直接呼叫twain.dll(16bit)或twain_32.dll(32bit),及使用OLE技术的话)。
探讨 :
为什么不直接使用呼叫twain.dll的技术却使用了eztwain.dll ?其实在很多情况下AP所要求的功能是「有图就好」,譬如∶员工、会员、产品资料库等等。在这些资料的维护程序中「图」只是一个辅助资料,Users并不需要太去关心影像的品质(如:解析度、色相、亮度对比…..)。更何况要user去了解这些影像专有名词或去操作影像处理(应用)程式只会增加user的困扰(透过OLE的方式来操作也是如此)。既然如此,developer就应该让user在不需切换程式的前题下去取得影像,共用的UI使用起来将方便很多。既然如此,吾人便必需去「驾驭」twain.dll。可是「驾驭」何其容易?动态联结函数库dll的使用原本就蛮麻烦的(如果您手头没有资料,至少取得其相关参数、资料型态或传回值是挺累人的)。更何况坊间要取得twain.dll这个「影像专用」的函式库相关资讯好像蛮难的。就算拿到了,里头对影像的相关规范会让很多人望之却步。前面谈到∶「了解那么多干嘛?又不是写影像处理软体!」确实,如果只是要扫图,只需用到某些函式就可以了。於是乎,TWAIN写了「简易版」来解决这样的问题,那就是eztwain.dll的由来。利用eztwain中的少数几个函式便可达到统一UI的目的。请注意∶只是「统一UI」而已,并不是完全使用自设的界面。也就是说∶利用eztwain在user不必切换程式的情形下来呼叫原硬体厂商所提供的影像输入使用者界面。扫图後可以直接回存至通用栏位或先在萤幕上显示後再决定是否回存档案。再举例说明∶如果您用的是EPSON的scaner,它提供了一个标准的扫图界面,可以设定相关的扫图条件;而不论您使用photoshop或coreldwaw来处理影像,只要在应用程式中去下达「扫图」功能,最後都会出现EPSON的UI。所有的前置处理完全由这个UI来做。应用程式只负责去呼叫UI,得到影像後再处理後续程序。我们今天所示范的正是这样的功能,至於如果要使用自订UI取代EPSON所附,进而做一些设定如:RGB或B&W等…..则您必需去使用etwain.dll的其它相关函式,如果有兴趣的话可参考etwain.h这个档案所列含式,在本主题中将只示范呼叫source UI。
前置注意事项∶
当您download了eztw105.zip解压後会产生数个目录∶\vfp中还有zip file也就是我们以下要示范的,(请注意它是for fp 2.5)解压後可以找到eztwain.dl
及foxtool.fll(如果您用的是vfp,请使用新版本的foxtool.fll,vfp的外部函数库并不向下相容!)。另外有vb的范例 \vb(同样请注易意版本);\source下有几支c的引入档,有需要者可参考。
原范例由Kevin Moreland (COMPUSERVE ID: 76720,3365)於www.twain.org发表
范例∶
原范例中采用了menu的方式来作业,本范例则采用表单(form)来说明:以便尔後可灵活运用於员工、产品或客户主档维护作业中(当然不同的通用栏位
指定需另外处理)
它包含了cmdSelectSource选择来源按钮(commandButton)
cmdAcquire 开始扫瞄按钮(commandButton)
cmdExit 回前作业按钮(commandButton)
optDestType 输出格式选项按钮组(optionGroup)
value 1:扫描至萤幕 2.扫瞄至档案
ckTwn 自订属性,用来控制当eztwain无法呼叫时
( 未安装twain.dll或eztwain及错误时)
选择来源及开始扫描钮反致能
scanprocess 自订程序,用来指定user click commandButton後
程式的走向(程式该如何处理)
接收参数pc_Smode→
'Acquire' 代表扫瞄
'SelSource 表'选取影像来源,比如同时拥有scaner
及数位像机时可让user自行决定来源
pc_DBF →
'BMP' 代表存到档案,选取影像来源时无此参数
注意:
此程序会使用到TwnSelSrc 已向Foxtools注册的功能
用来呼叫EZTWAIN.DLL中 TWAIN_SelectImageSource
这个功能(用来让user选取影像来源)
startscan 自订程序,开始扫图
让使用者藉由twain.dll来扫图
注意:
需呼叫 TwnAcqNat 已向Foxtools 注册的功能用来呼
叫EZTWAIN.DLL中TWAIN_AcquireNative 这个功能
需呼叫TwnDib2BMP - 已向Foxtools注册的功能用来
呼叫EZTWAIN.DLL中TWAIN_WriteNativeToFilename
接收参数pc_Dest →"BMP"∶表在萤幕中显示
"DBF" ∶存入档案中
pc_Fhandle →档名
pc_DBF →table名,pc_Dest = "DBF"才有用到
pc_FldName →栏位名(通用栏位名)
***************************
myform.Load Even Code: 如下
***************************
SET LIBRARY TO foxtools ADDITIVE
PUBLIC Gc_fnBMP
TwnAvail = RegFn("TWAIN_IsAvailable","","L","EZTWAIN.DLL") &&注册
&& 因为范例中使用eztwain.dll是for 16bits所以要用RegFn()来注册
&& 如果for 32bits则用RegFn32()
&& 注册失败时传回-1
pn_TwnOk = CallFn(TwnAvail)
Gl_TwnOk = IIF(pn_TwnOk = 1, .T., .F.) &&後续判断用
Gc_fnBMP = "C:\SCANTEST\" &&scanprocess()会用到….
IF Gl_TwnOk
PUBLIC Gn_TwnVer, TwnSelSrc, TwnAcqNat, TwnDib2BMP,;
wnDib2Fil, TwnFree
TwnVer = RegFn("TWAIN_EasyVersion","","I","EZTWAIN.DLL")
&& 注册RETURN 2成功
Gn_TwnVer = CallFn(TwnVer) / 100
&&RETURN 1.04 传回版本
TwnSelSrc = RegFn("TWAIN_SelectImageSource","I","I","EZTWAIN.DLL")
&&注册RETURN3
TwnAcqNat = RegFn("TWAIN_AcquireNative","II","I","EZTWAIN.DLL")
&&注册RETURN 4
TwnDib2BMP=RegFn("TWAIN_WriteNativeToFilename","IC","I","EZTWAIN.DLL")
&&注册RETURN 5
TwnFree = RegFn("TWAIN_FreeNative","I","I","EZTWAIN.DLL") &&
&&注册RETURN 6
ELSE
This.ckTwn=.f. && myform的新增属性用於eztwain未能载入时
&& disenabled( 反致能) cmdSelectSource(选择来源按钮)
&& 反致能cmdAcquire(开始扫瞄按钮)
ENDIF
******************************
myform.Refresh Even Code: 如下
******************************
if !This.ckTwn
this.cmdSelectSource.enabled=.f.
this.cmdAcquire.enabled=.f.
=messagebox(“ 注册失败,尚未安装驱动程式”,48,”系统讯息”)
endif
************************************
myform.cmdAcquire.click Even Code: 如下
************************************
if thisform.optDestType.value=1
thisform.scanprocess('Acquire','BMP')
else
thisform.scanprocess('Acquire', 'DBF')
endif
****************************************
myform.cmdSelectSource.click Even Code: 如下
****************************************
thisform.scanProcess('SelSource')
****************************************
myform.cmdExit.click Even Code: 如下
****************************************
clear dlls
thisform.Release()
****************************
myform.scanprocess() 自订程序
****************************
PARAMETER pc_SMode, pc_DBF
PRIVATE pc_fnBMP, pc_fnTXT
pc_SMode = UPPER(pc_SMode)
DO CASE
CASE pc_SMode = 'SELSOURCE' &&显示目前可用的来源
Pn_Result = CallFn(TwnSelSrc,0) &&传回1表ok 2表cancel
CASE pc_SMode = 'ACQUIRE'
pc_fnBMP = Gc_fnBMP + ALLTRIM(myTable.Field) + ".BMP"
&& 此处的myTable.Field指的是自订的图档名称
IF pc_DBF = 'BMP' &&在萤幕中show图
=startScan("BMP", pc_fnBMP)
ELSE &&扫图後存档
=startScan("DBF", pc_fnBMP,”myTablename”,”myFieldname")
&&myTablename主档档名
&&myTablename 通用栏位名
ENDIF
ENDCASE
RETURN
*************************
myform.startscan() 自订程序
*************************
PARAMETER pc_Dest, pc_FHandle, pc_DBF, pc_FldName
PRIVATE pn_hDib, pn_Result, pl_Done, pc_Topic, pn_Free
pc_Dest = IIF(PARAMETERS() < 1, "BMP", UPPER(pc_Dest))
pl_Done = .F.
IF PARAMETERS() < 2
pc_FHandle = 0
ELSE
IF FILE(pc_FHandle)
IF messagebox(' 图档已经存在要覆写吗?,4+32+256)=6
DELETE FILE &pc_FHandle
ELSE
pl_Done = .T.
ENDIF
ENDIF
ENDIF
IF !pl_Done
&& 开始截图(此为EZTWAIN.DLL的内部功能)
pn_hDib = CallFn(TwnAcqNat,0,0)
IF pn_hDib = 0
=messagebox(' 使用者取消扫瞄或无法扫瞄’,64,”系统讯息”)
ELSE
&& 以下将截取的DIB档转为BMP档(EZTWAIN.DLL的内部功能)
&& 并释放DIB所暂的记忆体空间
pn_Result = CallFn(TwnDib2BMP,pn_hDib,pc_FHandle)
pn_Free = CallFn(TwnFree,pn_hDib)
DO CASE
CASE pn_Result = 0
=messagebox(' 成功取得图档’,64,”系统讯息”)
&&以下为将取得的BMP档show出
IF NOT WEXIST("LW_Image") &&尚未定义视窗
DEFINE WINDOW LW_Image ;
AT 0.000, 0.000;
SIZE 30.1,57.0;
FONT "MS Sans Serif", 8 ;
TITLE " 扫图结果∶" ;
FLOAT ;
GROW ;
CLOSE ;
SYSTEM
MOVE WINDOW LW_Image CENTER
ENDIF
CASE pc_Dest = "BMP" &&萤幕中show图,建立一暂存档
CREATE CURSOR TmpImgDBF (Gr_Image G)
APPEND BLANK
APPEND GENERAL Gr_Image FROM (pc_FHandle) LINK
MODIFY GENERAL Gr_Image WINDOW LW_Image
USE IN TmpImgDBF
CASE pc_Dest = "DBF"
SELECT (pc_DBF)
APPEND GENERAL (pc_FldName) FROM (pc_FHandle) LINK
MODIFY GENERAL (pc_FldName) WINDOW LW_Image
ENDCASE
RELEASE WINDOW Lw_Image
&&错误处理
&&-1, -2, -3, -4 是EZTWAIN所传回的错误码
DO CASE
CASE pn_Result = -1
=messagebox(' 使用者取消存档作业’,64,”系统”)
CASE pn_Result = -2
=messagebox(' 档案开启错误’,16,”错误”)
CASE pn_Result = -3
=messagebox(' 无法锁定影像', 16,'错误' )
CASE pn_Result = -4
=messagebox(' 无法存成BMP模式,系统满载',16,”错误”)
OTHERWISE
=messagebox(' 一般性错误',16,”错误”)
ENDCASE
ENDIF
ENDIF
RETURN
结语 :
以上范例为了让狐友能很快的理解而将原例做了局部修改并加上中文注解,如有疑惑可参考原例。(原例中尚有scaner 配合fax的范例)
建议狐友应尽量直接去深入了解EZTWAIN内部的各个函式,应更可快速上手(如后附)。事实上也有一些付费的ActiveX(ocx)可用,但因非一言可蔽之,有机会再与众狐友共同讨论。
|
本文来源:
台湾飞狐
本文作者:
|
|
FOXPRO网络工作室 版主马军 欢迎连接
|
Tags:功能 加入 影像 使用 注册 CASE EZTWAIN.DLL BMP 呼叫
|