Okay, I'm trying to use the
RegisteredWindowMessage
API function to send text from one application to another, and I have the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Common
{
public static class RegisteredMsg
{
private const string MyMessage = "9C7EDA65363F4fdaAF32";
private static IntPtr m_targetWindow = new IntPtr(0xFFFF);
private static object m_object = new object();
private static HandleRef m_handleRef;
private static HandleRef m_handleRef;
public static uint RegisteredMessage
{
get { return m_regMsg; }
private set
{
m_regMsg = RegisterWindowMessage(SynchroMessage);
}
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
static RegisteredMsg()
{
m_handleRef = new HandleRef(m_object, m_targetWindow);
}
public static void PostUpdateMsg(string text)
{
IntPtr lpData = Marshal.StringToHGlobalAuto(text);
IntPtr lpLength = new IntPtr(text.Length);
if (!PostMessage(m_handleRef, RegisteredMessage, lpData, lpLength))
{
throw new Exception("Could not post message.");
}
}
public static string GetMessageText(Message msg)
{
string text = "";
int length = msg.LParam.ToInt32();
text = Marshal.PtrToStringAuto(msg.WParam, length);
Marshal.FreeHGlobal(msg.WParam);
return text;
}
}
}
Posting the message works find, but when the receiving application calls GetMessageText, the string contains "\0\0\0\0" (which is NOT what the sending application sent).
I'm calling it like this:
RegisteredMsg.PostUpdateMsg("test");
and receiving it like this:
protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
if (Convert.ToUInt32(msg.Msg) == RegisteredMsg.RegisteredMessage)
{
string text = RegisteredMsg.GetMessageText(msg);
}
}
EDIT #0 ================
I also tried it this way, and all of the bytes in the received array are '\0':
public static void PostUpdateMsg(string text)
{
byte[] array = StringToByteArray(text);
IntPtr lpData = Marshal.AllocHGlobal(array.Length);
Marshal.Copy(array, 0, lpData, array.Length);
IntPtr lpLength = new IntPtr(text.Length);
if (!PostMessage(m_handleRef, RegisteredMessage, lpData, lpLength))
{
throw new Exception("Could not post message.");
}
}
{
string text = "";
int length = msg.LParam.ToInt32();
byte[] array = new byte[length];
Marshal.Copy(msg.WParam, array, 0, length);
text = RegisteredMsg.ByteArrayToString(array);
return text;
}
EDIT #1 ====================
I also called this method from
PostUpdateMessage
, just to make sure what I was sending was what I thought I was sending:
private static void TestIntPtr(IntPtr ptr, int length)
{
string text = "";
byte[] array = new byte[length];
Marshal.Copy(ptr, array, 0, length);
text = ByteArrayToString(array);
}
When the indicated line is executed, the
text
variablle is indeed = "test", so I'm doing it right on the sending side. It looks like the memory is getting cleared before it gets to the receiving application.
EDIT #2 =====================
I also tried making the
IntPtr
(pointing to the string I want to send) global to its parent class to make sure it would live long enough to be viable at the other end. No joy there, either.
EDIT #3 =====================
I also reverted back to using the
StringToHGlobalAuto
, and ran the "
is it still okay in the sending app" test (see Edit #1 above), and that test proved that the way I was building the
IntPtr
was fine as well.