www.pudn.com > 基于TWAIN接口程序.zip > TwainCpp.cpp


#include "stdafx.h" 
#include "twaincpp.h" 
 
/* 
Constructor: 
	Parameters : HWND  
				Window to subclass 
				  
*/ 
CTwain::CTwain(HWND hWnd) 
{ 
	m_hTwainDLL = NULL; 
	m_pDSMProc = NULL; 
	m_bSourceSelected = FALSE; 
	m_bDSOpen = m_bDSMOpen = FALSE; 
	m_bSourceEnabled = FALSE; 
	m_bModalUI = TRUE; 
	m_nImageCount = TWCPP_ANYCOUNT; 
	if(hWnd) 
	{ 
		InitTwain(hWnd); 
	} 
} 
 
CTwain::~CTwain() 
{ 
	ReleaseTwain(); 
} 
 
/* 
Initializes TWAIN interface . Is already called from the constructor.  
It should be called again if ReleaseTwain is called. 
 
  hWnd is the window which has to subclassed in order to recieve 
  Twain messaged. Normally - this would be your main application window. 
 
*/ 
BOOL CTwain::InitTwain(HWND hWnd) 
{ 
char libName[512]; 
	if(IsValidDriver())  
	{ 
		return TRUE; 
	} 
	memset(&m_AppId,0,sizeof(m_AppId)); 
	if(!IsWindow(hWnd)) 
	{ 
		return FALSE; 
	} 
	m_hMessageWnd = hWnd; 
	strcpy(libName,"TWAIN_32.DLL"); 
	 
	m_hTwainDLL  = LoadLibrary(libName); 
	if(m_hTwainDLL != NULL) 
	{ 
		if(!(m_pDSMProc = (DSMENTRYPROC)GetProcAddress(m_hTwainDLL,MAKEINTRESOURCE(1)))) 
		{ 
			FreeLibrary(m_hTwainDLL); 
			m_hTwainDLL = NULL; 
		} 
	} 
	if(IsValidDriver()) 
	{ 
		GetIdentity(); 
		m_bDSMOpen= CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&m_hMessageWnd); 
		return TRUE; 
	} 
	else 
	{ 
		return FALSE; 
	} 
} 
 
/* 
Releases the twain interface . Need not be called unless you 
want to specifically shut it down. 
*/ 
void CTwain::ReleaseTwain() 
{ 
	if(IsValidDriver()) 
	{ 
		CloseDSM(); 
		FreeLibrary(m_hTwainDLL); 
		m_hTwainDLL = NULL; 
		m_pDSMProc = NULL; 
	} 
} 
 
/* 
Returns true if a valid driver has been loaded 
*/ 
BOOL CTwain::IsValidDriver() const 
{ 
	return (m_hTwainDLL && m_pDSMProc); 
} 
 
/* 
Entry point into Twain. For a complete description of this 
routine  please refer to the Twain specification 1.8 
*/ 
BOOL CTwain::CallTwainProc(pTW_IDENTITY pOrigin,pTW_IDENTITY pDest, 
					   TW_UINT32 DG,TW_UINT16 DAT,TW_UINT16 MSG, 
					   TW_MEMREF pData) 
{ 
	if(IsValidDriver()) 
	{ 
	USHORT ret_val; 
		ret_val = (*m_pDSMProc)(pOrigin,pDest,DG,DAT,MSG,pData); 
		m_returnCode = ret_val; 
		if(ret_val != TWRC_SUCCESS) 
		{ 
			(*m_pDSMProc)(pOrigin,pDest,DG_CONTROL,DAT_STATUS,MSG_GET,&m_Status); 
		} 
		return (ret_val == TWRC_SUCCESS); 
	} 
	else 
	{ 
		m_returnCode = TWRC_FAILURE; 
		return FALSE; 
	} 
} 
 
/* 
This function should ideally be overridden in the derived class . If only a  
few fields need to be updated , call CTawin::GetIdentity first in your 
derived class 
*/ 
void CTwain::GetIdentity() 
{ 
	// Expects all the fields in m_AppId to be set except for the id field. 
	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 = 5; 
	m_AppId.Version.Language = TWLG_USA; 
	m_AppId.Version.Country = TWCY_USA; 
	strcpy (m_AppId.Version.Info, "3.5"); 
	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, "Twain Test"); 
 
} 
 
 
/* 
Called to display a dialog box to select the Twain source to use. 
This can be overridden if a list of all sources is available 
to the application. These sources can be enumerated by Twain. 
it is not yet supportted by CTwain. 
*/ 
BOOL CTwain::SelectSource() 
{ 
	memset(&m_Source,0,sizeof(m_Source)); 
	if(!SourceSelected()) 
	{ 
		SelectDefaultSource(); 
	} 
	if(CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_USERSELECT,&m_Source)) 
	{ 
		m_bSourceSelected = TRUE; 
	} 
	return m_bSourceSelected; 
} 
 
