1. include "twaincpp.h"
  2. #include <QtGlobal>
  3. #include <QDateTime>
  4. #include <QString>
  5.  
  6. #pragma execution_character_set("utf-8");
  7.  
  8. CTwain::CTwain(HWND hWnd)
  9. {
  10. m_hMessageWnd = nullptr;//消息窗口句柄
  11. m_hTwainDLL = nullptr;//是否已载入库
  12. m_pDSMProc = nullptr;//数据源管理器
  13. m_bSourceSelected = false;//是否已选择数据源
  14. m_bDSOpen = false;//是否已打开数据源
  15. m_bDSMOpen = false;//是否已打开数据源管理器
  16. m_bSourceEnabled = false;//数据源是否设为可用
  17. m_bModalUI = true;
  18. m_nImageCount = TWCPP_ANYCOUNT;
  19. if(hWnd)
  20. {
  21. qDebug()<<"在构造函数中安装Twain";
  22. InitTwain(hWnd);
  23. }
  24. }
  25.  
  26. CTwain::~CTwain()
  27. {
  28. ReleaseTwain();
  29. }
  30.  
  31. /*
  32. Initializes TWAIN interface . Is already called from the constructor.
  33. It should be called again if ReleaseTwain is called.
  34. hWnd is the window which has to subclassed in order to recieve
  35. Twain messaged. Normally - this would be your main application window.
  36. 初始化TWAIN接口。已经从构造函数调用。
  37. 如果调用ReleaseTwain,则应再次调用它。
  38. hWnd是必须进行子类化以便接收的窗口Twain消息。
  39. 通常 - 这将是您的主要应用程序窗口。
  40. */
  41. bool CTwain::InitTwain(HWND hWnd)
  42. {
  43. qDebug()<<"****************开始安装Twain****************";
  44. char libName[512];
  45. if(IsValidDriver())
  46. {
  47. return true;
  48. }
  49. memset(&m_AppId,0,sizeof(m_AppId));
  50. if(!IsWindow(hWnd))//确定给定的窗口句柄是否标识一个已存在的窗口
  51. {
  52. return false;
  53. }
  54. m_hMessageWnd = hWnd;//要传递消息的窗口
  55. strcpy_s(libName,"TWAIN_32.DLL");
  56.  
  57. m_hTwainDLL = LoadLibraryA(libName);//载入库
  58. if(m_hTwainDLL != nullptr)
  59. {
  60. qDebug()<<"已载入有效扫描驱动";
  61.  
  62. //获取数据源管理器入
  63. if(!(m_pDSMProc = (DSMENTRYPROC)GetProcAddress(m_hTwainDLL,(LPCSTR)MAKEINTRESOURCE(1))))
  64. {
  65. qDebug()<<"获取数据源管理器入口失败";
  66. FreeLibrary(m_hTwainDLL);
  67. m_hTwainDLL = nullptr;
  68. }
  69. else
  70. {
  71. qDebug()<<"获取数据源管理器入口成功";
  72. }
  73. }
  74. if(IsValidDriver())//成功载入驱动且获取了数据源管理器
  75. {
  76. GetIdentity();//设置应用程序信息
  77.  
  78. //打开数据源管理器
  79. m_bDSMOpen = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&m_hMessageWnd);
  80. if(m_bDSMOpen)
  81. {
  82. qDebug()<<"初始化Twain接口:打开数据源管理器成功";
  83. get_source_list();
  84. qDebug()<<"****************结束安装Twain****************";
  85. return true;
  86. }
  87. else
  88. {
  89. qDebug()<<"初始化Twain接口:打开数据源管理器失败";
  90. qDebug()<<"****************结束安装Twain****************";
  91. return false;
  92. }
  93. }
  94. else
  95. {
  96. qDebug()<<"****************结束安装Twain****************";
  97. return false;
  98. }
  99. }
  100.  
  101. /*
  102. Releases the twain interface . Need not be called unless you
  103. want to specifically shut it down.
  104. 释放twain接口。除非你想要特别关闭它。
  105. */
  106. void CTwain::ReleaseTwain()
  107. {
  108. qDebug()<<"****************开始析构Twain****************";
  109. if(IsValidDriver())//如果已加载有效的驱动程序且存在数据源管理器入口
  110. {
  111. CloseDSM();
  112. FreeLibrary(m_hTwainDLL);
  113. m_hTwainDLL = nullptr;
  114. m_pDSMProc = nullptr;
  115. sourcelist.clear();
  116. }
  117. qDebug()<<"****************结束析构Twain****************";
  118. }
  119.  
  120. /*
  121. Returns true if a valid driver has been loaded
  122. 如果已加载有效的驱动程序且存在数据源管理器入口,则返回true
  123. */
  124. bool CTwain::IsValidDriver() const
  125. {
  126. return (m_hTwainDLL && m_pDSMProc);
  127. }
  128.  
  129. /*
  130. Entry point into Twain. For a complete description of this
  131. routine please refer to the Twain specification 1.8
  132. 进入Twain的入口点。有关此的完整描述
  133. 例程请参考Twain规范1.8
  134. */
  135. bool CTwain::CallTwainProc(pTW_IDENTITY pOrigin,pTW_IDENTITY pDest,
  136. TW_UINT32 DG,TW_UINT16 DAT,TW_UINT16 MSG,
  137. TW_MEMREF pData)
  138. {
  139. // qDebug()<<"****************开始数据源管理器相关操作****************";
  140. if(IsValidDriver())//如果已加载有效的驱动程序且存在数据源管理器入口
  141. {
  142. USHORT ret_val;
  143.  
  144. //数据源管理器相关操作
  145. ret_val = (*m_pDSMProc)(pOrigin,pDest,DG,DAT,MSG,pData);
  146.  
  147. // qDebug()<<"数据源管理器相关操作结果"<<ret_val;
  148. m_returnCode = ret_val;
  149.  
  150. /////////////////////吐血开始//////////////////
  151. // if(ret_val != TWRC_SUCCESS)
  152. // {
  153. // qDebug()<<"数据源管理器相关操作失败";
  154.  
  155. // //初始化数据源管理器
  156. // (*m_pDSMProc)(pOrigin,pDest,DG_CONTROL,DAT_STATUS,MSG_GET,&m_Status);
  157. // }
  158. // else
  159. // {
  160. // qDebug()<<"数据源管理器相关操作成功";
  161. // }
  162. ////////////////////吐血结束/////////////////
  163.  
  164. // qDebug()<<"****************结束数据源管理器相关操作****************A";
  165. return (ret_val == TWRC_SUCCESS);
  166. }
  167. else
  168. {
  169. m_returnCode = TWRC_FAILURE;
  170. // qDebug()<<"****************未加载有效的驱动程序或不存在数据源管理器入口****************";
  171. // qDebug()<<"****************结束数据源管理器相关操作****************B";
  172. return false;
  173. }
  174. }
  175.  
  176. /*
  177. This function should ideally be overridden in the derived class . If only a
  178. few fields need to be updated , call CTawin::GetIdentity first in your
  179. derived class
  180. 理想情况下,应在派生类中重写此函数。 如果只有一个
  181. 几个字段需要更新,首先在你的电话中调用CTawin :: GetIdentity
  182. 派生类
  183.  
  184. 设置应用程序信息
  185. */
  186. void CTwain::GetIdentity()
  187. {
  188. // Expects all the fields in m_AppId to be set except for the id field.
  189. //期望m_AppId中的所有字段都要设置,除了id字段。
  190. m_AppId.Id = 0; // Initialize to 0 Source Manager
  191. // will assign real value)
  192. m_AppId.Version.MajorNum = 1; //Your app's version number
  193. m_AppId.Version.MinorNum = 0;
  194. m_AppId.Version.Language = TWLG_USA;
  195. m_AppId.Version.Country = TWCY_USA;
  196. strcpy_s (m_AppId.Version.Info, "1.0");
  197. m_AppId.ProtocolMajor = TWON_PROTOCOLMAJOR;
  198. m_AppId.ProtocolMinor = TWON_PROTOCOLMINOR;
  199. m_AppId.SupportedGroups = DG_IMAGE | DG_CONTROL;
  200. strcpy_s (m_AppId.Manufacturer, "MICSS");
  201. strcpy_s (m_AppId.ProductFamily, "Generic");
  202. strcpy_s (m_AppId.ProductName, "jiandao Twain");
  203. }
  204.  
  205. /*
  206. Called to display a dialog box to select the Twain source to use.
  207. This can be overridden if a list of all sources is available
  208. to the application. These sources can be enumerated by Twain.
  209. it is not yet supportted by CTwain.
  210. 调用以显示一个对话框以选择要使用的Twain源。
  211. 如果所有源列表都可用,则可以覆盖此项
  212. 到申请。这些来源可以由Twain列举。
  213. 它还没有得到CTwain的支持。
  214.  
  215. //选择数据源
  216. MSG_USERSELECT的效果是弹出一个框让用户选择数据源
  217. */
  218. bool CTwain::SelectSource()
  219. {
  220. qDebug()<<"****************开始选择数据源****************";
  221. memset(&m_Source,0,sizeof(m_Source));
  222. if(!SourceSelected())//扫描时候未选择数据源,则设置数据源为默认的数据源
  223. {
  224. SelectDefaultSource();
  225. }
  226. if(CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_USERSELECT,&m_Source))//MSG_OPENDS
  227. {
  228. m_bSourceSelected = true;
  229. qDebug()<<"成功应用所选的数据源";
  230. }
  231. else
  232. {
  233. m_bSourceSelected = false;
  234. qDebug()<<"应用所选的数据源失败";
  235. }
  236. qDebug()<<"****************结束选择数据源****************";
  237. return m_bSourceSelected;
  238. }
  239.  
  240. //选择默认的数据源
  241. bool CTwain::SelectDefaultSource()
  242. {
  243. qDebug()<<"未选择数据源,使用默认的数据源";
  244. m_bSourceSelected = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETDEFAULT,&m_Source);
  245. if(m_bSourceSelected)
  246. {
  247. qDebug()<<"使用默认的数据源成功";
  248. }
  249. else
  250. {
  251. qDebug()<<"使用默认的数据源失败";
  252. }
  253. return m_bSourceSelected;
  254. }
  255.  
  256. //关闭数据源 先禁用再关闭
  257. void CTwain::CloseDS()
  258. {
  259. qDebug()<<"****************开始关闭数据源****************";
  260. if(DSOpen())//数据源是打开的
  261. {
  262. DisableSource();
  263. qDebug()<<"关闭数据源";
  264. CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&m_Source);
  265. m_bDSOpen = false;
  266. }
  267. qDebug()<<"****************结束关闭数据源****************";
  268. }
  269.  
  270. //关闭数据源管理器
  271. void CTwain::CloseDSM()
  272. {
  273. qDebug()<<"****************开始关闭数据源管理器****************";
  274. if(DSMOpen())//如果数据源管理器是打开的
  275. {
  276. CloseDS();//关闭数据源
  277. qDebug()<<"执行关闭数据源管理器";
  278. CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_PARENT,MSG_CLOSEDSM,(TW_MEMREF)&m_hMessageWnd);
  279. m_bDSMOpen = false;
  280. }
  281. qDebug()<<"****************结束关闭数据源管理器****************";
  282. }
  283.  
  284. /*如果:
  285. 1、数据源是打开的
  286. 2、数据源管理器是打开的
  287. 3、数据源管理器入口存在
  288. 返回true
  289. */
  290. bool CTwain::DSMOpen() const
  291. {
  292. return IsValidDriver() && m_bDSMOpen;
  293. }
  294.  
  295. /*如果:
  296. 1、数据源是打开的
  297. 2、数据源管理器是打开的
  298. 3、数据源管理器入口存在
  299. 4、已载入扫描驱动
  300. 返回true
  301. */
  302. bool CTwain::DSOpen() const
  303. {
  304. return IsValidDriver() && DSMOpen() && m_bDSOpen;
  305. }
  306.  
  307. //打开作为输入参数提供的数据源
  308. bool CTwain::OpenSource(TW_IDENTITY *pSource)
  309. {
  310. if(pSource)
  311. {
  312. m_Source = *pSource;
  313. }
  314. if(DSMOpen())//如果此时数据源管理器是打开的
  315. {
  316. qDebug()<<"xxxxxxxxxxx";
  317. if(!SourceSelected())//此时未选中数据源
  318. {
  319. SelectDefaultSource();
  320. }
  321. //打开数据源
  322. m_bDSOpen = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_OPENDS,(TW_MEMREF)&m_Source);
  323. }
  324. return DSOpen();
  325. }
  326.  
  327. /*
  328. Should be called from the main message loop of the application. Can always be called,
  329. it will not process the message unless a scan is in progress.
  330. 应该从应用程序的主消息循环调用。可以随时调用,
  331. 除非正在进行扫描,否则它不会处理消息。
  332.  
  333. 消息事件
  334. */
  335. bool CTwain::ProcessMessage(MSG msg)
  336. {
  337. if (msg.message == 528) // don't really know why...
  338. {
  339. return false;
  340. }
  341.  
  342. if (m_hMessageWnd == nullptr)
  343. {
  344. return false;
  345. }
  346.  
  347. if(SourceEnabled() && m_pDSMProc)//如果数据源可用
  348. {
  349. TW_EVENT twEvent;
  350. twEvent.pEvent = (TW_MEMREF)&msg;
  351. twEvent.TWMessage = MSG_NULL;
  352.  
  353. TW_UINT16 twRC = TWRC_NOTDSEVENT;
  354.  
  355. //从扫描仪中获取事件
  356. twRC = CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT,(TW_MEMREF)&twEvent);
  357. if(twRC != TWRC_NOTDSEVENT)
  358. {
  359. switch(twEvent.TWMessage)
  360. {
  361. case MSG_XFERREADY:
  362. TransferImage();//传输图像或取消传输
  363. break;
  364. case MSG_CLOSEDSREQ://关闭数据源
  365. CloseDS();
  366. break;
  367. case MSG_CLOSEDSOK:
  368. break;
  369. case MSG_DEVICEEVENT:
  370. break;
  371. default: ;
  372. //qDebug()<<"都不是";
  373. }
  374. }
  375. else
  376. {
  377. qDebug()<<"无法获取事件";
  378. }
  379. return false;
  380. }
  381. else
  382. {
  383. // qDebug()<<"数据源不可用";
  384. }
  385. return false;
  386. }
  387.  
  388. /*
  389. Queries the capability of the Twain Data Source
  390. 查询twain数据源的功能
  391. */
  392. bool CTwain::GetCapability(TW_CAPABILITY& twCap,TW_UINT16 cap,TW_UINT16 conType)
  393. {
  394. if(DSOpen())
  395. {
  396. twCap.Cap = cap;
  397. twCap.ConType = conType;
  398. twCap.hContainer = nullptr;
  399.  
  400. if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_GET,(TW_MEMREF)&twCap))
  401. {
  402. return true;
  403. }
  404. }
  405. return false;
  406. }
  407.  
  408. /*
  409. Queries the capability of the Twain Data Source
  410. 同上 重载函数
  411. */
  412. bool CTwain::GetCapability(TW_UINT16 cap,TW_UINT32& value)
  413. {
  414. TW_CAPABILITY twCap;
  415. if(GetCapability(twCap,cap))
  416. {
  417. pTW_ONEVALUE pVal;
  418. pVal = (pTW_ONEVALUE )GlobalLock(twCap.hContainer);
  419. if(pVal)
  420. {
  421. value = pVal->Item;
  422. GlobalUnlock(pVal);
  423. GlobalFree(twCap.hContainer);
  424. return true;
  425. }
  426. }
  427. return false;
  428. }
  429.  
  430. /*
  431. Sets the capability of the Twain Data Source
  432. 设置twain数据源的功能
  433. */
  434. bool CTwain::SetCapability(TW_UINT16 cap,TW_UINT16 value,bool sign)
  435. {
  436. if(DSOpen())
  437. {
  438. TW_CAPABILITY twCap;
  439. pTW_ONEVALUE pVal;
  440. bool ret_value = false;
  441.  
  442. twCap.Cap = cap;
  443. twCap.ConType = TWON_ONEVALUE;
  444. twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE));
  445.  
  446. if(twCap.hContainer)
  447. {
  448. pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer);
  449. pVal->ItemType = sign ? TWTY_INT16 : TWTY_UINT16;
  450. pVal->Item = (TW_UINT32)value;
  451. GlobalUnlock(twCap.hContainer);
  452. ret_value = SetCapability(twCap);
  453. GlobalFree(twCap.hContainer);
  454. }
  455. return ret_value;
  456. }
  457. return false;
  458. }
  459.  
  460. bool CTwain::SetResolution(TW_UINT16 cap,TW_UINT32 value)
  461. {
  462. if(DSOpen())
  463. {
  464. TW_CAPABILITY twCap;
  465. pTW_ONEVALUE pVal;
  466. BOOL ret_value = FALSE;
  467.  
  468. twCap.Cap = cap;
  469. twCap.ConType = TWON_ONEVALUE;
  470. twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE));
  471.  
  472. if(twCap.hContainer)
  473. {
  474. pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer);
  475. pVal->ItemType = TWTY_FIX32;
  476. pVal->Item = (TW_UINT32)value;
  477. GlobalUnlock(twCap.hContainer);
  478. ret_value = SetCapability(twCap);
  479. GlobalFree(twCap.hContainer);
  480. }
  481. return ret_value;
  482. }
  483. return FALSE;
  484. }
  485.  
  486. /*
  487. Sets the capability of the Twain Data Source
  488. 同上 重载函数
  489. */
  490. bool CTwain::SetCapability(TW_CAPABILITY& cap)
  491. {
  492. if(DSOpen())
  493. {
  494. return CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_SET,(TW_MEMREF)&cap);
  495. }
  496. return false;
  497. }
  498.  
  499. /*
  500. Sets the number of images which can be accpeted by the application at one time
  501. 设置应用程序一次可接收的图像数
  502. */
  503. bool CTwain::SetImageCount(TW_INT16 nCount)
  504. {
  505. if(SetCapability(CAP_XFERCOUNT,(TW_UINT16)nCount,true))
  506. {
  507. m_nImageCount = nCount;
  508. return true;
  509. }
  510. else
  511. {
  512. if(GetRC() == TWRC_CHECKSTATUS)
  513. {
  514. TW_UINT32 count;
  515. if(GetCapability(CAP_XFERCOUNT,count))
  516. {
  517. nCount = (TW_INT16)count;
  518. if(SetCapability(CAP_XFERCOUNT,nCount))
  519. {
  520. m_nImageCount = nCount;
  521. return true;
  522. }
  523. }
  524. }
  525. }
  526. return false;
  527. }
  528.  
  529. /*
  530. Called to enable the Twain Acquire Dialog. This too can be
  531. overridden but is a helluva job .
  532. 调用以启用TWAIN获取对话框。这也可以
  533. 被重写,但这是一个地狱般的工作。
  534.  
  535. 使数据源可用
  536. */
  537. bool CTwain::EnableSource(bool showUI)
  538. {
  539. qDebug()<<"****************开始使数据源可用****************";
  540. if(DSOpen() && !SourceEnabled())//数据源打开了且数据源不可用
  541. {
  542. twUI.ShowUI = false/*showUIfalse*/;//是否打开默认的UI 111111111111111111111111111111111这里不设为false会报错 看看
  543. twUI.hParent = (TW_HANDLE)m_hMessageWnd;//消息窗口作为默认ui的主窗口
  544. //启用数据源
  545. if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_ENABLEDS,(TW_MEMREF)&twUI))
  546. {
  547. m_bSourceEnabled = true;
  548. m_bModalUI = twUI.ModalUI;
  549. qDebug()<<"启用数据源成功 EnableSource";
  550. }
  551. else
  552. {
  553. m_bSourceEnabled = false;
  554. m_bModalUI = true;
  555. qDebug()<<"启用数据源失败 EnableSource";
  556. }
  557. return m_bSourceEnabled;
  558. }
  559. return false;
  560. }
  561.  
  562. /*
  563. Called to acquire images from the source. parameter numImages i the
  564. numberof images that you an handle concurrently
  565.  
  566. 调用以从源获取图像。参数numImages i
  567. 同时处理的图像数
  568. */
  569. bool CTwain::Acquire(int numImages,TW_UINT16 duplex,TW_UINT16 size,TW_UINT16 pixel,TW_UINT16 resolution)
  570. {
  571. qDebug()<<"****************开始启动扫描****************";
  572. if(DSOpen() || OpenSource())//数据源是打开可用的
  573. {
  574. BOOL ret_value = SetCapability(CAP_DUPLEXENABLED,duplex,TRUE);
  575. ret_value = SetCapability(ICAP_SUPPORTEDSIZES,size,TRUE);
  576. ret_value = SetCapability(ICAP_PIXELTYPE,pixel,TRUE);
  577. ret_value = SetResolution(ICAP_XRESOLUTION,resolution);
  578. ret_value = SetResolution(ICAP_YRESOLUTION,resolution);
  579. // lqh - 设置传输模式为文件
  580. ret_value = SetCapability(ICAP_XFERMECH,TWSX_FILE,TRUE);
  581.  
  582. //设置扫描的最大张数
  583. if(SetImageCount(numImages))
  584. {
  585. if(EnableSource())
  586. {
  587. return true;
  588. }
  589. else
  590. {
  591. qDebug()<<"启用扫描源失败";
  592. return false;
  593. }
  594. }
  595. }
  596. return false;
  597. }
  598.  
  599. //禁用数据源
  600. bool CTwain::DisableSource()
  601. {
  602. qDebug()<<"****************开始禁用数据源****************";
  603. if(SourceEnabled())//数据源目前的状态是:可用
  604. {
  605. //禁用数据源
  606. if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,&twUI))
  607. {
  608. m_bSourceEnabled = false;
  609. qDebug()<<"禁用数据源成功";
  610. return true;
  611. }
  612. else
  613. {
  614. qDebug()<<"禁用数据源失败";
  615. return false;
  616. }
  617. }
  618. else
  619. {
  620. qDebug()<<"数据源目前的状态是不可用,不用再次禁用";
  621. }
  622. return false;
  623. }
  624.  
  625. /*
  626. Gets Imageinfo for an image which is about to be transferred.
  627. 获取即将传输的图像的ImageInfo
  628. */
  629. bool CTwain::GetImageInfo(TW_IMAGEINFO& info)
  630. {
  631. qDebug()<<"****************开始获取图片信息****************";
  632. if(SourceEnabled())//如果数据源是可用的
  633. {
  634. bool b = CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGEINFO,MSG_GET,(TW_MEMREF)&info);
  635. if(b == true)
  636. {
  637. qDebug()<<"成功获取即将传输的图片信息";
  638. }
  639. else
  640. {
  641. qDebug()<<"获取即将传输的图片信息失败";
  642. }
  643. return b;
  644. }
  645. return false;
  646. }
  647.  
  648. /*
  649. Trasnfers the image or cancels the transfer depending on the state of the
  650. TWAIN system
  651. 根据图像的状态传输图像或取消传输
  652. */
  653. void CTwain::TransferImage()
  654. {
  655. qDebug()<<"****************根据图像的状态传输图像或取消传输****************";
  656. TW_IMAGEINFO info;//图片信息
  657. bool bContinue = true;
  658. while(bContinue)
  659. {
  660. if(GetImageInfo(info))//获取图片信息
  661. {
  662.  
  663. /* lqh start */
  664. TW_SETUPFILEXFER filexfer;
  665. memset(&filexfer, 0, sizeof(filexfer));
  666. QString file = "C:\\SCANFILES\\scan_" + QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz") +".bmp";
  667. qDebug() << "scan file = " << file ;
  668. filexfer.Format = TWFF_BMP/*TWFF_BMP*/;
  669. strcpy(filexfer.FileName,file.toLatin1().data());
  670.  
  671. CallTwainProc(&m_AppId,&m_Source,DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, (TW_MEMREF)&(filexfer));
  672. /* lqh end */
  673.  
  674. int permission;
  675. permission = ShouldTransfer(info);
  676. qDebug()<<"执行到这";
  677. switch(permission)
  678. {
  679. case TWCPP_CANCELTHIS:
  680. qDebug()<<"执行到这01";
  681. bContinue = EndTransfer();//结束当前的传输
  682. break;
  683.  
  684. case TWCPP_CANCELALL:
  685. qDebug()<<"执行到这02";
  686. CancelTransfer();//中止所有传输
  687. bContinue = false;
  688. break;
  689.  
  690. case TWCPP_DOTRANSFER:
  691. qDebug()<<"执行到这03";
  692. bContinue = GetImage(info);//获取图片
  693. break;
  694. }
  695. }
  696. }
  697. }
  698.  
  699. /*
  700. Ends the current transfer.
  701. Returns true if the more images are pending
  702. 结束当前传输。
  703. 如果有更多图像挂起,则返回true
  704. */
  705. bool CTwain::EndTransfer()
  706. {
  707. qDebug()<<"****************执行结束当前传输****************";
  708. TW_PENDINGXFERS twPend;
  709. if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&twPend))
  710. {
  711. if (twPend.Count==0)
  712. {
  713. DisableSource();
  714. }
  715. return twPend.Count != 0;
  716. }
  717. return false;
  718. }
  719.  
  720. /*
  721. Aborts all transfers
  722. 中止所有传输
  723. */
  724. void CTwain::CancelTransfer()
  725. {
  726. qDebug()<<"****************执行终止所有传输****************";
  727. TW_PENDINGXFERS twPend;
  728. CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&twPend);
  729. }
  730.  
  731. /*
  732. Calls TWAIN to actually get the image
  733. 调用twain以实际获取图像
  734. */
  735. bool CTwain::GetImage(TW_IMAGEINFO& info)
  736. {
  737. qDebug()<<"****************获得图片****************";
  738. HANDLE hBitmap;
  739. // CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,&hBitmap);
  740. //这里失败了
  741. CallTwainProc(&m_AppId,&m_Source,DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, NULL);
  742.  
  743. qDebug()<<"m_returnCode "<<m_returnCode;
  744.  
  745. switch(m_returnCode)
  746. {
  747. case TWRC_XFERDONE:
  748. qDebug()<<"01";
  749. CopyImage(hBitmap,info);//本类的虚函数 子类实现获取图片后的操作
  750. break;
  751. case TWRC_CANCEL:
  752. qDebug()<<"02";
  753. break;
  754. case TWRC_FAILURE:
  755. break;
  756. CancelTransfer();//终止传输
  757. return false;
  758. }
  759. GlobalFree(hBitmap);//释放图片内存
  760. return EndTransfer();
  761. }
  762.  
  763. //获取数据源列表
  764. void CTwain::get_source_list()
  765. {
  766. if(!sourcelist.isEmpty())
  767. {
  768. sourcelist.clear();
  769. }
  770.  
  771. if (CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETFIRST,&m_Source))
  772. {
  773. TW_IDENTITY temp_Source = m_Source;
  774. sourcelist.append(temp_Source);//添加到链表
  775. // qDebug()<<"可用扫描仪:"<<temp_Source.ProductName;
  776. while(CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETNEXT,&m_Source))
  777. {
  778. TW_IDENTITY temp_Source = m_Source;
  779. sourcelist.append(temp_Source);//添加到链表
  780. // qDebug()<<"可用扫描仪:"<<temp_Source.ProductName;
  781. }
  782.  
  783. m_Source = sourcelist.value(0);//第一个可用的扫描源
  784. m_bSourceSelected = TRUE;
  785. }
  786. else
  787. {
  788. qDebug()<<"没有可用的扫描仪";
  789. m_bSourceSelected = FALSE;
  790. }
  791. }

