initial checkin of yaulw (locally)
This commit is contained in:
321
Win32/AtomMessenger.cs
Normal file
321
Win32/AtomMessenger.cs
Normal file
@@ -0,0 +1,321 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Yaulw.Win32
|
||||
{
|
||||
/// <remarks>
|
||||
/// Quick and Easy Atom Window Messages Communication between windows of different
|
||||
/// Processes.
|
||||
/// </remarks>
|
||||
public class AtomMessenger : IDisposable
|
||||
{
|
||||
#region Private Members
|
||||
private const string _AtomMsgIDFormat = "AtomMsgID-[{0}]";
|
||||
private string _AtomMsgStr = "";
|
||||
private uint _AtomMsg = 0;
|
||||
private bool _disposed = false;
|
||||
|
||||
// For Posted Atom Messages
|
||||
private const int MAGIC_NUMBER_POSTED_ATOM_KEYS = 7;
|
||||
private List<uint> _postedAtomKeys = new List<uint>();
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Create an Atom Messaging Component with a Unique Identifier.
|
||||
/// The same Identifier should be used by all applications that want to pass
|
||||
/// Messages back and forth.
|
||||
/// ~You need to dispose of this Object only if you plan on using PostAtomMessage()
|
||||
/// </summary>
|
||||
/// <param name="UniqueWindowMessageIdentifier">An identifier for the Messaging</param>
|
||||
public AtomMessenger(Guid UniqueWindowMessageIdentifier)
|
||||
{
|
||||
if (UniqueWindowMessageIdentifier == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
// Register the Unique Window Message
|
||||
_AtomMsgStr = String.Format(_AtomMsgIDFormat, UniqueWindowMessageIdentifier);
|
||||
_AtomMsg = User32.RegisterWindowMessage(_AtomMsgStr);
|
||||
if (_AtomMsg == 0)
|
||||
throw new Exception("RegisterWindowMessage Failed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~AtomMessenger()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Atom Message Construction Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve ';' seperated values from an Atom Message
|
||||
/// </summary>
|
||||
/// <param name="AtomMessage">an atom message that contains multiple args</param>
|
||||
/// <returns>multiple args</returns>
|
||||
public string[] RetrieveMultipleValuesFromAtomMessage(string AtomMessage)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(AtomMessage))
|
||||
return AtomMessage.Split(';');
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create ';' seperated Atom message from multiple values
|
||||
/// </summary>
|
||||
/// <returns>an Atom Message containing multiple args</returns>
|
||||
public string SetMultipleValueInAtomMessage(params object[] args)
|
||||
{
|
||||
if (args != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (object a in args)
|
||||
{
|
||||
sb.Append(a.ToString());
|
||||
sb.Append(";");
|
||||
}
|
||||
|
||||
// Remove Trailing ";"
|
||||
sb = sb.Remove(sb.Length - 1, 1);
|
||||
return sb.ToString();
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Atom Message Identify / Retrieval
|
||||
|
||||
/// <summary>
|
||||
/// Use this to check if the passed in Message is an Atom Message.
|
||||
/// The identifier of the Message must match the Message registered with the UniqueIdentifier
|
||||
/// </summary>
|
||||
/// <param name="m">a Windows.Forms Message</param>
|
||||
/// <returns>true if the Messages matches the one created by the UniqueIdentifier</returns>
|
||||
public bool IsAtomMessage(ref Message m)
|
||||
{
|
||||
return (m.Msg == _AtomMsg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the values passed in by an Atom Message
|
||||
/// </summary>
|
||||
/// <param name="m">a Windows.Forms Message</param>
|
||||
/// <param name="AtomMessage">the Message Retrieved from the Atom</param>
|
||||
/// <param name="hWndSrc">the source window who send it, if valid</param>
|
||||
public void GetAtomMessageValues(ref Message m, out string AtomMessage, out IntPtr hWndSrc)
|
||||
{
|
||||
AtomMessage = String.Empty;
|
||||
hWndSrc = IntPtr.Zero;
|
||||
|
||||
// Check to make sure this is an Atom Message
|
||||
if (!IsAtomMessage(ref m))
|
||||
return;
|
||||
|
||||
// Source is passed to us by wParam
|
||||
if(m.WParam != IntPtr.Zero && User32.IsWindow(m.WParam))
|
||||
hWndSrc = m.WParam;
|
||||
|
||||
// Now retrieve the Atom Message
|
||||
StringBuilder sb = new StringBuilder( 254 );
|
||||
uint AtomKey = (uint) m.LParam;
|
||||
uint slen = Kernel32.GlobalGetAtomName(AtomKey, sb, 254);
|
||||
if (slen == 0)
|
||||
return;
|
||||
|
||||
// Write out Retrieved Message
|
||||
AtomMessage = sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the values passed in by an Atom Message
|
||||
/// </summary>
|
||||
/// <param name="m">a Windows.Forms Message</param>
|
||||
/// <param name="AtomMessage">the Message with multiple values retrieved from the Atom</param>
|
||||
/// <param name="hWndSrc">the source window who send it, if valid</param>
|
||||
public void GetAtomMessageValues(ref Message m, out string[] AtomMessage, out IntPtr hWndSrc)
|
||||
{
|
||||
AtomMessage = null;
|
||||
hWndSrc = IntPtr.Zero;
|
||||
|
||||
// Check to make sure this is an Atom Message
|
||||
if (!IsAtomMessage(ref m))
|
||||
return;
|
||||
|
||||
// Source is passed to us by wParam
|
||||
if (m.WParam != IntPtr.Zero && User32.IsWindow(m.WParam))
|
||||
hWndSrc = m.WParam;
|
||||
|
||||
// Now retrieve the Atom Message
|
||||
StringBuilder sb = new StringBuilder(254);
|
||||
uint AtomKey = (uint)m.LParam;
|
||||
uint slen = Kernel32.GlobalGetAtomName(AtomKey, sb, 254);
|
||||
if (slen == 0)
|
||||
return;
|
||||
|
||||
// Write out Retrieved Message
|
||||
AtomMessage = RetrieveMultipleValuesFromAtomMessage(sb.ToString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Send/Post Atom Message
|
||||
|
||||
/// <summary>
|
||||
/// Sends an Atom Message To the Specified Window or All Windows
|
||||
/// </summary>
|
||||
/// <param name="hWndSrc">Sender Windows (Nice to have), in case Receiver Needs it</param>
|
||||
/// <param name="hWndDst">Can be IntPtr.Zero to BroadCast the Message, otherwise specify window to send to</param>
|
||||
/// <param name="AtomMessage">The Message to Send * Can not be longer than 254 chars *</param>
|
||||
public void SendAtomMessage(IntPtr hWndSrc, IntPtr hWndDst, string AtomMessage)
|
||||
{
|
||||
// Is Broadcast?
|
||||
bool bBroadcast = (hWndDst==IntPtr.Zero);
|
||||
|
||||
// Check to make sure Atom Message is proper
|
||||
if(String.IsNullOrEmpty(AtomMessage) || AtomMessage.Length > 254)
|
||||
throw new ArgumentException("AtomMessage Invalid");
|
||||
|
||||
// Register Atom
|
||||
uint AtomKey = Kernel32.GlobalAddAtom(AtomMessage);
|
||||
if (AtomKey == 0)
|
||||
throw new Exception("GlobalAddAtom Failed");
|
||||
|
||||
// Send the Message
|
||||
if(bBroadcast)
|
||||
User32.SendMessage(Definitions.HWND_BROADCAST, (int)_AtomMsg, hWndSrc, (IntPtr)AtomKey);
|
||||
else
|
||||
User32.SendMessage(hWndDst, (int)_AtomMsg, hWndSrc, (IntPtr)AtomKey);
|
||||
|
||||
// We are done with the Atom
|
||||
Kernel32.GlobalDeleteAtom(AtomKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an Atom Message To the Specified Window or All Windows
|
||||
/// </summary>
|
||||
/// <param name="hWndSrc">Sender Windows (Nice to have), in case Receiver Needs it</param>
|
||||
/// <param name="hWndDst">Can be IntPtr.Zero to BroadCast the Message, otherwise specify window to send to</param>
|
||||
/// <param name="AtomMessage">The Message to Send that has multiple values * Total string can not be longer than 254 chars *</param>
|
||||
public void SendAtomMessage(IntPtr hWndSrc, IntPtr hWndDst, string[] AtomMessage)
|
||||
{
|
||||
SendAtomMessage(hWndSrc, hWndDst, SetMultipleValueInAtomMessage(AtomMessage));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post an Atom Message To the Specified Window or All Windows
|
||||
/// </summary>
|
||||
/// <param name="hWndSrc">Sender Windows (Nice to have), in case Receiver Needs it</param>
|
||||
/// <param name="hWndDst">Can be IntPtr.Zero to BroadCast the Message, otherwise specify window to send to</param>
|
||||
/// <param name="AtomMessage">The Message to Send * Can not be longer than 254 chars *</param>
|
||||
public void PostAtomMessage(IntPtr hWndSrc, IntPtr hWndDst, string AtomMessage)
|
||||
{
|
||||
// Is Broadcast?
|
||||
bool bBroadcast = (hWndDst == IntPtr.Zero);
|
||||
|
||||
// Check to make sure Atom Message is proper
|
||||
if (String.IsNullOrEmpty(AtomMessage) || AtomMessage.Length > 254)
|
||||
throw new ArgumentException("AtomMessage Invalid");
|
||||
|
||||
// Register a new Atom
|
||||
uint nAtomKey = Kernel32.GlobalAddAtom(AtomMessage);
|
||||
if (nAtomKey == 0)
|
||||
throw new Exception("GlobalAddAtom Failed");
|
||||
|
||||
// Send the Message
|
||||
if (bBroadcast)
|
||||
User32.PostMessage(Definitions.HWND_BROADCAST, (int)_AtomMsg, hWndSrc, (IntPtr)nAtomKey);
|
||||
else
|
||||
User32.PostMessage(hWndDst, (int)_AtomMsg, hWndSrc, (IntPtr)nAtomKey);
|
||||
|
||||
// Imp! Atom still must get Deleted, that is why we add it to DS
|
||||
AddPostedAtomKey(nAtomKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post an Atom Message To the Specified Window or All Windows
|
||||
/// </summary>
|
||||
/// <param name="hWndSrc">Sender Windows (Nice to have), in case Receiver Needs it</param>
|
||||
/// <param name="hWndDst">Can be IntPtr.Zero to BroadCast the Message, otherwise specify window to send to</param>
|
||||
/// <param name="AtomMessage">The Message to Send that has multiple values * Can not be longer than 254 chars *</param>
|
||||
public void PostAtomMessage(IntPtr hWndSrc, IntPtr hWndDst, string[] AtomMessage)
|
||||
{
|
||||
PostAtomMessage(hWndSrc, hWndDst, SetMultipleValueInAtomMessage(AtomMessage));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Posted Atom Keys handling
|
||||
|
||||
/// <summary>
|
||||
/// Adds the Specified Posted Atom Key to the Posted Atoms DS.
|
||||
/// Clears the DS, if MAGIC_NUMBER_POSTED_ATOM_KEY has been reached.
|
||||
/// </summary>
|
||||
/// <param name="nKey">a unique AtomKey</param>
|
||||
private void AddPostedAtomKey(uint nKey)
|
||||
{
|
||||
if (_postedAtomKeys.Count >= MAGIC_NUMBER_POSTED_ATOM_KEYS)
|
||||
DeleteAllPostedAtomKeys();
|
||||
|
||||
_postedAtomKeys.Add(nKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all posted Atoms and Clears the PostedAtoms DS
|
||||
/// </summary>
|
||||
private void DeleteAllPostedAtomKeys()
|
||||
{
|
||||
foreach (uint Key in _postedAtomKeys)
|
||||
Kernel32.GlobalDeleteAtom(Key);
|
||||
|
||||
_postedAtomKeys.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose Posted Atom Strings
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose Posted Atom Strings
|
||||
/// </summary>
|
||||
/// <param name="disposing">true, if called from within</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_postedAtomKeys.Count != 0)
|
||||
DeleteAllPostedAtomKeys();
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_postedAtomKeys = null;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user