C# Win32 messaging with SendMessage and WM_COPYDATA

I had a real pain recently where I wanted to control one windows app from another. I found some useful stuff on the net, but nothing that gave an end to end solution. So here’s what I came up with.

Firstly I’ll explain why this is useful. SendMessage is part of the Win32 API, and is used to send messages from one application to another. There are a set of predefined properties that the message can relate to, and these can be used to send messages to existing applications to perform all sorts of useful functions such as changing the font in notepad, or bringing a window to the fore. For more information of the wider use of the SendMessage function, have a look at:

http://www.autohotkey.com/docs/commands/PostMessage.htm

http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

The main use that I’m interested in is passing a specific instruction (via a string) from one app that I’ve written, to another one that I’ve written. This way I can effectively remote control one app from another (particularly useful if you want your main application to open a pop-up, and you don’t want to worry about the pop-up’s performance affecting the main application). Let’s now have a quick look at the SendMessage function:

SendMessage(int hWnd, int Msg, int wParam, int lParam)

hWnd – This is the window instance id of the application you want to send a message to. This id is retrieved using the FindWindow function

Msg – This is the type of message you want to send

wParam – Message specific data you pass in

wParam – Message specific data you pass in

Also used is the FindWindow function. This is to get the relevant window id:

FindWindow(String lpClassName, String lpWindowName)

lpClassName -The name of the class you want

lpWindowName – The name of the window that you want

To send a message that is a string, you need to use the WM_DATACOPY message property. The hard part is that you cannot just send the string as a parameter across. You need to send a pointer to the memory address of the string. If you just want to send an integer as a message you can use the WM_USER message property and send it as a value without a problem.

For a full example of the MessageHelper.cs class see this gist:

So now you can call the code to send a message like so:

MessageHelper msg = new MessageHelper();
int result = 0;
//First param can be null
int hWnd = msg.getWindowId(null, "My App Name");
result = msg.sendWindowsStringMessage(hWnd, 0, "Some_String_Message");
//Or for an integer message
result = msg.sendWindowsMessage(hWnd, MessageHelper.WM_USER, 123, 456);

Now all you need to do on the app that you want to receive the message is override the following function in the form class (obviously you can change what the responses are, and you’ll need to create constants for the parameters):

protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_USER:
MessageBox.Show("Message recieved: " + m.WParam + " - " + m.LParam);
break;
case WM_COPYDATA:
COPYDATASTRUCT mystr = new COPYDATASTRUCT();
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
this.doSomethingWithMessage(mystr.lpData);
break;
}
base.WndProc(ref m);
}
About these ads
Tagged with: , , , , ,
Posted in geeky, programming
12 comments on “C# Win32 messaging with SendMessage and WM_COPYDATA
  1. Mikael says:

    Thank’s very much! The MessageHelper class did save me a lot of work and helped me create a better solution.

    Kind regards
    Mikael

  2. boycook says:

    Hi – sorry I was doing a server upgrade. The link should work again now.

  3. Robert says:

    Exactly what I was looking for, thanks!

  4. Alan says:

    Excellent example in its directness. I will need to change it to vfp, but it is the most straight forward example I have found yet!

    Thanks,
    Alan

  5. boycook says:

    Sorry my box is down at the moment. Please try again over the weekend.

  6. bill gates says:

    thanks your article was very helpful..

  7. Carm says:

    I came across this post and it might be exactly what I’m looking for. Unfortunately the link to MessageHelper.cs.txt still seems to be down :(

  8. Dave B. says:

    Nice work. Plan to use it on some test automation where I have a patchbay controller app that talks to the hardware switches via usb, and another client that talks to the controller with a higher level device library – it will use the sendWindowsStringMessage technique. Thanks!

  9. You got me started on a beautiful little journey! I took your code and extended the send message functions to allow me not only to pass objects to other processes but also to get objects back as a result! (I use memory-mapped files as the out of band mechanism to turn result codes back into objects.) It’s pretty darn cool, great alternative to fussing with Sockets/WCF when you just want something simple!

  10. Zeeshan Nasir says:

    file not found. upload it again,

  11. Razvan Musca says:

    Hi, i have been trying to get the MessageHelper.cs.txt but the link appears to be dead “No route to host.” can you please post it again in some mirror ?

    Best regards,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 277 other followers

%d bloggers like this: