code_app/modules/twain_user/HGTwainImpl.cpp

1085 lines
28 KiB
C++

#include "HGTwainImpl.hpp"
#include "../base/HGInc.h"
#include "../base/HGInfo.h"
#include "../base/HGUtility.h"
#include "app_cfg.h"
std::map<HWND, HGTwainDSMImpl*> HGTwainDSMImpl::m_mapWnd;
HGTwainDSMImpl::HGTwainDSMImpl()
{
m_hDll = NULL;
m_pDSMProc = NULL;
m_AppId.Id = 0; // Initialize to 0 (Source Manager will assign real value)
m_AppId.Version.MajorNum = 3; //Your app's version number
m_AppId.Version.MinorNum = 8;
m_AppId.Version.Language = TWLG_USA;
m_AppId.Version.Country = TWCY_USA;
strcpy(m_AppId.Version.Info, "3.8");
m_AppId.ProtocolMajor = TWON_PROTOCOLMAJOR;
m_AppId.ProtocolMinor = TWON_PROTOCOLMINOR;
m_AppId.SupportedGroups = DG_IMAGE | DG_CONTROL;
strcpy(m_AppId.Manufacturer, "MICSS");
strcpy(m_AppId.ProductFamily, "Generic");
strcpy(m_AppId.ProductName, "MyTwain");
m_hWnd = NULL;
m_oldWndProc = NULL;
m_vds.clear();
}
HGTwainDSMImpl::~HGTwainDSMImpl()
{
}
HGResult HGTwainDSMImpl::Create(HWND hwnd)
{
assert(NULL == m_oldWndProc);
if (NULL == hwnd)
{
return HGBASE_ERR_INVALIDARG;
}
assert(NULL == m_hDll);
#ifdef _WIN64
HGBase_CreateDll("TWAINDSM.dll", &m_hDll);
#else
HGBase_CreateDll("twain_32.dll", &m_hDll);
#endif
if (NULL == m_hDll)
{
return HGBASE_ERR_FAIL;
}
assert(NULL == m_pDSMProc);
HGBase_GetDllProcAddress(m_hDll, MAKEINTRESOURCEA(1), (HGPointer*)&m_pDSMProc);
if (NULL == m_pDSMProc)
{
HGBase_DestroyDll(m_hDll);
m_hDll = NULL;
return HGBASE_ERR_FAIL;
}
USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, (TW_MEMREF)&hwnd);
if (TWRC_SUCCESS != ret)
{
m_pDSMProc = NULL;
HGBase_DestroyDll(m_hDll);
m_hDll = NULL;
return HGTWAIN_ERR_FAIL;
}
m_hWnd = hwnd;
m_mapWnd[m_hWnd] = this;
m_oldWndProc = (WNDPROC)SetWindowLongPtrW(m_hWnd, GWLP_WNDPROC, (LONG_PTR)NewWndProc);
TW_IDENTITY ds;
if (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &ds))
{
if (!filterTwainSource(ds.ProductName, ds.Version.MajorNum))
m_vds.push_back(ds);
while (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &ds))
{
if (!filterTwainSource(ds.ProductName, ds.Version.MajorNum))
m_vds.push_back(ds);
}
}
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::Destroy()
{
assert(NULL != m_oldWndProc);
if (!m_listDSImpl.empty())
{
return HGBASE_ERR_FAIL;
}
m_vds.clear();
m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, (TW_MEMREF)&m_hWnd);
SetWindowLongPtrW(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_oldWndProc);
m_oldWndProc = NULL;
std::map<HWND, HGTwainDSMImpl*>::iterator iter;
for (iter = m_mapWnd.begin(); iter != m_mapWnd.end(); ++iter)
{
if (iter->first == m_hWnd)
{
m_mapWnd.erase(iter);
break;
}
}
m_hWnd = NULL;
m_pDSMProc = NULL;
HGBase_DestroyDll(m_hDll);
m_hDll = NULL;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::GetDSCount(HGUInt* count)
{
if (NULL == count)
{
return HGBASE_ERR_INVALIDARG;
}
*count = m_vds.size();
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::GetDSName(HGUInt index, HGChar* name, HGUInt maxLen)
{
if (NULL == name || 0 == maxLen)
{
return HGBASE_ERR_INVALIDARG;
}
if (index >= (HGUInt)m_vds.size())
return HGBASE_ERR_INVALIDARG;
if (maxLen < strlen(m_vds[index].ProductName) + 1)
return HGBASE_ERR_FAIL;
strcpy(name, m_vds[index].ProductName);
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::CreateDS(HGUInt index, class HGTwainDSImpl** dsImpl)
{
if (NULL == dsImpl)
{
return HGBASE_ERR_INVALIDARG;
}
if (index >= (HGUInt)m_vds.size())
return HGBASE_ERR_INVALIDARG;
class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this, &m_vds[index]);
std::string DSName = m_vds[index].ProductName;
saveCfgValue("twain", "source", DSName);
m_listDSImpl.push_back(newDSImpl);
*dsImpl = newDSImpl;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::CreateDefaultDS(class HGTwainDSImpl** dsImpl)
{
if (NULL == dsImpl)
{
return HGBASE_ERR_INVALIDARG;
}
if (m_vds.empty())
{
return HGBASE_ERR_FAIL;
}
std::string sourceName = getCfgValue("twain", "source", std::string(""));
int index = -1;
for (int i = 0; i < m_vds.size(); ++i)
{
if (strcmp(m_vds[i].ProductName, sourceName.c_str()) == 0)
{
index = i;
break;
}
}
if (-1 == index)
{
index = 0;
}
class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this, &m_vds[index]);
std::string DSName = m_vds[index].ProductName;
saveCfgValue("twain", "source", DSName);
m_listDSImpl.push_back(newDSImpl);
*dsImpl = newDSImpl;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::CreateSelectedDS(class HGTwainDSImpl** dsImpl)
{
if (NULL == dsImpl)
{
return HGBASE_ERR_INVALIDARG;
}
TW_IDENTITY selectDS;
if (TWRC_SUCCESS != m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &selectDS))
{
return HGTWAIN_ERR_CANCELUI;
}
class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this, &selectDS);
std::string DSName = selectDS.ProductName;
saveCfgValue("twain", "source", DSName);
m_listDSImpl.push_back(newDSImpl);
*dsImpl = newDSImpl;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSMImpl::CreateSelectedDSEx(class HGTwainDSImpl** dsImpl)
{
if (NULL == dsImpl)
{
return HGBASE_ERR_INVALIDARG;
}
std::string sourceName = getCfgValue("twain", "source", std::string(""));
TW_IDENTITY selectDS;
memset(&selectDS, 0, sizeof(TW_IDENTITY));
if (-2 == show_twain_srclist_ui(&m_vds[0], m_vds.size(), sourceName.c_str(), m_hWnd, &selectDS))
{
return HGBASE_ERR_NOTSUPPORT;
}
if (0 == selectDS.Id)
{
return HGTWAIN_ERR_CANCELUI;
}
class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this, &selectDS);
std::string DSName = selectDS.ProductName;
saveCfgValue("twain", "source", DSName);
m_listDSImpl.push_back(newDSImpl);
*dsImpl = newDSImpl;
return HGBASE_ERR_OK;
}
void HGTwainDSMImpl::RemoveDS(class HGTwainDSImpl* dsImpl)
{
std::vector<class HGTwainDSImpl*>::iterator iter;
for (iter = m_listDSImpl.begin(); iter != m_listDSImpl.end(); ++iter)
{
if (*iter == dsImpl)
{
m_listDSImpl.erase(iter);
delete dsImpl;
break;
}
}
}
LRESULT CALLBACK HGTwainDSMImpl::NewWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HGTwainDSMImpl* p = m_mapWnd[hWnd];
assert(NULL != p);
MSG msg2 = { 0 };
msg2.hwnd = hWnd;
msg2.message = msg;
msg2.wParam = wParam;
msg2.lParam = lParam;
for (int i = 0; i < (int)p->m_listDSImpl.size(); ++i)
{
TW_EVENT twEvent;
twEvent.pEvent = (TW_MEMREF)&msg2;
twEvent.TWMessage = MSG_NULL;
USHORT ret = p->m_pDSMProc(&p->m_AppId, &p->m_listDSImpl[i]->m_iden, DG_CONTROL, DAT_EVENT,
MSG_PROCESSEVENT, (TW_MEMREF)&twEvent);
if (TWRC_DSEVENT == ret)
{
if (MSG_XFERREADY == twEvent.TWMessage)
{
HGBase_SetEvent(p->m_listDSImpl[i]->m_event);
}
else if (MSG_CLOSEDSREQ == twEvent.TWMessage)
{
if (p->m_listDSImpl[i]->m_eventFunc)
{
p->m_listDSImpl[i]->m_eventFunc((HGTwainDS)p->m_listDSImpl[i],
HGTWAIN_EVENT_TYPE_CLOSEDSREQ, p->m_listDSImpl[i]->m_eventParam);
}
}
}
}
return CallWindowProcW(p->m_oldWndProc, hWnd, msg, wParam, lParam);
}
bool HGTwainDSMImpl::filterTwainSource(const char* sourceName, int majorNum)
{
#if !defined(OEM_HANWANG) && !defined(OEM_LISICHENG) && !defined(OEM_CANGTIAN) && !defined(OEM_ZHONGJING) && !defined(OEM_ZIGUANG) && !defined(OEM_NEUTRAL) && !defined(OEM_DELI)
std::string oemIden = "HUAGOSCAN";
#elif defined(OEM_HANWANG)
std::string oemIden = "Hanvon";
#elif defined(OEM_LISICHENG)
std::string oemIden = "LANXUMSCAN";
#elif defined(OEM_CANGTIAN)
std::string oemIden = "CUMTENN";
#elif defined(OEM_ZHONGJING)
std::string oemIden = "Microtek";
#elif defined(OEM_ZIGUANG)
std::string oemIden = "Uniscan";
#elif defined(OEM_NEUTRAL)
std::string oemIden = "NeuScan";
#elif defined(OEM_DELI)
std::string oemIden = "DELI SCAN";
#endif
if (sourceName != strstr(sourceName, oemIden.c_str()) || 4 != majorNum)
{
return true;
}
return false;
}
HGTwainDSImpl::HGTwainDSImpl(HGTwainDSMImpl* dsmImpl, TW_IDENTITY* iden)
{
m_dsmImpl = dsmImpl;
assert(NULL != iden);
memcpy(&m_iden, iden, sizeof(TW_IDENTITY));
m_open = HGFALSE;
m_singleScan = HGFALSE;
m_oldXferCount = -1;
m_showUI = HGFALSE;
m_parent = NULL;
m_eventFunc = NULL;
m_eventParam = NULL;
m_imageFunc = NULL;
m_imageParam = NULL;
m_event = NULL;
m_stopThread = HGFALSE;
m_thread = NULL;
}
HGTwainDSImpl::~HGTwainDSImpl()
{
}
HGResult HGTwainDSImpl::Destroy()
{
Close();
m_dsmImpl->RemoveDS(this);
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::Open()
{
if (m_open)
{
return HGTWAIN_ERR_FAIL;
}
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &m_iden);
if (TWRC_SUCCESS != ret)
{
return HGTWAIN_ERR_FAIL;
}
HGBase_CreateEvent(HGFALSE, HGFALSE, &m_event);
m_stopThread = HGFALSE;
HGBase_OpenThread(ThreadFunc, this, &m_thread);
m_open = HGTRUE;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::Close()
{
if (!m_open)
{
return HGTWAIN_ERR_FAIL;
}
Disable();
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, (TW_MEMREF)&m_iden);
m_stopThread = HGTRUE;
HGBase_SetEvent(m_event);
HGBase_CloseThread(m_thread);
m_thread = NULL;
HGBase_DestroyEvent(m_event);
m_event = NULL;
m_open = HGFALSE;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::GetName(HGChar* name, HGUInt maxLen)
{
if (NULL == name || 0 == maxLen)
{
return HGBASE_ERR_INVALIDARG;
}
if (maxLen < strlen(m_iden.ProductName) + 1)
return HGBASE_ERR_FAIL;
strcpy(name, m_iden.ProductName);
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::GetDeviceName(HGChar* name, HGUInt maxLen)
{
if (NULL == name || 0 == maxLen)
{
return HGBASE_ERR_INVALIDARG;
}
return GetCapStr255(0x8854, name, maxLen);
}
HGResult HGTwainDSImpl::GetDeviceCustomInfo(HGTwainDeviceCustomInfo *info)
{
if (NULL == info)
{
return HGBASE_ERR_INVALIDARG;
}
memset(info, 0, sizeof(HGTwainDeviceCustomInfo));
GetCapInt(0x8852, &info->vid);
GetCapInt(0x8853, &info->pid);
GetCapStr255(0x8856, info->sn, sizeof(info->sn));
GetCapStr255(0x8855, info->type, sizeof(info->type));
GetCapStr255(0x8857, info->fwVer, sizeof(info->fwVer));
GetCapStr255(0x8858, info->ip, sizeof(info->ip));
GetCapStr255(0x8859, info->mac, sizeof(info->mac));
GetCapStr255(0x884A, info->driverVer, sizeof(info->driverVer));
GetCapStr255(0x884B, info->vendor, sizeof(info->vendor));
GetCapStr255(0x884C, info->copyright, sizeof(info->copyright));
GetCapStr255(0x884D, info->comUrl, sizeof(info->comUrl));
GetCapStr255(0x884E, info->comTel, sizeof(info->comTel));
GetCapStr255(0x884F, info->comAddr, sizeof(info->comAddr));
GetCapStr255(0x8850, info->comGps, sizeof(info->comGps));
GetCapInt(0x9902, &info->rollerCount);
GetCapInt(0x8849, &info->totalCount);
return HGBASE_ERR_OK;
}
#pragma pack(push)
#pragma pack(1)
struct LoginType
{
TW_UINT16 ItemType;
TW_UINT32 NumItems;
TW_STR32 Value[2];
};
#pragma pack(pop)
HGResult HGTwainDSImpl::Login(const HGChar *user, const HGChar *pwd)
{
if (NULL == user || strlen(user) >= sizeof(TW_STR32)
|| NULL == pwd || strlen(pwd) >= sizeof(TW_STR32))
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)0x9900;
twCap.ConType = TWON_ARRAY;
twCap.hContainer = GlobalAlloc(GHND, sizeof(LoginType));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
LoginType *pVal = (LoginType *)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR32;
pVal->NumItems = 2;
strcpy(pVal->Value[0], user);
strcpy(pVal->Value[1], pwd);
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::Logout()
{
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)0x9901;
twCap.ConType = TWON_ARRAY;
twCap.hContainer = GlobalAlloc(GHND, sizeof(LoginType));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
LoginType *pVal = (LoginType *)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR32;
pVal->NumItems = 2;
memset(pVal->Value[0], 0, sizeof(pVal->Value[0]));
memset(pVal->Value[1], 0, sizeof(pVal->Value[1]));
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::ClearRollerCount()
{
return ResetCapInt(0x9902, TWTY_INT32);
}
#pragma pack(push)
#pragma pack(1)
struct CapStr255Type
{
TW_UINT16 ItemType;
TW_STR255 Value;
};
#pragma pack(pop)
HGResult HGTwainDSImpl::GetDriverLog(const HGChar *fileName)
{
if (NULL == fileName || strlen(fileName) >= sizeof(TW_STR255))
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)0x9903;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND, sizeof(CapStr255Type));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
CapStr255Type* pVal = (CapStr255Type*)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR255;
strcpy(pVal->Value, fileName);
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::ClearDriverLog()
{
return ResetCapStr255(0x9903);
}
HGResult HGTwainDSImpl::GetDeviceLog(const HGChar *fileName)
{
if (NULL == fileName || strlen(fileName) >= sizeof(TW_STR255))
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)0x9904;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND, sizeof(CapStr255Type));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
CapStr255Type* pVal = (CapStr255Type*)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR255;
strcpy(pVal->Value, fileName);
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::ClearDeviceLog()
{
return ResetCapStr255(0x9904);
}
HGResult HGTwainDSImpl::EnableUIOnly(HWND parent, HGDSEventFunc eventFunc, HGPointer eventParam)
{
TW_USERINTERFACE twUI;
twUI.ShowUI = (TW_BOOL)HGTRUE;
twUI.hParent = (TW_HANDLE)parent;
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDSUIONLY, (TW_MEMREF)&twUI);
if (TWRC_SUCCESS != ret)
{
TW_STATUS status;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&status);
if (status.ConditionCode == TWCC_CHECKDEVICEONLINE)
return HGTWAIN_ERR_DEVICEOFFLINE;
return HGTWAIN_ERR_FAIL;
}
m_showUI = HGTRUE;
m_parent = parent;
m_eventFunc = eventFunc;
m_eventParam = eventParam;
m_imageFunc = NULL;
m_imageParam = NULL;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::Enable(HGBool showUI, HWND parent, HGDSEventFunc eventFunc, HGPointer eventParam,
HGDSImageFunc imageFunc, HGPointer imageParam)
{
TW_USERINTERFACE twUI;
twUI.ShowUI = (TW_BOOL)showUI;
twUI.hParent = (TW_HANDLE)parent;
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, (TW_MEMREF)&twUI);
if (TWRC_SUCCESS != ret)
{
TW_STATUS status;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&status);
if (status.ConditionCode == TWCC_CHECKDEVICEONLINE)
return HGTWAIN_ERR_DEVICEOFFLINE;
return HGTWAIN_ERR_FAIL;
}
m_showUI = showUI;
m_parent = parent;
m_eventFunc = eventFunc;
m_eventParam = eventParam;
m_imageFunc = imageFunc;
m_imageParam = imageParam;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::EnableWithSingleScan(HWND parent, HGDSEventFunc eventFunc, HGPointer eventParam,
HGDSImageFunc imageFunc, HGPointer imageParam)
{
HGInt oldXferCount = -1;
HGResult ret = GetCapInt(CAP_XFERCOUNT, &oldXferCount);
if (HGBASE_ERR_OK != ret)
{
TW_STATUS status;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&status);
if (status.ConditionCode == TWCC_CHECKDEVICEONLINE)
return HGTWAIN_ERR_DEVICEOFFLINE;
return ret;
}
ret = SetCapInt(CAP_XFERCOUNT, TWTY_INT16, 1);
if (HGBASE_ERR_OK != ret)
{
TW_STATUS status;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&status);
if (status.ConditionCode == TWCC_CHECKDEVICEONLINE)
return HGTWAIN_ERR_DEVICEOFFLINE;
return ret;
}
TW_USERINTERFACE twUI;
twUI.ShowUI = (TW_BOOL)HGFALSE;
twUI.hParent = (TW_HANDLE)parent;
if (TWRC_SUCCESS != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, (TW_MEMREF)&twUI))
{
SetCapInt(CAP_XFERCOUNT, TWTY_INT16, oldXferCount);
TW_STATUS status;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&status);
if (status.ConditionCode == TWCC_CHECKDEVICEONLINE)
return HGTWAIN_ERR_DEVICEOFFLINE;
return HGTWAIN_ERR_FAIL;
}
m_singleScan = HGTRUE;
m_oldXferCount = oldXferCount;
m_showUI = HGFALSE;
m_parent = parent;
m_eventFunc = eventFunc;
m_eventParam = eventParam;
m_imageFunc = imageFunc;
m_imageParam = imageParam;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::Disable()
{
TW_USERINTERFACE twUI;
twUI.ShowUI = (TW_BOOL)m_showUI;
twUI.hParent = (TW_HANDLE)m_parent;
m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &twUI);
if (m_singleScan)
{
SetCapInt(CAP_XFERCOUNT, TWTY_INT16, m_oldXferCount);
}
m_singleScan = FALSE;
m_oldXferCount = -1;
m_showUI = HGFALSE;
m_parent = NULL;
m_eventFunc = NULL;
m_eventParam = NULL;
m_imageFunc = NULL;
m_imageParam = NULL;
return HGBASE_ERR_OK;
}
#pragma pack(push)
#pragma pack(1)
struct CapInt8Type
{
TW_UINT16 ItemType;
TW_INT8 Value;
};
struct CapInt16Type
{
TW_UINT16 ItemType;
TW_INT16 Value;
};
struct CapInt32Type
{
TW_UINT16 ItemType;
TW_INT32 Value;
};
#pragma pack(pop)
HGResult HGTwainDSImpl::SetCapInt(HGUInt cap, TW_UINT16 itemType, HGInt value)
{
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
DWORD size = sizeof(CapInt32Type);
if (itemType == TWTY_INT8)
size = sizeof(CapInt8Type);
else if (itemType == TWTY_INT16)
size = sizeof(CapInt16Type);
twCap.hContainer = GlobalAlloc(GHND, size);
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
void* pVal = GlobalLock(twCap.hContainer);
assert(NULL != pVal);
if (itemType == TWTY_INT8)
{
((CapInt8Type*)pVal)->ItemType = TWTY_INT8;
((CapInt8Type*)pVal)->Value = (TW_INT8)value;
}
else if (itemType == TWTY_INT16)
{
((CapInt16Type*)pVal)->ItemType = TWTY_INT16;
((CapInt16Type*)pVal)->Value = (TW_INT16)value;
}
else
{
((CapInt32Type*)pVal)->ItemType = TWTY_INT32;
((CapInt32Type*)pVal)->Value = (TW_INT32)value;
}
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::ResetCapInt(HGUInt cap, TW_UINT16 itemType)
{
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
DWORD size = sizeof(CapInt32Type);
if (itemType == TWTY_INT8)
size = sizeof(CapInt8Type);
else if (itemType == TWTY_INT16)
size = sizeof(CapInt16Type);
twCap.hContainer = GlobalAlloc(GHND, size);
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
void* pVal = GlobalLock(twCap.hContainer);
assert(NULL != pVal);
if (itemType == TWTY_INT8)
{
((CapInt8Type*)pVal)->ItemType = TWTY_INT8;
((CapInt8Type*)pVal)->Value = 0;
}
else if (itemType == TWTY_INT16)
{
((CapInt16Type*)pVal)->ItemType = TWTY_INT16;
((CapInt16Type*)pVal)->Value = 0;
}
else
{
((CapInt32Type*)pVal)->ItemType = TWTY_INT32;
((CapInt32Type*)pVal)->Value = 0;
}
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_RESET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::GetCapInt(HGUInt cap, HGInt* value)
{
if (NULL == value)
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = NULL;
if (TWRC_SUCCESS != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap))
{
return HGTWAIN_ERR_FAIL;
}
HGResult ret = HGBASE_ERR_FAIL;
assert(NULL != twCap.hContainer);
void* pVal = GlobalLock(twCap.hContainer);
if (NULL != pVal)
{
TW_UINT16 ItemType = *(TW_UINT16*)pVal;
if (ItemType == TWTY_INT8)
{
*value = ((CapInt8Type*)pVal)->Value;
ret = HGBASE_ERR_OK;
}
else if (ItemType == TWTY_INT16)
{
*value = ((CapInt16Type*)pVal)->Value;
ret = HGBASE_ERR_OK;
}
else if (ItemType == TWTY_INT32)
{
*value = ((CapInt32Type*)pVal)->Value;
ret = HGBASE_ERR_OK;
}
GlobalUnlock(twCap.hContainer);
}
GlobalFree(twCap.hContainer);
return ret;
}
HGResult HGTwainDSImpl::SetCapStr255(HGUInt cap, const HGChar *value)
{
if (NULL == value || strlen(value) >= sizeof(TW_STR255))
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND, sizeof(CapStr255Type));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
CapStr255Type* pVal = (CapStr255Type*)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR255;
strcpy(pVal->Value, value);
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::ResetCapStr255(HGUInt cap)
{
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND, sizeof(CapStr255Type));
if (NULL == twCap.hContainer)
{
return HGBASE_ERR_FAIL;
}
CapStr255Type* pVal = (CapStr255Type*)GlobalLock(twCap.hContainer);
assert(NULL != pVal);
pVal->ItemType = TWTY_STR255;
memset(pVal->Value, 0, sizeof(pVal->Value));
GlobalUnlock(twCap.hContainer);
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_RESET, &twCap);
GlobalFree(twCap.hContainer);
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
}
HGResult HGTwainDSImpl::GetCapStr255(HGUInt cap, HGChar *value, HGUInt maxLen)
{
if (NULL == value || 0 == maxLen)
{
return HGBASE_ERR_INVALIDARG;
}
TW_CAPABILITY twCap;
twCap.Cap = (TW_UINT16)cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = NULL;
if (TWRC_SUCCESS != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap))
{
return HGTWAIN_ERR_FAIL;
}
HGResult ret = HGBASE_ERR_FAIL;
assert(NULL != twCap.hContainer);
CapStr255Type* pVal = (CapStr255Type*)GlobalLock(twCap.hContainer);
if (NULL != pVal && pVal->ItemType == TWTY_STR255)
{
if (maxLen > strlen(pVal->Value))
{
strcpy(value, pVal->Value);
ret = HGBASE_ERR_OK;
}
else
{
ret = HGBASE_ERR_INVALIDARG;
}
}
GlobalUnlock(twCap.hContainer);
GlobalFree(twCap.hContainer);
return ret;
}
HGResult HGTwainDSImpl::ImageNativeXfer(HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
TW_IMAGEINFO info;
if (TWRC_SUCCESS != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info))
{
return HGTWAIN_ERR_FAIL;
}
#ifdef _WIN64
HANDLE hMem = NULL;
if (TWRC_XFERDONE != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hMem))
{
return HGTWAIN_ERR_FAIL;
}
HGStream stream = NULL;
HGResult ret = HGBase_CreateDIBStream(hMem, &stream);
GlobalFree(hMem);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
ret = HGBase_CreateImageFromStream(stream, NULL, type, origin, image);
HGBase_DestroyStream(stream);
#else
HGChar tmpFile[260];
HGBase_GetTmpFileName("bmp", tmpFile, 260);
TW_SETUPFILEXFER xfer = {0};
strcpy(xfer.FileName, tmpFile);
xfer.Format = TWFF_BMP;
if (TWRC_SUCCESS != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, &xfer))
{
return HGTWAIN_ERR_FAIL;
}
if (TWRC_XFERDONE != m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, NULL))
{
return HGTWAIN_ERR_FAIL;
}
HGResult ret = HGBase_CreateImageFromFile(tmpFile, NULL, type, origin, image);
HGBase_DeleteFile(tmpFile);
#endif
return ret;
}
HGResult HGTwainDSImpl::EndXfer(HGUInt* count)
{
if (NULL == count)
{
return HGBASE_ERR_INVALIDARG;
}
TW_PENDINGXFERS twPend;
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&twPend);
if (TWRC_SUCCESS != ret)
{
return HGTWAIN_ERR_FAIL;
}
*count = twPend.Count;
return HGBASE_ERR_OK;
}
HGResult HGTwainDSImpl::Reset()
{
TW_PENDINGXFERS twPend;
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, (TW_MEMREF)&twPend);
if (TWRC_SUCCESS != ret)
{
return HGTWAIN_ERR_FAIL;
}
return HGBASE_ERR_OK;
}
void HGAPI HGTwainDSImpl::ThreadFunc(HGThread thread, HGPointer param)
{
(void)thread;
HGTwainDSImpl *p = (HGTwainDSImpl *)param;
while (!p->m_stopThread)
{
HGBase_WaitEvent(p->m_event);
if (NULL != p->m_eventFunc)
p->m_eventFunc((HGTwainDS)p, HGTWAIN_EVENT_TYPE_WORKING, p->m_eventParam);
while (1)
{
HGImage image = NULL;
p->ImageNativeXfer(0, 0, &image);
if (NULL != image)
{
if (NULL != p->m_imageFunc)
{
HGUInt imgRet = p->m_imageFunc((HGTwainDS)p, image, HGTWAIN_IMAGE_TYPE_NORMAL, p->m_imageParam);
assert(HGBASE_ERR_OK == imgRet);
}
HGBase_DestroyImage(image);
}
HGUInt count = 0;
p->EndXfer(&count);
if (0 == count)
{
break;
}
}
if (NULL != p->m_eventFunc)
p->m_eventFunc((HGTwainDS)p, HGTWAIN_EVENT_TYPE_SCANFINISHED, p->m_eventParam);
}
}