Click here to Skip to main content
15,888,803 members
Articles / Programming Languages / C#

The Paperless Desktop

Rate me:
Please Sign up or sign in to vote.
4.91/5 (83 votes)
5 Apr 20075 min read 416.9K   7K   316  
How to perform scanning, rearranging, OCR and Outlook export of documents for a paperless future - or at least a tidy desktop.
using System;

using System.Collections;
using System.Runtime.InteropServices;
using System.Windows.Forms;

using System.IO;

using System.Drawing;
using System.Drawing.Imaging;

namespace Util.TwainLib
{
	public class Gdip
	{
		private static ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

		private static bool GetCodecClsid( string filename, out Guid clsid )
		{
			clsid = Guid.Empty;
			string ext = Path.GetExtension( filename );
			if( ext == null )
				return false;
			ext = "*" + ext.ToUpper();
			foreach( ImageCodecInfo codec in codecs )
			{
				if( codec.FilenameExtension.IndexOf( ext ) >= 0 )
				{
					clsid = codec.Clsid;
					return true;
				}
			}
			return false;
		}


		public static bool SaveDIBAs( string picname, IntPtr bminfo, IntPtr pixdat )
		{
			SaveFileDialog sd = new SaveFileDialog();

			sd.FileName = picname;
			sd.Title = "Save bitmap as...";
			sd.Filter = "Bitmap file (*.bmp)|*.bmp|TIFF file (*.tif)|*.tif|JPEG file (*.jpg)|*.jpg|PNG file (*.png)|*.png|GIF file (*.gif)|*.gif|All files (*.*)|*.*";
			sd.FilterIndex = 1;
			if( sd.ShowDialog() != DialogResult.OK )
				return false;

			Guid clsid;
			if( ! GetCodecClsid( sd.FileName, out clsid ) )
			{
				MessageBox.Show( "Unknown picture format for extension " + Path.GetExtension( sd.FileName ),
					"Image Codec", MessageBoxButtons.OK, MessageBoxIcon.Information );
				return false;
			}
		
			IntPtr img = IntPtr.Zero;
			int st = GdipCreateBitmapFromGdiDib( bminfo, pixdat, ref img );
			if( (st != 0) || (img == IntPtr.Zero) )
				return false;

			st = GdipSaveImageToFile( img, sd.FileName, ref clsid, IntPtr.Zero );
			GdipDisposeImage( img );
			return st == 0;
		}

	
		public static bool SaveDIB( string picname, IntPtr bminfo, IntPtr pixdat )
		{
			Guid clsid;
			if( ! GetCodecClsid( picname, out clsid ) )
			{
				return false;
			}
		
			IntPtr img = IntPtr.Zero;
			int st = GdipCreateBitmapFromGdiDib( bminfo, pixdat, ref img );
			if( (st != 0) || (img == IntPtr.Zero) )
				return false;

			st = GdipSaveImageToFile( img, picname, ref clsid, IntPtr.Zero );
			GdipDisposeImage( img );
			return st == 0;
		}


		[DllImport("gdiplus.dll", ExactSpelling=true)]
		internal static extern int GdipCreateBitmapFromGdiDib( IntPtr bminfo, IntPtr pixdat, ref IntPtr image );