/* 
Called to select the default source 
*/ 
BOOL CTwain::SelectDefaultSource() 
{ 
	m_bSourceSelected = CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_GETDEFAULT,&m_Source); 
	return m_bSourceSelected; 
} 
 
/* 
Closes the Data Source 
*/ 
void CTwain::CloseDS() 
{ 
	if(DSOpen()) 
	{ 
		DisableSource(); 
		CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&m_Source); 
		m_bDSOpen = FALSE; 
	} 
} 
 
/* 
Closes the Data Source Manager 
*/ 
void CTwain::CloseDSM() 
{ 
	if(DSMOpen()) 
	{ 
		CloseDS(); 
		CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_PARENT,MSG_CLOSEDSM,(TW_MEMREF)&m_hMessageWnd); 
		m_bDSMOpen = FALSE; 
	} 
} 
 
/* 
Returns true if the Data Source Manager is Open 
*/ 
BOOL CTwain::DSMOpen() const 
{ 
	return IsValidDriver() && m_bDSMOpen; 
} 
 
/* 
Returns true if the Data Source is Open 
*/ 
BOOL CTwain::DSOpen() const 
{ 
	return IsValidDriver() && DSMOpen() && m_bDSOpen; 
} 
 
/* 
Opens a Data Source supplied as the input parameter 
*/ 
BOOL CTwain::OpenSource(TW_IDENTITY *pSource) 
{ 
	if(pSource)  
	{ 
		m_Source = *pSource; 
	} 
	if(DSMOpen()) 
	{ 
		if(!SourceSelected()) 
		{ 
			SelectDefaultSource(); 
		} 
		m_bDSOpen = CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_OPENDS,(TW_MEMREF)&m_Source); 
	} 
	return DSOpen(); 
} 
 
/* 
Should be called from the main message loop of the application. Can always be called, 
it will not process the message unless a scan is in progress. 
*/ 
BOOL CTwain::ProcessMessage(MSG msg) 
{ 
	if(SourceEnabled()) 
	{ 
	TW_EVENT twEvent; 
		twEvent.pEvent = (TW_MEMREF)&msg; 
		twEvent.TWMessage = MSG_NULL; 
	 
		CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT,(TW_MEMREF)&twEvent); 
		if(GetRC() != TWRC_NOTDSEVENT) 
		{ 
			TranslateMessage(twEvent); 
		} 
		return FALSE; 
 
	} 
	return FALSE; 
} 
 
/* 
Queries the capability of the Twain Data Source 
*/ 
BOOL CTwain::GetCapability(TW_CAPABILITY& twCap,TW_UINT16 cap,TW_UINT16 conType) 
{ 
	if(DSOpen()) 
	{ 
		twCap.Cap = cap; 
		twCap.ConType = conType; 
		twCap.hContainer = NULL; 
 
		if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_GET,(TW_MEMREF)&twCap)) 
		{ 
			return TRUE; 
		} 
	} 
	return FALSE; 
} 
 
/* 
Queries the capability of the Twain Data Source 
*/ 
BOOL CTwain::GetCapability(TW_UINT16 cap,TW_UINT32& value) 
{ 
TW_CAPABILITY twCap; 
	if(GetCapability(twCap,cap)) 
	{ 
	pTW_ONEVALUE pVal; 
		pVal = (pTW_ONEVALUE )GlobalLock(twCap.hContainer); 
		if(pVal) 
		{ 
			value = pVal->Item; 
			GlobalUnlock(pVal); 
			GlobalFree(twCap.hContainer); 
			return TRUE; 
		} 
	} 
	return FALSE; 
} 
 
 
/* 
Sets the capability of the Twain Data Source 
*/ 
BOOL CTwain::SetCapability(TW_UINT16 cap,TW_UINT16 value,BOOL sign) 
{ 
	if(DSOpen()) 
	{ 
	TW_CAPABILITY twCap; 
	pTW_ONEVALUE pVal; 
	BOOL ret_value = FALSE; 
 
		twCap.Cap = cap; 
		twCap.ConType = TWON_ONEVALUE; 
		 
		twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE)); 
		if(twCap.hContainer) 
		{ 
			pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer); 
			pVal->ItemType = sign ? TWTY_INT16 : TWTY_UINT16; 
			pVal->Item = (TW_UINT32)value; 
			GlobalUnlock(twCap.hContainer); 
			ret_value = SetCapability(twCap); 
			GlobalFree(twCap.hContainer); 
		} 
		return ret_value; 
	} 
	return FALSE; 
} 
 
/* 
Sets the capability of the Twain Data Source 
*/ 
BOOL CTwain::SetCapability(TW_CAPABILITY& cap) 
{ 
	if(DSOpen()) 
	{ 
		return CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_SET,(TW_MEMREF)&cap); 
	} 
	return FALSE; 
} 
 
