#include "HGTwainImpl.hpp" #include "../base/HGInc.h" std::map HGTwainDSMImpl::m_mapWnd; HGTwainDSMImpl::HGTwainDSMImpl() { m_hDll = NULL; m_pDSMProc = NULL; GetIdentity(); m_hWnd = NULL; m_oldWndProc = NULL; m_dsEventFunc = NULL; m_dsEventParam = NULL; m_DSMOpen = HGFALSE; } HGTwainDSMImpl::~HGTwainDSMImpl() { UnloadDSM(); } HGResult HGTwainDSMImpl::LoadDSM() { if (NULL != m_pDSMProc) { return HGBASE_ERR_FAIL; } assert(NULL == m_hDll); HGBase_CreateDll("twain_32.dll", &m_hDll); if (NULL == m_hDll) { return HGBASE_ERR_FAIL; } HGBase_GetDllProcAddress(m_hDll, MAKEINTRESOURCEA(1), (HGPointer*)&m_pDSMProc); if (NULL == m_pDSMProc) { HGBase_DestroyDll(m_hDll); m_hDll = NULL; return HGBASE_ERR_FAIL; } return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::UnloadDSM() { if (NULL == m_pDSMProc) { return HGBASE_ERR_FAIL; } // 先必须关闭DSM CloseDSM(); m_pDSMProc = NULL; HGBase_DestroyDll(m_hDll); m_hDll = NULL; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::OpenDSM(HWND hwnd, HGDSEventFunc func, HGPointer param) { if (NULL == m_pDSMProc || m_DSMOpen || NULL == hwnd || NULL == func) { return HGBASE_ERR_FAIL; } USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, (TW_MEMREF)&hwnd); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } m_hWnd = hwnd; m_mapWnd[m_hWnd] = this; m_oldWndProc = (WNDPROC)SetWindowLongPtrW(m_hWnd, GWLP_WNDPROC, (LONG_PTR)NewWndProc); m_dsEventFunc = func; m_dsEventParam = param; m_DSMOpen = HGTRUE; // 获取DS列表 TW_IDENTITY ds; ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &ds); if (TWRC_SUCCESS == ret) { HGTwainDSImpl dsImpl(this); memcpy(&dsImpl.ds, &ds, sizeof(TW_IDENTITY)); m_DSList.push_back(dsImpl); while (TWRC_SUCCESS == m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &ds)) { HGTwainDSImpl dsImpl(this); memcpy(&dsImpl.ds, &ds, sizeof(TW_IDENTITY)); m_DSList.push_back(dsImpl); } } return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::CloseDSM() { if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } // 先必须关闭DS for (int i = 0; i < (int)m_DSList.size(); ++i) { CloseDS(&m_DSList[i]); } // 清理DS列表 m_DSList.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::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_dsEventFunc = NULL; m_dsEventParam = NULL; m_DSMOpen = HGFALSE; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::GetDSList(HGTwainDSImpl** ds, HGUInt* size) { if (NULL == ds || NULL == size || 0 == *size) { return HGBASE_ERR_INVALIDARG; } if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } HGUInt count = 0; for (int i = 0; i < (int)m_DSList.size(); ++i) { ds[i] = &m_DSList[i]; ++count; if (count >= *size) { break; } } *size = count; return HGBASE_ERR_OK; } HGResult HGTwainDSMImpl::GetDefaultDS(HGTwainDSImpl** ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } assert(NULL != m_pDSMProc); TW_IDENTITY defDS; USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &defDS); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (0 == memcmp(&defDS, &m_DSList[i].ds, sizeof(TW_IDENTITY))) { *ds = &m_DSList[i]; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::SelectDS(HGTwainDSImpl** ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } assert(NULL != m_pDSMProc); TW_IDENTITY selectDS; USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &selectDS); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (0 == memcmp(&selectDS, &m_DSList[i].ds, sizeof(TW_IDENTITY))) { *ds = &m_DSList[i]; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::GetDSName(HGTwainDSImpl* ds, HGChar* name, HGUInt maxLen) { if (NULL == ds || NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { strcpy_s(name, maxLen, m_DSList[i].ds.ProductName); return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::OpenDS(HGTwainDSImpl* ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } if (!m_DSMOpen) { return HGBASE_ERR_FAIL; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (m_DSList[i].open) { return HGBASE_ERR_FAIL; } USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &m_DSList[i].ds); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } m_DSList[i].open = HGTRUE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::CloseDS(HGTwainDSImpl* ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].open) { return HGBASE_ERR_FAIL; } DisableDS(ds); m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, (TW_MEMREF)&m_DSList[i].ds); m_DSList[i].open = HGFALSE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::SetCapability(HGTwainDSImpl* ds, HGUInt cap, HGInt value) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].open) { return HGBASE_ERR_FAIL; } TW_UINT16 cap2 = 0; if (HGTWAIN_DSCAP_DUPLEX == cap) cap2 = CAP_DUPLEX; else if (HGTWAIN_DSCAP_DUPLEXENABLED == cap) cap2 = CAP_DUPLEXENABLED; else if (HGTWAIN_DSCAP_XFERCOUNT == cap) cap2 = CAP_XFERCOUNT; if (0 == cap2) { return HGBASE_ERR_FAIL; } TW_CAPABILITY twCap; twCap.Cap = (TW_UINT16)cap2; 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_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &twCap); if (TWRC_SUCCESS != ret) { GlobalFree(twCap.hContainer); return HGBASE_ERR_FAIL; } GlobalFree(twCap.hContainer); return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::GetCapability(HGTwainDSImpl* ds, HGUInt cap, HGInt* value) { if (NULL == ds || NULL == value) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].open) { return HGBASE_ERR_FAIL; } TW_UINT16 cap2 = 0; if (HGTWAIN_DSCAP_DUPLEX == cap) cap2 = CAP_DUPLEX; else if (HGTWAIN_DSCAP_DUPLEXENABLED == cap) cap2 = CAP_DUPLEXENABLED; else if (HGTWAIN_DSCAP_XFERCOUNT == cap) cap2 = CAP_XFERCOUNT; if (0 == cap2) { return HGBASE_ERR_FAIL; } TW_CAPABILITY twCap; twCap.Cap = (TW_UINT16)cap2; twCap.ConType = TWON_ONEVALUE; twCap.hContainer = NULL; USHORT ret = m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, &twCap); if (TWRC_SUCCESS != ret) { return HGBASE_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; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::EnableDSUIOnly(HGTwainDSImpl* ds, HGBool showUI, HWND parent) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].open || m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_USERINTERFACE twUI; twUI.ShowUI = (TW_BOOL)showUI; twUI.hParent = (TW_HANDLE)parent; USHORT ret = m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDSUIONLY, (TW_MEMREF)&twUI); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } m_DSList[i].showUI = showUI; m_DSList[i].parent = parent; m_DSList[i].enable = HGTRUE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::EnableDS(HGTwainDSImpl* ds, HGBool showUI, HWND parent) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].open || m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_USERINTERFACE twUI; twUI.ShowUI = (TW_BOOL)showUI; twUI.hParent = (TW_HANDLE)parent; USHORT ret = m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, (TW_MEMREF)&twUI); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } m_DSList[i].showUI = showUI; m_DSList[i].parent = parent; m_DSList[i].enable = HGTRUE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::DisableDS(HGTwainDSImpl* ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_USERINTERFACE twUI; twUI.ShowUI = (TW_BOOL)m_DSList[i].showUI; twUI.hParent = (TW_HANDLE)m_DSList[i].parent; m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &twUI); m_DSList[i].showUI = HGFALSE; m_DSList[i].parent = NULL; m_DSList[i].enable = HGFALSE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::ImageNativeXfer(HGTwainDSImpl* ds, HGUInt type, HGUInt origin, HGImage* image) { if (NULL == ds || NULL == image) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_IMAGEINFO info; if (TWRC_SUCCESS != m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info)) { return HGBASE_ERR_FAIL; } HANDLE hMem = NULL; if (TWRC_XFERDONE != m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hMem)) { return HGBASE_ERR_FAIL; } HGResult ret = HGBase_CreateImageFromDIB(hMem, NULL, type, origin, image); GlobalFree(hMem); return ret; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::EndXfer(HGTwainDSImpl* ds, HGUInt* count) { if (NULL == ds || NULL == count) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_PENDINGXFERS twPend; USHORT ret = m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&twPend); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } *count = twPend.Count; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::Reset(HGTwainDSImpl* ds) { if (NULL == ds) { return HGBASE_ERR_INVALIDARG; } for (int i = 0; i < (int)m_DSList.size(); ++i) { if (ds == &m_DSList[i]) { if (!m_DSList[i].enable) { return HGBASE_ERR_FAIL; } TW_PENDINGXFERS twPend; USHORT ret = m_pDSMProc(&m_AppId, &m_DSList[i].ds, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, (TW_MEMREF)&twPend); if (TWRC_SUCCESS != ret) { return HGBASE_ERR_FAIL; } return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } void HGTwainDSMImpl::GetIdentity() { 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"); } 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_DSList.size(); ++i) { if (p->m_DSList[i].enable) { TW_EVENT twEvent; twEvent.pEvent = (TW_MEMREF)&msg2; twEvent.TWMessage = MSG_NULL; USHORT ret = p->m_pDSMProc(&p->m_AppId, &p->m_DSList[i].ds, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, (TW_MEMREF)&twEvent); if (TWRC_DSEVENT == ret) { HGUInt event = HGTWAIN_DSEVENT_UNKNOWN; if (MSG_XFERREADY == twEvent.TWMessage) event = HGTWAIN_DSEVENT_XFERREADY; else if (MSG_CLOSEDSREQ == twEvent.TWMessage) event = HGTWAIN_DSEVENT_CLOSEDSREQ; else if (MSG_CLOSEDSOK == twEvent.TWMessage) event = HGTWAIN_DSEVENT_CLOSEDSOK; p->m_dsEventFunc((HGTwainDS)&p->m_DSList[i], event, p->m_dsEventParam); } } } return CallWindowProcW(p->m_oldWndProc, hWnd, msg, wParam, lParam); }