		[DllImport("gdiplus.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
		internal static extern int GdipSaveImageToFile( IntPtr image, string filename, [In] ref Guid clsid, IntPtr encparams );

		[DllImport("gdiplus.dll", ExactSpelling=true)]
		internal static extern int GdipDisposeImage( IntPtr image );

	}
	


	public class TwProtocol
	{									// TWON_PROTOCOL...
		public const short Major	= 1;
		public const short Minor	= 9;
	}


	[Flags]
	internal enum TwDG : short
	{									// DG_.....
		Control			= 0x0001,
		Image			= 0x0002,
		Audio			= 0x0004
	}

	internal enum TwDAT : short
	{									// DAT_....
		Null			= 0x0000,
		Capability		= 0x0001,
		Event			= 0x0002,
		Identity		= 0x0003,
		Parent			= 0x0004,
		PendingXfers	= 0x0005,
		SetupMemXfer	= 0x0006,
		SetupFileXfer	= 0x0007,
		Status			= 0x0008,
		UserInterface	= 0x0009,
		XferGroup		= 0x000a,
		TwunkIdentity	= 0x000b,
		CustomDSData	= 0x000c,
		DeviceEvent		= 0x000d,
		FileSystem		= 0x000e,
		PassThru		= 0x000f,

		ImageInfo		= 0x0101,
		ImageLayout		= 0x0102,
		ImageMemXfer	= 0x0103,
		ImageNativeXfer	= 0x0104,
		ImageFileXfer	= 0x0105,
		CieColor		= 0x0106,
		GrayResponse	= 0x0107,
		RGBResponse		= 0x0108,
		JpegCompression	= 0x0109,
		Palette8		= 0x010a,
		ExtImageInfo	= 0x010b,

		SetupFileXfer2	= 0x0301
	}

	internal enum TwMSG : short
	{									// MSG_.....
		Null			= 0x0000,
		Get				= 0x0001,
		GetCurrent		= 0x0002,
		GetDefault		= 0x0003,
		GetFirst		= 0x0004,
		GetNext			= 0x0005,
		Set				= 0x0006,
		Reset			= 0x0007,
		QuerySupport	= 0x0008,

		XFerReady		= 0x0101,
		CloseDSReq		= 0x0102,
		CloseDSOK		= 0x0103,
		DeviceEvent		= 0x0104,

		CheckStatus		= 0x0201,

		OpenDSM			= 0x0301,
		CloseDSM		= 0x0302,

		OpenDS			= 0x0401,
		CloseDS			= 0x0402,
		UserSelect		= 0x0403,

		DisableDS		= 0x0501,
		EnableDS		= 0x0502,
		EnableDSUIOnly	= 0x0503,

		ProcessEvent	= 0x0601,

		EndXfer			= 0x0701,
		StopFeeder		= 0x0702,

		ChangeDirectory	= 0x0801,
		CreateDirectory	= 0x0802,
		Delete			= 0x0803,
		FormatMedia		= 0x0804,
		GetClose		= 0x0805,
		GetFirstFile	= 0x0806,
		GetInfo			= 0x0807,
		GetNextFile		= 0x0808,
		Rename			= 0x0809,
		Copy			= 0x080A,
		AutoCaptureDir	= 0x080B,

		PassThru		= 0x0901
	}


	public enum TwRC : short
	{									// TWRC_....
		Success				= 0x0000,
		Failure				= 0x0001,
		CheckStatus			= 0x0002,
		Cancel				= 0x0003,
		DSEvent				= 0x0004,
		NotDSEvent			= 0x0005,
		XferDone			= 0x0006,
		EndOfList			= 0x0007,
		InfoNotSupported	= 0x0008,
		DataNotAvailable	= 0x0009
	}

	internal enum TwCC : short
	{									// TWCC_....
		Success				= 0x0000,
		Bummer				= 0x0001,
		LowMemory			= 0x0002,
		NoDS				= 0x0003,
		MaxConnections		= 0x0004,
		OperationError		= 0x0005,
		BadCap				= 0x0006,
		BadProtocol			= 0x0009,
		BadValue			= 0x000a,
		SeqError			= 0x000b,
		BadDest				= 0x000c,
		CapUnsupported		= 0x000d,
		CapBadOperation		= 0x000e,
		CapSeqError			= 0x000f,
		Denied				= 0x0010,
		FileExists			= 0x0011,
		FileNotFound		= 0x0012,
		NotEmpty			= 0x0013,
		PaperJam			= 0x0014,
		PaperDoubleFeed		= 0x0015,
		FileWriteError		= 0x0016,
		CheckDeviceOnline	= 0x0017
	}

	internal enum TwOn : short
	{									// TWON_....
		Array			= 0x0003,
		Enum			= 0x0004,
		One				= 0x0005,
		Range			= 0x0006,
		DontCare		= -1
	}

	internal enum TwType : short
	{									// TWTY_....
		Int8			= 0x0000,
		Int16			= 0x0001,
		Int32			= 0x0002,
		UInt8			= 0x0003,
		UInt16			= 0x0004,
		UInt32			= 0x0005,
		Bool			= 0x0006,
		Fix32			= 0x0007,
		Frame			= 0x0008,
		Str32			= 0x0009,
		Str64			= 0x000a,
		Str128			= 0x000b,
		Str255			= 0x000c,
		Str1024			= 0x000d,
		Str512			= 0x000e
	}


	internal enum TwCap : short
	{
		XferCount		= 0x0001,			// CAP_XFERCOUNT
		ICompression	= 0x0100,			// ICAP_...
		IPixelType		= 0x0101,
		IUnits			= 0x0102,
		IXferMech		= 0x0103
	}


	[StructLayout(LayoutKind.Sequential, Pack=2, CharSet=CharSet.Ansi)]
	internal class TwIdentity
	{									// TW_IDENTITY
		public IntPtr		Id;
		public TwVersion	Version;
		public short		ProtocolMajor;
		public short		ProtocolMinor;
		public int			SupportedGroups;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=34)]
		public string		Manufacturer;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=34)]
		public string		ProductFamily;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=34)]
		public string		ProductName;
	}

	[StructLayout(LayoutKind.Sequential, Pack=2, CharSet=CharSet.Ansi)]
	internal struct TwVersion
	{									// TW_VERSION
		public short		MajorNum;
		public short		MinorNum;
		public short		Language;
		public short		Country;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=34)]
		public string		Info;
	}

	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal class TwUserInterface
	{									// TW_USERINTERFACE
		public short		ShowUI;				// bool is strictly 32 bit, so use short
		public short		ModalUI;
		public IntPtr		ParentHand;
	}

	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal class TwStatus
	{									// TW_STATUS
		public short		ConditionCode;		// TwCC
		public short		Reserved;
	}

	[StructLayout(LayoutKind.Sequential, Pack=2)]
	public struct TwEvent
	{									// TW_EVENT
		public IntPtr		EventPtr;
		public short		Message;
	}


	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal class TwImageInfo
	{									// TW_IMAGEINFO
		public int			XResolution;
		public int			YResolution;
		public int			ImageWidth;
		public int			ImageLength;
		public short		SamplesPerPixel;
		[MarshalAs( UnmanagedType.ByValArray, SizeConst=8)] 
		public short[]		BitsPerSample;
		public short		BitsPerPixel;
		public short		Planar;
		public short		PixelType;
		public short		Compression;
	}

	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal class TwPendingXfers
	{									// TW_PENDINGXFERS
		public short		Count;
		public int			EOJ;
	}


	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal struct TwFix32
	{												// TW_FIX32
		public short		Whole;
		public ushort		Frac;
	
		public float ToFloat()
		{
			return (float) Whole + ( (float)Frac /65536.0f );
		}
		public void FromFloat( float f )
		{
			int i = (int)((f * 65536.0f) + 0.5f);
			Whole = (short) (i >> 16);
			Frac = (ushort) (i & 0x0000ffff);
		}
	}


	[StructLayout(LayoutKind.Sequential, Pack=2)]
	internal class TwCapability
	{									// TW_CAPABILITY
		public TwCapability( TwCap cap )
		{
			Cap = (short) cap;
			ConType = -1;
		}
		public TwCapability( TwCap cap, short sval )
		{
			Cap = (short) cap;
			ConType = (short) TwOn.One;
			Handle = Twain.GlobalAlloc( 0x42, 6 );
			IntPtr pv = Twain.GlobalLock( Handle );
			Marshal.WriteInt16( pv, 0, (short) TwType.Int16 );
			Marshal.WriteInt32( pv, 2, (int) sval );
			Twain.GlobalUnlock( Handle );
		}
		~TwCapability()
		{
			if( Handle != IntPtr.Zero )
				Twain.GlobalFree( Handle );
		}
		public short		Cap;
		public short		ConType;
		public IntPtr		Handle;
	}



} // namespace TwainLib