/* 
Sets the number of images which can be accpeted by the application at one time 
*/ 
BOOL CTwain::SetImageCount(TW_INT16 nCount) 
{ 
	if(SetCapability(CAP_XFERCOUNT,(TW_UINT16)nCount,TRUE)) 
	{ 
		m_nImageCount = nCount; 
		return TRUE; 
	} 
	else 
	{ 
		if(GetRC() == TWRC_CHECKSTATUS) 
		{ 
		TW_UINT32 count; 
			if(GetCapability(CAP_XFERCOUNT,count)) 
			{ 
				nCount = (TW_INT16)count; 
				if(SetCapability(CAP_XFERCOUNT,nCount)) 
				{ 
					m_nImageCount = nCount; 
					return TRUE; 
				} 
			} 
		} 
	} 
	return FALSE; 
} 
 
/* 
Called to enable the Twain Acquire Dialog. This too can be 
overridden but is a helluva job .  
*/ 
BOOL CTwain::EnableSource(BOOL showUI) 
{ 
	if(DSOpen() && !SourceEnabled()) 
	{ 
		TW_USERINTERFACE twUI; 
		twUI.ShowUI = showUI; 
		twUI.hParent = (TW_HANDLE)m_hMessageWnd; 
		if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_ENABLEDS,(TW_MEMREF)&twUI)) 
		{ 
			m_bSourceEnabled = TRUE; 
			m_bModalUI = twUI.ModalUI; 
		} 
		else 
		{ 
			m_bSourceEnabled = FALSE; 
			m_bModalUI = TRUE; 
		} 
		return m_bSourceEnabled; 
	} 
	return FALSE; 
} 
 
/* 
Called to acquire images from the source. parameter numImages i the 
numberof images that you an handle concurrently 
*/ 
BOOL CTwain::Acquire(int numImages) 
{ 
	if(DSOpen() || OpenSource()) 
	{ 
		if(SetImageCount(numImages)) 
		{ 
			if(EnableSource()) 
			{ 
				return TRUE; 
			} 
		} 
	} 
	return FALSE; 
} 
 
/* 
 Called to disable the source. 
*/ 
BOOL CTwain::DisableSource() 
{ 
	if(SourceEnabled()) 
	{ 
	TW_USERINTERFACE twUI; 
		if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,&twUI)) 
		{ 
			m_bSourceEnabled = FALSE; 
			return TRUE; 
		} 
	} 
	return FALSE; 
} 
 
/* 
Called by ProcessMessage to Translate a TWAIN message 
*/ 
void CTwain::TranslateMessage(TW_EVENT& twEvent) 
{ 
	switch(twEvent.TWMessage) 
	{ 
	case MSG_XFERREADY: 
			TransferImage(); 
			break; 
	case MSG_CLOSEDSREQ: 
			if(CanClose()) 
			{ 
				CloseDS(); 
			} 
			break; 
	} 
} 
 
/* 
Gets Imageinfo for an image which is about to be transferred. 
*/ 
BOOL CTwain::GetImageInfo(TW_IMAGEINFO& info) 
{ 
	if(SourceEnabled()) 
	{ 
		return CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGEINFO,MSG_GET,(TW_MEMREF)&info); 
	} 
	return FALSE; 
} 
 
/* 
Trasnfers the image or cancels the transfer depending on the state of the 
TWAIN system 
*/ 
void CTwain::TransferImage() 
{ 
TW_IMAGEINFO info; 
BOOL bContinue=TRUE; 
	while(bContinue) 
	{ 
		if(GetImageInfo(info)) 
		{ 
			int permission; 
			permission = ShouldTransfer(info); 
			switch(permission) 
			{ 
			case TWCPP_CANCELTHIS: 
					bContinue=EndTransfer(); 
					break; 
			case TWCPP_CANCELALL: 
					CancelTransfer(); 
					bContinue=FALSE; 
					break; 
			case TWCPP_DOTRANSFER: 
					bContinue=GetImage(info); 
					break; 
			} 
		} 
	} 
} 
 
/* 
Ends the current transfer. 
Returns TRUE if the more images are pending 
*/ 
BOOL CTwain::EndTransfer() 
{ 
TW_PENDINGXFERS twPend; 
	if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&twPend)) 
	{ 
		return twPend.Count != 0; 
	} 
	return FALSE; 
} 
 
/* 
Aborts all transfers 
*/ 
void CTwain::CancelTransfer() 
{ 
TW_PENDINGXFERS twPend; 
	CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&twPend); 
} 
 
/* 
Calls TWAIN to actually get the image 
*/ 
BOOL CTwain::GetImage(TW_IMAGEINFO& info) 
{ 
HANDLE hBitmap; 
	CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,&hBitmap); 
	switch(m_returnCode) 
	{ 
	case TWRC_XFERDONE: 
			CopyImage(hBitmap,info); 
			break; 
	case TWRC_CANCEL: 
			break; 
	case TWRC_FAILURE: 
			CancelTransfer(); 
			return FALSE; 
 
	} 
	GlobalFree(hBitmap); 
	return EndTransfer(); 
}