www.pudn.com > CFPrinterClass_src.rar > CommDev.cs, change:2004-04-05,size:10733b


using System; 
using System.Threading; 
using System.Runtime.InteropServices; 
 
namespace CFPrinting 
{ 
	// ' *-----------------------------------------* 
	// * Mobile COM Device (.NET CF)				* 
	// * Author : Orkun Gedik						* 
	// * e-mail : orkun.gedik@astron.yasar.com.tr	* 
	// ' *-----------------------------------------* 
	public class CommDevice 
	{ 
		// Comm events 
		private enum EventFlags : uint 
		{ 
			NONE        = 0x0000, // 
			RXCHAR      = 0x0001, // Any Character received 
			RXFLAG      = 0x0002, // Received specified flag character 
			TXEMPTY     = 0x0004, // Tx buffer Empty 
			CTS         = 0x0008, // CTS changed 
			DSR         = 0x0010, // DSR changed 
			RLSD        = 0x0020, // RLSD changed 
			BREAK       = 0x0040, // BREAK received 
			ERR         = 0x0080, // Line status error 
			RING        = 0x0100, // ring detected 
			PERR        = 0x0200, // printer error 
			RX80FULL    = 0x0400, // rx buffer is at 80% 
			EVENT1      = 0x0800, // provider event 
			EVENT2      = 0x1000, // provider event 
			POWER       = 0x2000, // wince power notification 
			ALL			= 0x3FFF  // mask of all flags  
		} 
 
		// Device control block structure 
		private class DeviceControlBlock 
		{ 
			public uint BaudRate; 
			public byte Size; 
			public byte Parity; 
			public byte StopBits; 
		} 
 
		// Comm timeout 
		private class CommTimeout 
		{ 
			public UInt32 ReadIntervalTimeout; 
			public UInt32 ReadTotalTimeoutMultiplier; 
			public UInt32 ReadTotalTimeoutConstant; 
			public UInt32 WriteTotalTimeoutMultiplier; 
			public UInt32 WriteTotalTimeoutConstant; 
		} 
 
		// Flags 
		private enum Flags 
		{ 
			EVENT_PULSE     = 1, 
			EVENT_RESET     = 2, 
			EVENT_SET       = 3 
		} 
		#region API declarations 
			// CECreateFileW 
			[DllImport("coredll.dll", EntryPoint="CreateFileW", SetLastError = true)] 
			private static extern IntPtr CECreateFileW( 
				String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode, 
				IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes, 
				IntPtr hTemplateFile); 
			// CESetupComm 
			[DllImport("coredll.dll", EntryPoint="SetupComm", SetLastError = true)] 
			private static extern int CESetupComm(IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue); 
			// CEWriteFile 
			[DllImport("coredll.dll", EntryPoint="WriteFile", SetLastError = true)] 
			private static extern int CEWriteFile(IntPtr hFile, byte[] lpBuffer, UInt32 nNumberOfBytesToRead, ref Int32 lpNumberOfBytesRead, IntPtr lpOverlapped);	 
			// CESetCommMask 
			[DllImport("coredll.dll", EntryPoint="SetCommMask", SetLastError = true)] 
			private static extern int CESetCommMask(IntPtr handle, EventFlags dwEvtMask); 
			// CESetCommState 
			[DllImport("coredll.dll", EntryPoint="SetCommState", SetLastError = true)] 
			private static extern int CESetCommState(IntPtr hFile, DeviceControlBlock dcb); 
			// CESetCommTimeouts 
			[DllImport("coredll.dll", EntryPoint="SetCommTimeouts", SetLastError = true)] 
			private static extern int CESetCommTimeouts(IntPtr hFile, CommTimeout timeouts); 
			// CEWaitCommEvent 
			[DllImport("coredll.dll", EntryPoint="WaitCommEvent", SetLastError = true)] 
			private static extern int CEWaitCommEvent(IntPtr hFile, ref EventFlags lpEvtMask, IntPtr lpOverlapped); 
			// CEGetCommModemStatus 
			[DllImport("coredll.dll", EntryPoint="GetCommModemStatus", SetLastError = true)] 
			extern private static int CEGetCommModemStatus(IntPtr hFile, ref uint lpModemStat); 
			// CECloseHandle 
			[DllImport("coredll.dll", EntryPoint="CloseHandle", SetLastError = true)] 
			private static extern int CECloseHandle(IntPtr hObject); 
			// CEWaitForSingleObject 
			[DllImport("coredll.dll", EntryPoint="WaitForSingleObject", SetLastError = true)] 
			private static extern int CEWaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); 
			// CEEventModify 
			[DllImport("coredll.dll", EntryPoint="EventModify", SetLastError = true)] 
			private static extern int CEEventModify(IntPtr hEvent, uint function);  
			//CECreateEvent 
			[DllImport("coredll.dll", EntryPoint="CreateEvent", SetLastError = true)] 
			private static extern IntPtr CECreateEvent(IntPtr lpEventAttributes, int bManualReset, int bInitialState, string lpName);  
		#endregion 
		private string sPort; // COM port# 
		private IntPtr hPort; // COM port handler 
		private uint iTransmitBufferSize; // Transmit buffer size 
		private uint Acctype; // Access type to COM port 
		private byte[] bTransmitBuffer; // Transmit buffer 
		private const UInt32 EXISTING = 3; // Open existing port 
		private const UInt32 WRITE = 0x40000000; // write only 
		private const Int32 INVALID_HANDLE = -1; // Thread exit value 
		private const Int32 PACKAGE_SIZE = 1024; // Packet size 
		private const string ClosePortEventName = "ClosePort"; // Event name 
		private IntPtr ClosePortEvent; // Event handle		 
		private ManualResetEvent ThreadEvent = new ManualResetEvent(false); // Thread event 
		private CommTimeout commTimeout; // time out 
		private DeviceControlBlock dcb;	// Device control block 
 
