#include "HGTwainImpl.hpp" #include "../base/HGInc.h" #include "../base/HGInfo.h" std::map 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; } HGTwainDSMImpl::~HGTwainDSMImpl() { } HGResult HGTwainDSMImpl::Create(HWND hwnd) { assert(NULL == m_oldWndProc); if (NULL == hwnd) { return HGBASE_ERR_INVALIDARG; } assert(NULL == m_hDll); HGBase_CreateDll("twain_32.dll", &m_hDll); 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); return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::Destroy() { assert(NULL != m_oldWndProc); if (!m_listDSImpl.empty()) { return HGBASE_ERR_FAIL; } 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::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; } HGUInt num = 0; TW_IDENTITY ds; if (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &ds)) { ++num; while (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &ds)) { ++num; } } *count = num; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::GetDSName(HGUInt index, HGChar* name, HGUInt maxLen) { if (NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } std::vector vds; TW_IDENTITY ds; if (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &ds)) { vds.push_back(ds); while (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &ds)) { vds.push_back(ds); } } if (index >= (HGUInt)vds.size()) return HGBASE_ERR_INVALIDARG; if (maxLen < strlen(vds[index].ProductName) + 1) return HGBASE_ERR_FAIL; strcpy(name, vds[index].ProductName); return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::OpenDS(HGUInt index, class HGTwainDSImpl** dsImpl) { if (NULL == dsImpl) { return HGBASE_ERR_INVALIDARG; } std::vector vds; TW_IDENTITY ds; if (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &ds)) { vds.push_back(ds); while (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &ds)) { vds.push_back(ds); } } if (index >= (HGUInt)vds.size()) return HGBASE_ERR_INVALIDARG; class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this); HGResult ret = newDSImpl->Open(&vds[index]); if (HGBASE_ERR_OK != ret) { delete newDSImpl; return ret; } m_listDSImpl.push_back(newDSImpl); *dsImpl = newDSImpl; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::OpenDefaultDS(class HGTwainDSImpl** dsImpl) { if (NULL == dsImpl) { return HGBASE_ERR_INVALIDARG; } TW_IDENTITY defDS; if (TWRC_SUCCESS != m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &defDS)) { return HGTWAIN_ERR_FAIL; } class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this); HGResult ret = newDSImpl->Open(&defDS); if (HGBASE_ERR_OK != ret) { delete newDSImpl; return ret; } m_listDSImpl.push_back(newDSImpl); *dsImpl = newDSImpl; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::OpenSelectedDS(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_FAIL; } class HGTwainDSImpl* newDSImpl = new HGTwainDSImpl(this); HGResult ret = newDSImpl->Open(&selectDS); if (HGBASE_ERR_OK != ret) { delete newDSImpl; return ret; } m_listDSImpl.push_back(newDSImpl); *dsImpl = newDSImpl; return HGBASE_ERR_OK; } void HGTwainDSMImpl::RemoveDS(class HGTwainDSImpl* dsImpl) { std::vector::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) { if (p->m_listDSImpl[i]->m_enable) { 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) { while (1) { HGImage image = NULL; p->m_listDSImpl[i]->ImageNativeXfer(0, 0, &image); if (NULL != image) { if (NULL != p->m_listDSImpl[i]->m_imageFunc) p->m_listDSImpl[i]->m_imageFunc((HGTwainDS)p->m_listDSImpl[i], image, p->m_listDSImpl[i]->m_imageParam); HGBase_DestroyImage(image); } HGUInt count = 0; p->m_listDSImpl[i]->EndXfer(&count); if (0 == count) { break; } } p->m_listDSImpl[i]->Reset(); } else if (MSG_CLOSEDSREQ == twEvent.TWMessage/* || MSG_CLOSEDSOK == twEvent.TWMessage*/) { if (NULL != p->m_listDSImpl[i]->m_eventFunc) p->m_listDSImpl[i]->m_eventFunc((HGTwainDS)p->m_listDSImpl[i], HGBASE_ERR_OK, NULL, p->m_listDSImpl[i]->m_eventParam); } } } } return CallWindowProcW(p->m_oldWndProc, hWnd, msg, wParam, lParam); } HGTwainDSImpl::HGTwainDSImpl(HGTwainDSMImpl* dsmImpl) { m_dsmImpl = dsmImpl; memset(&m_iden, 0, sizeof(TW_IDENTITY)); m_open = HGFALSE; m_showUI = HGFALSE; m_parent = NULL; m_eventFunc = NULL; m_eventParam = NULL; m_imageFunc = NULL; m_imageParam = NULL; m_enable = HGFALSE; } HGTwainDSImpl::~HGTwainDSImpl() { } HGResult HGTwainDSImpl::Open(const TW_IDENTITY* iden) { assert(!m_open); 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; } memcpy(&m_iden, iden, sizeof(TW_IDENTITY)); m_open = HGTRUE; return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::Close() { assert(m_open); Disable(); m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, (TW_MEMREF)&m_iden); m_open = HGFALSE; m_dsmImpl->RemoveDS(this); return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::EnableUIOnly(HWND parent, HGDSEventFunc eventFunc, HGPointer eventParam) { if (m_enable) { return HGBASE_ERR_FAIL; } 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) { return HGTWAIN_ERR_FAIL; } m_showUI = HGTRUE; m_parent = parent; m_eventFunc = eventFunc; m_eventParam = eventParam; m_imageFunc = NULL; m_imageParam = NULL; m_enable = HGTRUE; return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::Enable(HGBool showUI, HWND parent, HGDSEventFunc eventFunc, HGPointer eventParam, HGDSImageFunc imageFunc, HGPointer imageParam) { if (m_enable) { return HGBASE_ERR_FAIL; } 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) { return HGTWAIN_ERR_FAIL; } m_showUI = showUI; m_parent = parent; m_eventFunc = eventFunc; m_eventParam = eventParam; m_imageFunc = imageFunc; m_imageParam = imageParam; m_enable = HGTRUE; return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::Disable() { if (!m_enable) { return HGBASE_ERR_FAIL; } 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); m_showUI = HGFALSE; m_parent = NULL; m_eventFunc = NULL; m_eventParam = NULL; m_imageFunc = NULL; m_imageParam = NULL; m_enable = HGFALSE; return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::SetCap(HGUInt cap, HGInt value) { TW_CAPABILITY twCap; twCap.Cap = (TW_UINT16)cap; twCap.ConType = TWON_ONEVALUE; twCap.hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE)); if (NULL == twCap.hContainer) { return HGBASE_ERR_FAIL; } pTW_ONEVALUE pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer); assert(NULL != pVal); pVal->ItemType = TWTY_INT32; pVal->Item = (TW_UINT32)value; GlobalUnlock(twCap.hContainer); USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap); if (TWRC_SUCCESS != ret) { GlobalFree(twCap.hContainer); return HGTWAIN_ERR_FAIL; } GlobalFree(twCap.hContainer); return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::GetCap(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; USHORT ret = m_dsmImpl->m_pDSMProc(&m_dsmImpl->m_AppId, &m_iden, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap); if (TWRC_SUCCESS != ret) { return HGTWAIN_ERR_FAIL; } assert(NULL != twCap.hContainer); pTW_ONEVALUE pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer); assert(NULL != pVal); *value = pVal->Item; GlobalUnlock(twCap.hContainer); GlobalFree(twCap.hContainer); return HGBASE_ERR_OK; } HGResult HGTwainDSImpl::ImageNativeXfer(HGUInt type, HGUInt origin, HGImage* image) { if (!m_enable) { return HGBASE_ERR_FAIL; } 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; } 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; } HGResult ret = HGBase_CreateImageFromDIB(hMem, NULL, type, origin, image); GlobalFree(hMem); return ret; } HGResult HGTwainDSImpl::EndXfer(HGUInt* count) { if (!m_enable) { return HGBASE_ERR_FAIL; } 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() { if (!m_enable) { return HGBASE_ERR_FAIL; } 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; }