1284 lines
34 KiB
C++
1284 lines
34 KiB
C++
#include "HGTwainImpl.hpp"
|
|
#include "../base/HGInc.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(""));
|
|
|
|
if (m_vds.empty())
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
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) && !defined(OEM_MEISONGDA) && !defined(OEM_GUANGDIANTONG)
|
|
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";
|
|
#elif defined(OEM_MEISONGDA)
|
|
std::string oemIden = "MAXSOUND";
|
|
#elif defined(OEM_GUANGDIANTONG)
|
|
std::string oemIden = "TOEC";
|
|
#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;
|
|
}
|
|
|
|
HGCapValue value;
|
|
HGResult ret = GetCapbility(0x8854, &value);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
if (value.type == HGCAPVALUE_TYPE_STR32)
|
|
strcpy(name, value.valueStr32);
|
|
else if (value.type == HGCAPVALUE_TYPE_STR64)
|
|
strcpy(name, value.valueStr64);
|
|
else if (value.type == HGCAPVALUE_TYPE_STR128)
|
|
strcpy(name, value.valueStr128);
|
|
else if (value.type == HGCAPVALUE_TYPE_STR255)
|
|
strcpy(name, value.valueStr255);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HGResult HGTwainDSImpl::GetDeviceCustomInfo(HGTwainDeviceCustomInfo *info)
|
|
{
|
|
if (NULL == info)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
memset(info, 0, sizeof(HGTwainDeviceCustomInfo));
|
|
|
|
HGCapValue value;
|
|
|
|
GetCapbility(0x8852, &value);
|
|
info->vid = value.valueInt;
|
|
GetCapbility(0x8853, &value);
|
|
info->pid = value.valueInt;
|
|
|
|
GetCapbility(0x8856, &value);
|
|
strcpy(info->sn, value.valueStr255);
|
|
GetCapbility(0x8855, &value);
|
|
strcpy(info->type, value.valueStr255);
|
|
GetCapbility(0x8857, &value);
|
|
strcpy(info->fwVer, value.valueStr255);
|
|
GetCapbility(0x8858, &value);
|
|
strcpy(info->ip, value.valueStr255);
|
|
GetCapbility(0x8859, &value);
|
|
strcpy(info->mac, value.valueStr255);
|
|
GetCapbility(0x884A, &value);
|
|
strcpy(info->driverVer, value.valueStr255);
|
|
GetCapbility(0x884B, &value);
|
|
strcpy(info->vendor, value.valueStr255);
|
|
GetCapbility(0x884C, &value);
|
|
strcpy(info->copyright, value.valueStr255);
|
|
GetCapbility(0x884D, &value);
|
|
strcpy(info->comUrl, value.valueStr255);
|
|
GetCapbility(0x884E, &value);
|
|
strcpy(info->comTel, value.valueStr255);
|
|
GetCapbility(0x884F, &value);
|
|
strcpy(info->comAddr, value.valueStr255);
|
|
GetCapbility(0x8850, &value);
|
|
strcpy(info->comGps, value.valueStr255);
|
|
|
|
GetCapbility(0x9902, &value);
|
|
info->rollerCount = value.valueInt;
|
|
GetCapbility(0x8849, &value);
|
|
info->totalCount = value.valueInt;
|
|
|
|
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()
|
|
{
|
|
HGCapValue value;
|
|
value.type = HGCAPVALUE_TYPE_INT;
|
|
value.valueInt = 0;
|
|
|
|
return SetCapbility(0x9902, &value, true);
|
|
}
|
|
|
|
#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;
|
|
};
|
|
struct CapUInt8Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_UINT8 Value;
|
|
};
|
|
struct CapUInt16Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_UINT16 Value;
|
|
};
|
|
struct CapUInt32Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_UINT32 Value;
|
|
};
|
|
struct CapBoolType
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_BOOL Value;
|
|
};
|
|
struct CapFix32Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_FIX32 Value;
|
|
};
|
|
struct CapStr32Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_STR32 Value;
|
|
};
|
|
struct CapStr64Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_STR64 Value;
|
|
};
|
|
struct CapStr128Type
|
|
{
|
|
TW_UINT16 ItemType;
|
|
TW_STR128 Value;
|
|
};
|
|
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()
|
|
{
|
|
HGCapValue value;
|
|
value.type = HGCAPVALUE_TYPE_STR255;
|
|
return SetCapbility(0x9903, &value, true);
|
|
}
|
|
|
|
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()
|
|
{
|
|
|
|
HGCapValue value;
|
|
value.type = HGCAPVALUE_TYPE_STR255;
|
|
return SetCapbility(0x9904, &value, true);
|
|
}
|
|
|
|
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)
|
|
{
|
|
HGCapValue value;
|
|
HGResult ret = GetCapbility(CAP_XFERCOUNT, &value);
|
|
HGInt oldXferCount = value.valueInt;
|
|
|
|
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;
|
|
}
|
|
|
|
HGCapValue value2;
|
|
value2.type = HGCAPVALUE_TYPE_SHORT;
|
|
value2.valueInt = 1;
|
|
ret = SetCapbility(CAP_XFERCOUNT, &value2, false);
|
|
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))
|
|
{
|
|
HGCapValue value3;
|
|
value3.type = HGCAPVALUE_TYPE_SHORT;
|
|
value3.valueInt = oldXferCount;
|
|
SetCapbility(CAP_XFERCOUNT, &value3, false);
|
|
|
|
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)
|
|
{
|
|
HGCapValue value;
|
|
value.type = HGCAPVALUE_TYPE_SHORT;
|
|
value.valueInt = m_oldXferCount;
|
|
SetCapbility(CAP_XFERCOUNT, &value, false);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
HGResult HGTwainDSImpl::SetCapbility(HGUShort cap, const HGCapValue* value, HGBool reset)
|
|
{
|
|
TW_CAPABILITY twCap;
|
|
twCap.Cap = (TW_UINT16)cap;
|
|
twCap.ConType = TWON_ONEVALUE;
|
|
twCap.hContainer = NULL;
|
|
|
|
HGInt size = 0;
|
|
TW_UINT16 itemType = 0;
|
|
|
|
if (HGCAPVALUE_TYPE_CHAR == value->type)
|
|
{
|
|
size = sizeof(CapInt8Type);
|
|
itemType = TWTY_INT8;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_BYTE == value->type)
|
|
{
|
|
size = sizeof(CapUInt8Type);
|
|
itemType = TWTY_UINT8;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_SHORT == value->type)
|
|
{
|
|
size = sizeof(CapInt16Type);
|
|
itemType = TWTY_INT16;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_USHORT == value->type)
|
|
{
|
|
size = sizeof(CapUInt16Type);
|
|
itemType = TWTY_UINT16;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_INT == value->type)
|
|
{
|
|
size = sizeof(CapInt32Type);
|
|
itemType = TWTY_INT32;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_UINT == value->type)
|
|
{
|
|
size = sizeof(CapUInt32Type);
|
|
itemType = TWTY_UINT32;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_BOOL == value->type)
|
|
{
|
|
size = sizeof(CapBoolType);
|
|
itemType = TWTY_BOOL;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_FLOAT == value->type)
|
|
{
|
|
size = sizeof(CapFix32Type);
|
|
itemType = TWTY_FIX32;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR32 == value->type)
|
|
{
|
|
size = sizeof(CapStr32Type);
|
|
itemType = TWTY_STR32;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR64 == value->type)
|
|
{
|
|
size = sizeof(CapStr64Type);
|
|
itemType = TWTY_STR64;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR128 == value->type)
|
|
{
|
|
size = sizeof(CapStr128Type);
|
|
itemType = TWTY_STR128;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR255 == value->type)
|
|
{
|
|
size = sizeof(CapStr255Type);
|
|
itemType = TWTY_STR255;
|
|
}
|
|
|
|
twCap.hContainer = GlobalAlloc(GHND, size);
|
|
if (NULL == twCap.hContainer)
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
void* pVal = GlobalLock(twCap.hContainer);
|
|
assert(NULL != pVal);
|
|
|
|
if (HGCAPVALUE_TYPE_CHAR == value->type)
|
|
{
|
|
((CapInt8Type*)pVal)->ItemType = itemType;
|
|
((CapInt8Type*)pVal)->Value = value->valueChar;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_BYTE == value->type)
|
|
{
|
|
((CapUInt8Type*)pVal)->ItemType = itemType;
|
|
((CapUInt8Type*)pVal)->Value = value->valueByte;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_SHORT == value->type)
|
|
{
|
|
((CapInt16Type*)pVal)->ItemType = itemType;
|
|
((CapInt16Type*)pVal)->Value = value->valueShort;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_USHORT == value->type)
|
|
{
|
|
((CapUInt16Type*)pVal)->ItemType = itemType;
|
|
((CapUInt16Type*)pVal)->Value = value->valueUShort;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_INT == value->type)
|
|
{
|
|
((CapInt32Type*)pVal)->ItemType = itemType;
|
|
((CapInt32Type*)pVal)->Value = value->valueInt;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_UINT == value->type)
|
|
{
|
|
((CapUInt32Type*)pVal)->ItemType = itemType;
|
|
((CapUInt32Type*)pVal)->Value = value->valueUInt;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_BOOL == value->type)
|
|
{
|
|
((CapBoolType*)pVal)->ItemType = itemType;
|
|
((CapBoolType*)pVal)->Value = value->valueBool;
|
|
}
|
|
else if (HGCAPVALUE_TYPE_FLOAT == value->type)
|
|
{
|
|
((CapFix32Type*)pVal)->ItemType = itemType;
|
|
((CapFix32Type*)pVal)->Value = FloatToFIX32(value->valueFloat);
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR32 == value->type)
|
|
{
|
|
assert(NULL != pVal);
|
|
((CapStr32Type*)pVal)->ItemType = itemType;
|
|
if (reset)
|
|
memset(((CapStr32Type*)pVal)->Value, 0, sizeof(((CapStr32Type*)pVal)->Value));
|
|
else
|
|
strcpy(((CapStr32Type*)pVal)->Value, value->valueStr32);
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR64 == value->type)
|
|
{
|
|
assert(NULL != pVal);
|
|
((CapStr64Type*)pVal)->ItemType = itemType;
|
|
if (reset)
|
|
memset(((CapStr64Type*)pVal)->Value, 0, sizeof(((CapStr64Type*)pVal)->Value));
|
|
else
|
|
strcpy(((CapStr64Type*)pVal)->Value, value->valueStr64);
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR128 == value->type)
|
|
{
|
|
assert(NULL != pVal);
|
|
((CapStr128Type*)pVal)->ItemType = itemType;
|
|
if (reset)
|
|
memset(((CapStr128Type*)pVal)->Value, 0, sizeof(((CapStr128Type*)pVal)->Value));
|
|
else
|
|
strcpy(((CapStr128Type*)pVal)->Value, value->valueStr128);
|
|
}
|
|
else if (HGCAPVALUE_TYPE_STR255 == value->type)
|
|
{
|
|
assert(NULL != pVal);
|
|
((CapStr255Type*)pVal)->ItemType = itemType;
|
|
if (reset)
|
|
memset(((CapStr255Type*)pVal)->Value, 0, sizeof(((CapStr255Type*)pVal)->Value));
|
|
else
|
|
strcpy(((CapStr255Type*)pVal)->Value, value->valueStr255);
|
|
}
|
|
|
|
GlobalUnlock(twCap.hContainer);
|
|
|
|
USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, reset ? MSG_RESET : MSG_SET, &twCap);
|
|
GlobalFree(twCap.hContainer);
|
|
return (TWRC_SUCCESS == ret) ? HGBASE_ERR_OK : HGTWAIN_ERR_FAIL;
|
|
}
|
|
|
|
HGResult HGTwainDSImpl::GetCapbility(HGUShort cap, HGCapValue* 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->type = HGCAPVALUE_TYPE_CHAR;
|
|
value->valueChar = ((CapInt8Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_UINT8)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_BYTE;
|
|
value->valueByte = ((CapUInt8Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_INT16)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_SHORT;
|
|
value->valueShort = ((CapInt16Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_UINT16)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_USHORT;
|
|
value->valueUShort = ((CapUInt16Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_INT32)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_INT;
|
|
value->valueInt = ((CapInt32Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_UINT32)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_UINT;
|
|
value->valueUInt = ((CapUInt32Type*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_BOOL)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_BOOL;
|
|
value->valueBool = ((CapBoolType*)pVal)->Value;
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_FIX32)
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_FLOAT;
|
|
value->valueFloat = FIX32ToFloat(((CapFix32Type*)pVal)->Value);
|
|
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else if (ItemType == TWTY_STR32)
|
|
{
|
|
if (32 > strlen(((CapStr32Type*)pVal)->Value))
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_STR32;
|
|
strcpy(value->valueStr32, ((CapStr32Type*)pVal)->Value);
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else
|
|
{
|
|
ret = HGBASE_ERR_INVALIDARG;
|
|
}
|
|
}
|
|
else if (ItemType == TWTY_STR64)
|
|
{
|
|
if (64 > strlen(((CapStr64Type*)pVal)->Value))
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_STR64;
|
|
strcpy(value->valueStr64, ((CapStr64Type*)pVal)->Value);
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else
|
|
{
|
|
ret = HGBASE_ERR_INVALIDARG;
|
|
}
|
|
}
|
|
else if (ItemType == TWTY_STR128)
|
|
{
|
|
if (128 > strlen(((CapStr128Type*)pVal)->Value))
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_STR128;
|
|
strcpy(value->valueStr128, ((CapStr128Type*)pVal)->Value);
|
|
ret = HGBASE_ERR_OK;
|
|
}
|
|
else
|
|
{
|
|
ret = HGBASE_ERR_INVALIDARG;
|
|
}
|
|
}
|
|
else if (ItemType == TWTY_STR255)
|
|
{
|
|
if (255 > strlen(((CapStr255Type*)pVal)->Value))
|
|
{
|
|
value->type = HGCAPVALUE_TYPE_STR255;
|
|
strcpy(value->valueStr255, ((CapStr255Type*)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;
|
|
}
|
|
|
|
TW_FIX32 HGTwainDSImpl::FloatToFIX32(float i_float)
|
|
{
|
|
TW_FIX32 Fix32_value;
|
|
TW_INT32 value = (TW_INT32)(i_float * 65536.0 + 0.5);
|
|
Fix32_value.Whole = LOWORD(value >> 16);
|
|
Fix32_value.Frac = LOWORD(value & 0x0000ffffL);
|
|
return Fix32_value;
|
|
}
|
|
|
|
float HGTwainDSImpl::FIX32ToFloat(TW_FIX32 FIX32Value)
|
|
{
|
|
TW_INT16 whole = FIX32Value.Whole;
|
|
TW_UINT16 frac = FIX32Value.Frac;
|
|
return (float)(whole << 16 | frac) / 65536.0;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|