namespace Util.TwainLib
{
	public enum TwainCommand
	{
		Not				= -1,
		Null			= 0,
		TransferReady	= 1,
		CloseRequest	= 2,
		CloseOk			= 3,
		DeviceEvent		= 4
	}

	public class TwainCommandClass
	{
		public TwainCommand cmd = TwainCommand.Null;
		public TwRC rc = TwRC.Success;
	}
	public class Twain
	{
		private const short CountryUSA		= 1;
		private const short LanguageUSA		= 13;

		public Twain()
		{
			appid = new TwIdentity();
			appid.Id				= IntPtr.Zero;
			appid.Version.MajorNum	= 1;
			appid.Version.MinorNum	= 1;
			appid.Version.Language	= LanguageUSA;
			appid.Version.Country	= CountryUSA;
			appid.Version.Info		= "Hack 1";
			appid.ProtocolMajor		= TwProtocol.Major;
			appid.ProtocolMinor		= TwProtocol.Minor;
			appid.SupportedGroups	= (int)(TwDG.Image | TwDG.Control);
			appid.Manufacturer		= "NETMaster";
			appid.ProductFamily		= "Freeware";
			appid.ProductName		= "Hack";

			srcds = new TwIdentity();
			srcds.Id = IntPtr.Zero;

			evtmsg.EventPtr = Marshal.AllocHGlobal( Marshal.SizeOf( winmsg ) );
		}