		// Constructor 
		public CommDevice() 
		{ 
			// Set max transmit & receive buffer sizes 
			iTransmitBufferSize = PACKAGE_SIZE; 
 
			// Create instance for device control block and set values 
			dcb = new DeviceControlBlock(); 
			dcb.BaudRate = 9600; 
			dcb.Size = 8; 
			dcb.Parity = 0; 
			dcb.StopBits = 0; 
 
			// Access type 
			Acctype = WRITE; 
 
			// Reset close event value 
			ClosePortEvent = IntPtr.Zero; 
 
			// Set buffer area for transmit & receive data 
			bTransmitBuffer = new byte[iTransmitBufferSize]; 
 
			// Create event 
			ClosePortEvent = CECreateEvent(IntPtr.Zero, Convert.ToInt32(true), Convert.ToInt32(false), ClosePortEventName); 
		} 
 
		// Open COM port 
		private IntPtr OpenPort() 
		{ 
			if(sPort.Length!=0) 
			{ 
				// Open COM port 
				hPort=CECreateFileW(sPort,  
					Acctype, 
					0, 
					IntPtr.Zero, 
					EXISTING, 
					0, 
					IntPtr.Zero); 
			} 
			else 
			{ 
				// Port number has not been specified 
				hPort=IntPtr.Zero; 
			} 
			return(hPort); 
		} 
 
		// Setup comm 
		private void SetupComm() 
		{ 
			// Set buffer sizes 
			CESetupComm(hPort,  
						0,  
						iTransmitBufferSize); 
		} 
 
		// Set timeout 
		private void SetConnectionTimeOut() 
		{ 
			// Create comm timeout instance 
			commTimeout = new CommTimeout(); 
 
			commTimeout.ReadIntervalTimeout = uint.MaxValue; // Read interval 
			commTimeout.ReadTotalTimeoutConstant = 0; // 0 Seconds for write 
			commTimeout.ReadTotalTimeoutMultiplier = 0; // 0 Seconds for write 
			commTimeout.WriteTotalTimeoutConstant = 5; // 5 Seconds for write 
			commTimeout.WriteTotalTimeoutMultiplier = 0; // 0 Seconds for write 
		} 
 
		// Set DCB 
		private void SetDCB() 
		{ 
			// Set device control block 
			CESetCommState(hPort, 
							dcb); 
		} 
 