TWAIN.CPP的更多相关文章

  1. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

  2. Json CPP 中文支持与入门示例

    在每一个Json Cpp自带*.cpp文件头加上: #include "stdafx.h" 将Json Cpp对自带的头文件的引用修改为单引号方式,例如json_reader.cp ...

  3. cpp 调用python

    在用cpp调用python时, 出现致命错误: no module named site  ,  原因解释器在搜索路径下没有找到python库.可以在调用Py_Initialize前,调用 Py_Se ...

  4. nginx+fastcgi+c/cpp

    参考:http://github.tiankonguse.com/blog/2015/01/19/cgi-nginx-three/ 跟着做了一遍,然后根据记忆写的,不清楚有没错漏步骤,希望多多评论多多 ...

  5. APM程序分析-ArduCopter.cpp

    该文件是APM的主文件. #define SCHED_TASK(func, rate_hz, max_time_micros) SCHED_TASK_CLASS(Copter, &copter ...

  6. APM程序分析-AC_WPNav.cpp

    APM程序分析 主程序在ArduCopter.cpp的loop()函数. /// advance_wp_target_along_track - move target location along ...

  7. Dev Cpp 输出中文字符问题

    最近 c++ 上机作业,vc++6.0 挂了没法用,只好用 Dev Cpp 先顶替一下,然而在遇到输出中文字符的时候出现了乱码的情况,但这种情况又非常诡异.于是简单了解了一下写成此博客. [写在前面] ...

  8. 扫描仪API接入大全:Twain, WIA 或 两者不具有.[换个思路 春暖花开]

    最近做和扫描仪接入的扫描应用程序,深深感觉到了来自底层设备和WINDOWS协议的恶意.软件专业,对计算机深层次通知机制和协议,以及与之相连接的机器的接入协议和一些参数,当时并木有认真学习和了解,前一阵 ...

  9. 【安卓】aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creating directories: Invalid argument

    这几天在使用.aidl文件的时候eclipse的控制台总是爆出如下提示: aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creatin ...

