CopyData.cs in WebService_WindowsMe


Exporting data read by windows messaging to another windows application via wind...Original Link
    Sponsored links

			
			using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Windows.Forms;
using Manas;

namespace vbAccelerator.Components.Win32
{
	public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);

	/// <summary>
	/// A class which wraps using Windows native WM_COPYDATA
	/// message to send interprocess data between applications.
	/// This is a simple technique for interprocess data sends
	/// using Windows.  The alternative to this is to use
	/// Remoting, which requires a network card and a way
	/// to register the Remoting name of an object so it
	/// can be read by other applications.
	/// </summary>
	public class CopyData : NativeWindow, IDisposable
	{	
		/// <summary>
		/// Event raised when data is received on any of the channels 
		/// this class is subscribed to.
		/// </summary>
		public event DataReceivedEventHandler DataReceived;

		[StructLayout(LayoutKind.Sequential)]
		private struct COPYDATASTRUCT
		{
			public IntPtr dwData;
			public int cbData;
			public IntPtr lpData;
		}
		
		private const int WM_COPYDATA = 0x4A;
		private const int WM_DESTROY = 0x2;

		#region Member Variables
		private CopyDataChannels channels = null;
		private bool disposed = false;
		#endregion

		/// <summary>
		/// Override for a form's Window Procedure to handle WM_COPYDATA
		/// messages sent by other instances of this class.
		/// </summary>
		/// <param name="m">The Windows Message information.</param>
		protected override void WndProc (ref System.Windows.Forms.Message m )
		{
			if (m.Msg == WM_COPYDATA)
			{
				COPYDATASTRUCT cds = new COPYDATASTRUCT();
				cds = (COPYDATASTRUCT) Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
				if (cds.cbData > 0)
				{
					byte[] data = new byte[cds.cbData];		
					Marshal.Copy(cds.lpData, data, 0, cds.cbData);
					MemoryStream stream = new MemoryStream(data);
                    string textData = (new System.Text.ASCIIEncoding()).GetString(data, 0, cds.cbData-1);
                    CopyDataObjectData cdo =  new CopyDataObjectData(textData);
                    DataReceivedEventArgs d = new DataReceivedEventArgs( cdo.Data);
					OnDataReceived(d);
					m.Result = (IntPtr) 1;
				}
			}
			else if (m.Msg == WM_DESTROY)
			{
				// WM_DESTROY fires before OnHandleChanged and is
				// a better place to ensure that we've cleared 
				// everything up.
				channels.OnHandleChange();
				base.OnHandleChange();
			}
			base.WndProc(ref m);
		}

		/// <summary>
		/// Raises the DataReceived event from this class.
		/// </summary>
		/// <param name="e">The data which has been received.</param>
		protected void OnDataReceived(DataReceivedEventArgs e)
		{
			DataReceived(this, e);
		}

		/// <summary>
		/// If the form's handle changes, the properties associated
		/// with the window need to be cleared up. This override ensures
		/// that it is done.  Note that the CopyData class will then
		/// stop responding to events and it should be recreated once
		/// the new handle has been assigned.
		/// </summary>
		protected override void OnHandleChange ()
		{
			// need to clear up everything we had set.
			channels.OnHandleChange();
			base.OnHandleChange();
		}

		/// <summary>
		/// Gets the collection of channels.
		/// </summary>
		public CopyDataChannels Channels
		{
			get
			{
				return this.channels;
			}
		}

		/// <summary>
		/// Clears up any resources associated with this object.
		/// </summary>
		public void Dispose()
		{
			if (!disposed)
			{
				channels.Clear();
				channels = null;
				disposed = true;
				GC.SuppressFinalize(this);
			}
		}

		/// <summary>
		/// Constructs a new instance of the CopyData class
		/// </summary>
		public CopyData()
		{
			channels = new CopyDataChannels(this);
		}

		/// <summary>
		/// Finalises a CopyData class which has not been disposed.
		/// There may be a minor resource leak if this class is finalised
		/// after the form it is associated with.
		/// </summary>
		~CopyData()
		{
			Dispose();
		}
	}

	/// <summary>
	/// Contains data and other information associated with data
	/// which has been sent from another application.
	/// </summary>
	public class DataReceivedEventArgs
	{
		private object data = null;
		
		/// <summary>
		/// Gets the channel name that this data was sent on.
		/// </summary>
		/// <summary>
		/// Gets the data object which was sent.
		/// </summary>
		public Object Data
		{
			get
			{
				return this.data;
			}
		}
		/// <summary>
		/// Constructs an instance of this class.
		/// </summary>
		/// <param name="data">The data which was sent</param>
		internal DataReceivedEventArgs(object data)
		{
			this.data = data;
		}
	}

	/// <summary>
	/// A strongly-typed collection of channels associated with the CopyData
	/// class.
	/// </summary>
	public class CopyDataChannels : DictionaryBase
	{
		private NativeWindow owner = null;

		/// <summary>
		/// Returns an enumerator for each of the CopyDataChannel objects
		/// within this collection.
		/// </summary>
		/// <returns>An enumerator for each of the CopyDataChannel objects
		/// within this collection.</returns>
		public new System.Collections.IEnumerator GetEnumerator (  )
		{
			return this.Dictionary.Values.GetEnumerator();
		}

		/// <summary>
		/// Returns the CopyDataChannel at the specified 0-based index.
		/// </summary>
		public CopyDataChannel this[int index]
		{
			get 
			{
				CopyDataChannel ret = null;
				int i = 0;
				foreach (CopyDataChannel cdc in this.Dictionary.Values)
				{
					i++;
					if (i == index)
					{
						ret = cdc;
						break;
					}
				}
				return ret;
			}
		}
		/// <summary>
		/// Returns the CopyDataChannel for the specified channelName
		/// </summary>
		public CopyDataChannel this[string channelName]
		{
			get
			{
				return (CopyDataChannel) this.Dictionary[channelName];
			}
		}
		/// <summary>
		/// Adds a new channel on which this application can send and
		/// receive messages.
		/// </summary>
		public void Add(string channelName)
		{
			CopyDataChannel cdc = new CopyDataChannel(owner, channelName);
			this.Dictionary.Add(channelName , cdc);
		}
		/// <summary>
		/// Removes an existing channel.
		/// </summary>
		/// <param name="channelName">The channel to remove</param>
		public void Remove(string channelName)
		{
			this.Dictionary.Remove(channelName);
		}
		/// <summary>
		/// Gets/sets whether this channel contains a CopyDataChannel
		/// for the specified channelName.
		/// </summary>
		public bool Contains(string channelName)
		{
			return this.Dictionary.Contains(channelName);
		}

		/// <summary>
		/// Ensures the resources associated with a CopyDataChannel
		/// object collected by this class are cleared up.
		/// </summary>
		protected override void OnClear()
		{
			foreach (CopyDataChannel cdc in this.Dictionary.Values)
			{
				cdc.Dispose();
			}
			base.OnClear();
		}

		/// <summary>
		/// Ensures any resoures associated with the CopyDataChannel object
		/// which has been removed are cleared up.
		/// </summary>
		/// <param name="key">The channelName</param>
		/// <param name="data">The CopyDataChannel object which has
		/// just been removed</param>
		protected override void OnRemoveComplete ( Object key , System.Object data )
		{
			( (CopyDataChannel) data).Dispose();
			base.OnRemove(key, data);
		}

		/// <summary>
		/// If the form's handle changes, the properties associated
		/// with the window need to be cleared up. This override ensures
		/// that it is done.  Note that the CopyData class will then
		/// stop responding to events and it should be recreated once
		/// the new handle has been assigned.
		/// </summary>
		public void OnHandleChange()
		{
			foreach (CopyDataChannel cdc in this.Dictionary.Values)
			{
				cdc.OnHandleChange();
			}
		}
		
		/// <summary>
		/// Constructs a new instance of the CopyDataChannels collection.
		/// Automatically managed by the CopyData class.
		/// </summary>
		/// <param name="owner">The NativeWindow this collection
		/// will be associated with</param>
		internal CopyDataChannels(NativeWindow owner)
		{
			this.owner = owner;
		}
	}

	/// <summary>
	/// A channel on which messages can be sent.
	/// </summary>
	public class CopyDataChannel : IDisposable
	{
		#region Unmanaged Code
		[DllImport("user32", CharSet=CharSet.Auto)]
		private extern static int GetProp(
			IntPtr hwnd , 
			string lpString);
		[DllImport("user32", CharSet=CharSet.Auto)]
		private extern static int SetProp(
			IntPtr hwnd , 
			string lpString, 
			int hData);
		[DllImport("user32", CharSet=CharSet.Auto)]
		private extern static int RemoveProp(
			IntPtr hwnd, 
			string lpString);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

		[DllImport("user32", CharSet=CharSet.Auto)]
		private extern static int SendMessage(
			IntPtr hwnd, 
			int wMsg, 
			int wParam, 				
			ref COPYDATASTRUCT lParam
			);

		[StructLayout(LayoutKind.Sequential)]
		private struct COPYDATASTRUCT
		{
			public IntPtr dwData;
			public int cbData;
			public IntPtr lpData;
		}
		
		private const int WM_COPYDATA = 0x4A;
		#endregion

		#region Member Variables
		private string channelName = "";
        private IntPtr receiverHandle = (IntPtr)0;
        private bool disposed = false;
		private NativeWindow owner = null;
		#endregion

		/// <summary>
		/// Gets the name associated with this channel.
		/// </summary>
		public string ChannelName
		{
			get
			{
				return this.channelName;
			}
		}

        public IntPtr ReceiverHandle        
        {	
            get {return receiverHandle;}	
            set {receiverHandle = value;}		
        }


		/// <summary>
		/// Sends the specified object on this channel to any other
		/// applications which are listening.  The object must have the
		/// SerializableAttribute set, or must implement ISerializable.
		/// </summary>
		/// <param name="obj">The object to send</param>
		/// <returns>The number of recipients</returns>

        public int SendString(string str)
        {
            return SendString(this.receiverHandle, str,0);
        }

        public int SendString(string str,int dataType)
        {
            return SendString(this.receiverHandle, str, dataType);
        }

        public int SendString(IntPtr receiverHandle, string str, int dataType)
		{
            int recipients = 0;
           
            /*
            Encoding enc = Encoding.Unicode;
            //the exact byte count.
            int iBC = enc.GetByteCount((string)str);
            //the maximum byte count.
            int iMBC = enc.GetMaxByteCount(((string)str).Length);
            // Encode the entire string.
            byte[] data = enc.GetBytes((string)str);

            //Allocate enough memory space and return its starting point
            IntPtr ptrData = Marshal.AllocCoTaskMem(iMBC);

            // Now move the data into a pointer so we can send
            Marshal.Copy(data, 0, ptrData, iMBC - 2);
           */

            str = Utilities.EncodeTurkishChars(str);
            Encoding enc = Encoding.ASCII;
            //the exact byte count.
            int iBC = enc.GetByteCount((string)str);
            //the maximum byte count.
            int iMBC = enc.GetMaxByteCount(((string)str).Length);
            // Encode the entire string.
            byte[] data = enc.GetBytes((string)str);

            //Allocate enough memory space and return its starting point
            IntPtr ptrData = Marshal.AllocCoTaskMem(iMBC);

            // Now move the data into a pointer so we can send
            Marshal.Copy(data, 0, ptrData, iMBC - 1);

            // it using WM_COPYDATA:
			// Get the length of the data:
        	// This isn't very efficient if your data is very large.
			// First we copy to a byte array, then copy to a CoTask 
			// Mem object... And when we use WM_COPYDATA windows will
			// make yet another copy!  But if you're talking about 4K
			// or less of data then it doesn't really matter.
			
	        if (receiverHandle.ToInt64() > 0)
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                //cds.cbData = iMBC-2;  //unicode
                cds.cbData = iMBC - 1;  //ascii
                cds.dwData = (IntPtr)dataType;
                cds.lpData = ptrData;
                int res = SendMessage(receiverHandle, WM_COPYDATA, (int)owner.Handle, ref cds);
                recipients += (Marshal.GetLastWin32Error() == 0 ? 1 : 0);
            }
			
            // Clear up the data:
			Marshal.FreeCoTaskMem(ptrData);
		
			return recipients;
		}

		private void addChannel()
		{
			// Tag this window with property "channelName"
			//SetProp(owner.Handle, this.channelName, (int)owner.Handle);

		}
		private void removeChannel()
		{
			// Remove the "channelName" property from this window
			RemoveProp(owner.Handle, this.channelName);
		}

		/// <summary>
		/// If the form's handle changes, the properties associated
		/// with the window need to be cleared up. This method ensures
		/// that it is done.  Note that the CopyData class will then
		/// stop responding to events and it should be recreated once
		/// the new handle has been assigned.
		/// </summary>
		public void OnHandleChange()
		{
			removeChannel();
		}

		/// <summary>
		/// Clears up any resources associated with this channel.
		/// </summary>
		public void Dispose()
		{
			if (!disposed)
			{
				if (channelName.Length > 0)
				{
					removeChannel();
				}
				channelName = "";
				disposed = true;
				GC.SuppressFinalize(this);
			}
		}

		/// <summary>
		/// Constructs a new instance of a CopyData channel.  Called
		/// automatically by the CopyDataChannels collection.
		/// </summary>
		/// <param name="owner">The owning native window</param>
		/// <param name="channelName">The name of the channel to
		/// send messages on</param>
		internal CopyDataChannel(NativeWindow owner, string channelName)
		{
			this.owner = owner;
			this.channelName = channelName;
			addChannel();
		}

		~CopyDataChannel()
		{
			Dispose();
		}
	}

	/// <summary>
	/// A class which wraps the data being copied, used
	/// internally within the CopyData class objects.
	/// </summary>
	[Serializable()]
	internal class CopyDataObjectData
	{
		/// <summary>
		/// The Object to copy.  Must be Serializable.
		/// </summary>
		public object Data;
		
		/// <summary>
		/// Constructs a new instance of this object
		/// </summary>
		/// <param name="data">The data to copy</param>
		public CopyDataObjectData(object data)
		{
			Data = data;
		}
	}

}
			click here to download the whole source code package.

			
			