		// Create thread 
		private void CreateCommThread() 
		{ 
			// Create thread 
			Thread eventThread = new Thread(new ThreadStart(CommThread)); 
			// Set priority 
			eventThread.Priority = ThreadPriority.AboveNormal; 
			// Start now 
			eventThread.Start(); 
			// Set wait event 
			ThreadEvent.WaitOne(); 
		} 
		// Public initialization method 
		public void Init() 
		{ 
			// Initialize COM port 
			hPort=OpenPort(); // Open COM port 
			SetupComm(); // Set buffer size 
			SetDCB(); // Device control block 
			SetConnectionTimeOut(); // Timeout settings 
			CreateCommThread(); // Create & begin thread 
		} 
		// Send data to COM port (char array) 
		public void Send(char[,] Data) 
		{			 
			int iXPos=0; // Row 
			int iYPos=0; // Column 
			int iXBound=0; // X 
			int iYBound=0; // Y 
			int iCounter=0; // Byte counter 
			int iTotalCounter=0; // Total count						 
			int iIndex; // Clear Output 
			int iNumberOfBytesRead=0; 
			uint iNumberOfBytesToRead=PACKAGE_SIZE; 
			byte[] Output = new byte[PACKAGE_SIZE]; // Package 
 
			// Get bounds 
			iYBound=(Data.GetUpperBound(0))+1; 
			iXBound=(Data.GetUpperBound(1))+1; 
 
			// Parse & locate the data into byte array 
			for(iYPos=0;iYPos!=iYBound;iYPos++) 
			{ 
				// Row loop 
				for(iXPos=0;iXPos!=iXBound;iXPos++) 
				{ 
					// Insert data into buffer 
					if(0!=(byte)(Data[iYPos, iXPos])) 
						Output[iCounter]=(byte)(Data[iYPos, iXPos]); // char 
					else 
						Output[iCounter]=0x20; // Space character 
					iCounter++; // 1024 bytes 
					iTotalCounter++; // As a whole document 
					// Column loop 
					if(iCounter==PACKAGE_SIZE || iTotalCounter==(iXBound*iYBound)) // Check package size 
					{ 
						// Send data to COM port 
						CEWriteFile(hPort, Output, iNumberOfBytesToRead, ref iNumberOfBytesRead, IntPtr.Zero); 
						// Clear package 
						iCounter=0; 
						for(iIndex=0;iIndex!=PACKAGE_SIZE;iIndex++) 
							Output[iIndex]=0x0; 
					} 
				} 
				Output[iCounter]=0xD; 
				iCounter++; // 1024 bytes 
				Output[iCounter]=0xA; 
				iCounter++; // 1024 bytes 
			} 
 
			// Dispose value 
			Output=null; 
 
			// Call gc 
			GC.Collect(); 
		} 
		// Send data to COM port (byte) 
		public void Send(byte Data) 
		{ 
			// Send a byte 
			byte[] Output=new byte[1]; 
			uint iNumberOfBytesToRead=1; 
			int iNumberOfBytesRead=0; 
 
			// Send data 
			Output[0]=Data; 
			CEWriteFile(hPort, Output, iNumberOfBytesToRead, ref iNumberOfBytesRead, IntPtr.Zero); 
 
			// Dispose value 
			Output=null; 
 
			// Call gc 
			GC.Collect(); 
		} 
		// Close port 
		public void ClosePort() 
		{ 
			if(Convert.ToBoolean(CECloseHandle(hPort))) 
			{ 
				hPort = (IntPtr)INVALID_HANDLE; 
				CEEventModify(ClosePortEvent, (uint)Flags.EVENT_SET); 
			} 
		} 
		// Dispose 
		public void Dispose() 
		{		 
			bTransmitBuffer = null; 
			commTimeout = null; 
			ThreadEvent = null; 
		} 
		// Properties 
 
		// Port# 
		public string Port 
		{ 
			get 
			{ 
				return(sPort); 
			} 
			set 
			{ 
				sPort=value; 
			} 
		} 
		// Baud 
		public uint BaudRate 
		{ 
			get 
			{ 
				return(dcb.BaudRate); 
			} 
		} 
		// Parity 
		public int Parity 
		{ 
			get 
			{ 
				return(dcb.Parity); 
			} 
		} 
 
		// Threading method 
		private void CommThread() 
		{ 
			EventFlags commEvents = new EventFlags(); 
 
			// Monitor events 
			CESetCommMask(hPort, EventFlags.ALL); 
 
			try 
			{ 
				// Thread has been started 
				ThreadEvent.Set(); 
 
				// Wait for new event 
				while(hPort!=(IntPtr)INVALID_HANDLE) 
				{ 
					if(!Convert.ToBoolean(CEWaitCommEvent(hPort, ref commEvents, IntPtr.Zero))) 
					{ 
						CEWaitForSingleObject(ClosePortEvent, 1000); 
						ThreadEvent.Reset(); 
						return; 
					} 
					CESetCommMask(hPort, EventFlags.ALL); 
				} 
			} 
			catch(Exception e) 
			{ 
				throw e; 
			} 
		} 
	} 
}