		~Twain()
		{
			Marshal.FreeHGlobal( evtmsg.EventPtr );
		}




		public void Init( IntPtr hwndp )
		{
			//Finish();
			TwRC rc = DSMparent( appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.OpenDSM, ref hwndp );
			if( rc == TwRC.Success )
			{
				rc = DSMident( appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetDefault, srcds );
				if( rc == TwRC.Success )
					hwnd = hwndp;
				else
					rc = DSMparent( appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, ref hwndp );
			}
		}

		public void Select()
		{
			TwRC rc;
			CloseSrc();
			if( appid.Id == IntPtr.Zero )
			{
				Init( hwnd );
				if( appid.Id == IntPtr.Zero )
					return;
			}
			rc = DSMident( appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.UserSelect, srcds );
		}


		public void Acquire(bool showUI, bool modal)
		{
			TwRC rc;
			CloseSrc();
			if( appid.Id == IntPtr.Zero )
			{
				Init( hwnd );
				if( appid.Id == IntPtr.Zero )
					return;
			}
			rc = DSMident( appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.OpenDS, srcds );
			if( rc != TwRC.Success )
				return;

			TwCapability cap = new TwCapability( TwCap.XferCount, -1 );
			rc = DScap( appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, cap );
			if( rc != TwRC.Success )
			{
				CloseSrc();
				return;
			}

			TwUserInterface	guif = new TwUserInterface();
			guif.ShowUI = 1;
			guif.ModalUI = 1;
			if (!showUI) guif.ShowUI = 0;
			if (!modal) guif.ModalUI = 0;
			guif.ParentHand = hwnd;
			rc = DSuserif( appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.EnableDS, guif );
			if( rc != TwRC.Success )
			{
				CloseSrc();
				return;
			}
		}


		public ArrayList TransferPictures()
		{
			try
			{
				ArrayList pics = new ArrayList();
				if( srcds.Id == IntPtr.Zero )
					return pics;

				TwRC rc;
				IntPtr hbitmap = IntPtr.Zero;
				TwPendingXfers pxfr = new TwPendingXfers();
		
				do
				{
					pxfr.Count = 0;
					hbitmap = IntPtr.Zero;

					TwImageInfo	iinf = new TwImageInfo();
					
					rc = DSiinf( appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf );
					if( rc != TwRC.Success )
					{
						CloseSrc();
						return pics;
					}

					rc = DSixfer( appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, ref hbitmap );
					if( rc != TwRC.XferDone )
					{
						CloseSrc();
						return pics;
					}

					rc = DSpxfer( appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr );
					if( rc != TwRC.Success )
					{
						CloseSrc();
						return pics;
					}

					pics.Add( hbitmap );
				}
				while( pxfr.Count != 0 );

				rc = DSpxfer( appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr );
				return pics;
			}
			catch(Exception ee)
			{
				return new ArrayList();
			}
		}