Project Files

    Sponsored links
NameSizeDate
 01.00 B
 01.00 B
 Project1.cfg353.00 B02-08-08 12:57
 Project1.dof1.90 kB02-08-08 12:57
 Project1.dpr188.00 B02-08-08 12:57
 Project1.exe423.00 kB02-08-08 16:15
 Project1.res876.00 B02-08-08 12:56
 Unit1.dcu7.97 kB02-08-08 16:15
 Unit1.ddp51.00 B02-08-08 16:15
 Unit1.dfm1.01 kB02-08-08 16:11
 Unit1.pas3.60 kB02-08-08 16:15
 Unit1.~ddp51.00 B02-08-08 16:12
 Unit1.~dfm1.01 kB02-08-08 16:11
 Unit1.~pas3.70 kB02-08-08 16:12
 WebServiceInterface.exe128.00 kB02-08-08 16:05
 WebServiceInterface.exe.config894.00 B02-08-08 14:44
 WebServiceInterface.pdb309.50 kB02-08-08 16:05
 WebServiceInterface.vshost.exe5.50 kB09-23-05 07:56
 WebServiceInterface.vshost.exe.config894.00 B02-08-08 14:44
 01.00 B
 app.config894.00 B02-08-08 14:44
 01.00 B
 01.00 B
 WebServis2ElTerminali.exe168.00 kB02-08-08 12:44
 WebServis2ElTerminali.exe.config1.11 kB02-08-08 11:44
 WebServis2ElTerminali.pdb347.50 kB02-08-08 12:44
 WebServis2ElTerminali.vshost.exe.config943.00 B07-19-06 17:16
 CopyData.cs14.90 kB02-08-08 14:59
 DataClass1.cs1.12 kB06-08-06 17:12
 EnumWindows.cs13.01 kB06-08-06 17:08
 Frm_KPS.cs11.29 kB02-08-08 16:05
 Frm_KPS.Designer.cs3.65 kB02-08-08 14:58
 Frm_KPS.resx5.68 kB02-08-08 14:58
 01.00 B
 01.00 B
 012.00 B
 ResolveAssemblyReference.cache7.65 kB02-08-08 11:47
 01.00 B
 Properties.Resources.Designer.cs.dll5.50 kB02-08-08 14:21
 Web40.00 kB02-08-08 14:21
 Web108.00 kB02-08-08 14:29
 Web32.00 kB06-10-06 10:22
 WebServiceInterface.csproj.GenerateResource.Cache920.00 B02-08-08 14:59
 WebServiceInterface.exe128.00 kB02-08-08 16:05
 WebServiceInterface.Frm_KPS.resources180.00 B02-08-08 14:59
 WebServiceInterface.pdb309.50 kB02-08-08 16:05
 WebServiceInterface.Properties.Resources.resources180.00 B02-08-08 14:10
 WebServis2ElTerminali.csproj.GenerateResource.Cache920.00 B02-08-08 12:08
 WebServiceInterface.csproj.FileListAbsolute.txt1.64 kB02-08-08 16:05
 WebServis2ElTerminali.csproj.FileList.txt428.00 B10-30-06 16:41
 WebServis2ElTerminali.csproj.FileListAbsolute.txt1.19 kB02-08-08 13:20
 Program.cs488.00 B02-08-08 14:12
 01.00 B
 AssemblyInfo.cs1.26 kB02-08-08 14:33
 Resources.Designer.cs2.80 kB02-08-08 14:08
 Resources.resx5.48 kB06-10-06 10:19
 Settings.Designer.cs1.64 kB02-08-08 14:44
 Settings.settings507.00 B02-08-08 14:44
 Utilities.cs6.49 kB02-08-08 14:18
 <Web>0.00 B01-02-09 16:33
 <Web>0.00 B01-02-09 16:33
 Web637.00 B02-08-08 14:21
 Web651.00 B02-08-08 14:21
 Web629.00 B02-08-08 14:21
 Web631.00 B02-08-08 14:21
 Web647.00 B02-08-08 14:21
 Web629.00 B02-08-08 14:21
 Web651.00 B02-08-08 14:21
 Web631.00 B02-08-08 14:21
 Web635.00 B02-08-08 14:21
 Web637.00 B02-08-08 14:21
 Web639.00 B02-08-08 14:21
 Web645.00 B02-08-08 14:21
 Web663.00 B02-08-08 14:21
 Web637.00 B02-08-08 14:21
 Web639.00 B02-08-08 14:21
 Web745.00 B02-08-08 14:21
 Web104.22 kB02-08-08 14:21
 Web637.00 B02-08-08 14:21
 Web653.00 B02-08-08 14:21
 Web647.00 B02-08-08 14:21
 Web639.00 B02-08-08 14:21
 Web645.00 B02-08-08 14:21
 Web205.96 kB02-08-08 14:29
 Web588.00 B02-08-08 14:21
 Web651.00 B02-08-08 14:21
 WebServiceInterface.csproj7.66 kB02-08-08 14:44
 WebServiceInterface.idc634.00 B02-08-08 11:46
 WebServiceInterface.sln926.00 B02-08-08 14:29
 WebServiceInterface.suo36.50 kB02-08-08 15:56
...

Related Items

    Sponsored links