随机推荐

  1. GO语言复合类型02---数组

    package main import "fmt" /* 固定长度.固定类型的数据容器 */ /*数组的声明*/ func main031() { //var array [5]i ...

  2. Python+Selenium - Alert弹框

    上面三种弹窗可以在浏览器的控制台做出效果,如下图 上面三种弹窗可以用alert方法处理 示例: #出现弹窗的操作xxxx# 切换al = driver.switch_to.alert# print(a ...

  3. Python+Selenium+Appium+API学习使用过的命令

    adb devices 查看连接电脑的手机设备 weditor 启动uiautomatorviewer2元素定位工具 以下2个命令作用一样 adb shell dumpsys activity | f ...

  4. springboot项目添加swagger2

    1.pom中添加swagger依赖 <!-- swagger-ui --> <dependency> <groupId>io.springfox</group ...

  5. 适用于AMD ROC GPU的Numba概述

    适用于AMD ROC GPU的Numba概述 Numba通过按照HSA执行模型将Python代码的受限子集直接编译到HSA内核和设备功能中,从而支持AMD ROC GPU编程.用Numba编写的内核似 ...

  6. TensorRT 7.2.1 开发概要(上)

    TensorRT 7.2.1 开发概要(上) Abstract 这个TysRR7.2.1开发者指南演示了如何使用C++和Python API来实现最常用的深层学习层.它展示了如何使用深度学习框架构建现 ...

  7. 如何查看app启动的activity

    adb 查看 使用adb shell 进入安卓的linux系统 拿QQ做例子: monkey -p com.tencent.mobileqq -v -v 1 #启动一次 启动页面为:com.tence ...

  8. .Net RabbitMQ实战指南——HTTP API接口调用

    RabbitMQ Management插件还提供了基于RESTful风格的HTTP API接口来方便调用.一共涉及4种HTTP方法:GET.PUT.DELETE和POST.GET方法一般用来获取如集群 ...

  9. docker基本底层原理

    docker是怎么工作的 Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket客户端进行访问 DockerServer接收到DockerClie ...

  10. Java-Lambda相关使用介绍

    频繁使用的语句   Lambda又涉及到comparator和comparable区别(Comparable是实现comparable接口,实现后可以使用Collections.sort或Arrays ...