#include "HGTwainImpl.hpp" #include "../base/HGInc.h" extern HMODULE g_hInst; ULONG HGTwainDSMImpl::m_nRefCount = 0; HGTwainDSMImpl::HGTwainDSMImpl() { m_hDll = NULL; m_pDSMProc = NULL; GetIdentity(); m_hWnd = NULL; m_DSMOpen = HGFALSE; if (0 == m_nRefCount) { WNDCLASSW wndcls; wndcls.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndcls.lpfnWndProc = WndProc; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hInstance = g_hInst; wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndcls.lpszMenuName = NULL; wndcls.lpszClassName = L"TwainDSMWnd"; ATOM atom = RegisterClassW(&wndcls); assert(0 != atom); } ++m_nRefCount; } HGTwainDSMImpl::~HGTwainDSMImpl() { --m_nRefCount; if (0 == m_nRefCount) { UnregisterClassW(L"TwainDSMWnd", g_hInst); } } 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() { if (NULL == m_pDSMProc || m_DSMOpen) { return HGBASE_ERR_FAIL; } assert(NULL == m_hWnd); HWND hWnd = CreateWindowExW(0, TEXT("TwainDSMWnd"), NULL, WS_OVERLAPPEDWINDOW, -1, -1, 1, 1, NULL, (HMENU)0, g_hInst, NULL); assert(NULL != hWnd); SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)this); USHORT ret = m_pDSMProc(&m_AppId, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, (TW_MEMREF)&hWnd); if (TWRC_SUCCESS != ret) { DestroyWindow(hWnd); return HGBASE_ERR_FAIL; } m_hWnd = hWnd; 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); DestroyWindow(m_hWnd); m_hWnd = 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, HGDSEventFunc func, HGPointer param) { if (NULL == ds || NULL == func) { 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].func = func; m_DSList[i].param = param; m_DSList[i].enable = HGTRUE; return HGBASE_ERR_OK; } } return HGBASE_ERR_FAIL; } HGResult HGTwainDSMImpl::EnableDS(HGTwainDSImpl* ds, HGBool showUI, HWND parent, HGDSEventFunc func, HGPointer param) { if (NULL == ds || NULL == func) { 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].func = func; m_DSList[i].param = param; 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].param; 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].func = NULL; m_DSList[i].param = 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::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HGTwainDSMImpl *p = (HGTwainDSMImpl *)GetWindowLongPtrW(hWnd, GWLP_USERDATA); if (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 && NULL != p->m_DSList[i].func) { 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_DSList[i].func((HGTwainDS)&p->m_DSList[i], event, p->m_DSList[i].param); } } } } return DefWindowProc(hWnd, msg, wParam, lParam); }