		public TwainCommandClass PassMessage( ref Message m, ref string log)
		{
			TwainCommandClass cl = new TwainCommandClass();

			if( srcds.Id == IntPtr.Zero )
			{
				cl.cmd = TwainCommand.Not;
				return cl;
			}

			int pos = GetMessagePos();

			winmsg.hwnd		= m.HWnd;
			winmsg.message	= m.Msg;
			winmsg.wParam	= m.WParam;
			winmsg.lParam	= m.LParam;
			winmsg.time		= GetMessageTime();
			winmsg.x		= (short) pos;
			winmsg.y		= (short) (pos >> 16);
		
			Marshal.StructureToPtr( winmsg, evtmsg.EventPtr, false );
			evtmsg.Message = 0;
			TwRC rc = DSevent( appid, srcds, TwDG.Control, TwDAT.Event, TwMSG.ProcessEvent, ref evtmsg );

			log += "rc: "+rc.ToString()+"\r\n";
			cl.rc = rc;
			cl.cmd = TwainCommand.Null;
			if( rc == TwRC.NotDSEvent )
			{
				cl.cmd = TwainCommand.Not;
				return cl;
			}
			
			if( evtmsg.Message == (short) TwMSG.XFerReady )
			{
				cl.cmd = TwainCommand.TransferReady;
				return cl;
			}
	
			if( evtmsg.Message == (short) TwMSG.CloseDSReq )
			{
				cl.cmd = TwainCommand.CloseRequest;
				return cl;
			}
	
			if( evtmsg.Message == (short) TwMSG.CloseDSOK )
			{
				cl.cmd = TwainCommand.CloseOk;
				return cl;
			}
		
			if( evtmsg.Message == (short) TwMSG.DeviceEvent )
			{
				cl.cmd = TwainCommand.DeviceEvent;
				return cl;
			}


			return cl;
		}

		public void CloseSrc()
		{
			TwRC rc;
			if( srcds.Id != IntPtr.Zero )
			{
				TwUserInterface	guif = new TwUserInterface();
				rc = DSuserif( appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.DisableDS, guif );
				rc = DSMident( appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.CloseDS, srcds );
			}
		}

		public void Finish()
		{
			TwRC rc;
			CloseSrc();
			if( appid.Id != IntPtr.Zero )
				rc = DSMparent( appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, ref hwnd );
			appid.Id = IntPtr.Zero;
		}

		private IntPtr		hwnd;
		private TwIdentity	appid;
		private TwIdentity	srcds;
		private TwEvent		evtmsg;
		private WINMSG		winmsg;
	


		// ------ DSM entry point DAT_ variants:
		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSMparent( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSMident( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwIdentity idds );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSMstatus( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat );


		// ------ DSM entry point DAT_ variants to DS:
		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSuserif( [In, Out] TwIdentity origin, [In, Out] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, TwUserInterface guif );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSevent( [In, Out] TwIdentity origin, [In, Out] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, ref TwEvent evt );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSstatus( [In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DScap( [In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwCapability capa );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSiinf( [In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwImageInfo imginf );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSixfer( [In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr hbitmap );

		[DllImport("twain_32.dll", EntryPoint="#1")]
		private static extern TwRC DSpxfer( [In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwPendingXfers pxfr );


		[DllImport("kernel32.dll", ExactSpelling=true)]
		internal static extern IntPtr GlobalAlloc( int flags, int size );
		[DllImport("kernel32.dll", ExactSpelling=true)]
		internal static extern IntPtr GlobalLock( IntPtr handle );
		[DllImport("kernel32.dll", ExactSpelling=true)]
		internal static extern bool GlobalUnlock( IntPtr handle );
		[DllImport("kernel32.dll", ExactSpelling=true)]
		internal static extern IntPtr GlobalFree( IntPtr handle );

		[DllImport("user32.dll", ExactSpelling=true)]
		private static extern int GetMessagePos();
		[DllImport("user32.dll", ExactSpelling=true)]
		private static extern int GetMessageTime();


		[DllImport("gdi32.dll", ExactSpelling=true)]
		private static extern int GetDeviceCaps( IntPtr hDC, int nIndex );

		[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
		private static extern IntPtr CreateDC( string szdriver, string szdevice, string szoutput, IntPtr devmode );

		[DllImport("gdi32.dll", ExactSpelling=true)]
		private static extern bool DeleteDC( IntPtr hdc );

		public static int ScreenBitDepth 
		{
			get 
			{
				IntPtr screenDC = CreateDC( "DISPLAY", null, null, IntPtr.Zero );
				int bitDepth = GetDeviceCaps( screenDC, 12 );
				bitDepth *= GetDeviceCaps( screenDC, 14 );
				DeleteDC( screenDC );
				return bitDepth;
			}
		}


		[StructLayout(LayoutKind.Sequential, Pack=4)]
			internal struct WINMSG
		{
			public IntPtr		hwnd;
			public int			message;
			public IntPtr		wParam;
			public IntPtr		lParam;
			public int			time;
			public int			x;
			public int			y;
		}


	} // class Twain
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
CEO Axonic Informationssysteme GmbH, Germany
Germany Germany

Comments and Discussions