Archive for the ‘geeky’ Category

C# Win32 messaging with SendMessage and WM_COPYDATA

July 29, 2008

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.

Below now is a brief listing of my MessageHelper.cs class, for the whole class file see:

http://craigcook.co.uk/samples/MessageHelper.cs.txt

//////////////////// Code Begins ////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Diagnostics;

public class MessageHelper
{
[DllImport("User32.dll")]
private static extern int RegisterWindowMessage(string lpString);

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);

[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);

[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
public static extern bool SetForegroundWindow(int hWnd);

public const int WM_USER = 0×400;
public const int WM_COPYDATA = 0×4A;

//Used for WM_COPYDATA for string messages
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}

public bool bringAppToFront(int hWnd)
{
return SetForegroundWindow(hWnd);
}

public int sendWindowsStringMessage(int hWnd, int wParam, string msg)
{
int result = 0;

if (hWnd > 0)
{
byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = msg;
cds.cbData = len + 1;
result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}

return result;
}

public int sendWindowsMessage(int hWnd, int Msg, int wParam, int lParam)
{
int result = 0;

if (hWnd > 0)
{
result = SendMessage(hWnd, Msg, wParam, lParam);
}

return result;
}

public int getWindowId(string className, string windowName)
{

return FindWindow(className, windowName);

}
}

//////////////////// Code Ends ////////////////////

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);
}

TiddlyBlogger updated

November 5, 2007

I’ve recently updated my original TiddlyBlogger code to include JayFresh’s additions mentioned here (cheers for your work here Jon).

The added features are:

  • You can publish tags
  • You get a response to the XML-RPC Ajax call (i.e. you know if your post was successful
  • The ‘publish as blog’ option now only appears when you add the tag ‘blog’ to your tiddler.

Changes planned for the future are:

  • Being able to pull down blogs from WordPress (and editing them).
  • Support for more complex formatting (hyper links, bullet points etc)

Musings on facebook status’

November 2, 2007

Over the last few days I’ve noticed something strange happening. I’ve started to think in terms of my facebook status. I’ll be at my desk and in my head I’ll say ‘Craig is…’ something or the other. Earlier on I was thinking ‘Craig is… going for a haircut’, when I got back I was thinking ‘Craig is… wondering why hairdressers never listen’. I think you get the point.

My point is that it’s become almost second nature to me to transpose what I’m doing and feeling into facebook terminology. I wonder has anyone else noticed this?

I wonder if it will affect us in any other ways? Will we find ourselves thinking differently as we need to cope with managing both out online (virtual?) and physical selves.

I’d love to hear peoples thoughts.

Goodbye Carson

October 21, 2007

I posted this in my old blog, but I thought I’d repost it here:

When I first heard that Dr. Beckett was going to be killed off in season 3 of Atlantis I was pleased. To be honest he always annoyed me, I thought that the creators were just trying to keep to a similar format to SG-1, where a doctor is a main character. I must also say that Dr Frasier in SG-1 had never been a favourite character of mine either.

The strange thing is that during that episode ‘Sunday’ I was actually starting to feel sorry for him. He was just trying to have a day off where he could relax and connect with some of his colleagues (friends), but his attempts were either brushed off or too late. I then realised that the previous few episodes had started to make me like him. It suddenly hit me ‘this is it’ he’s going to die in this episode, and I did genuinely feel sorry for him. It wasn’t exactly the most dignified of deaths, an exploding tumour, but at least it was noble. Carson was self sacrificing to the end, and will be remembered by fans of the show.

We can learn from this not to take for granted those that we have around us on a day-to-day basis. Some people may irritate or annoy us at times, but at the end of the day the world is a lesser place without them.

Shaka, when the walls fell

September 21, 2007

One of the fundamentally best ways of learning in life is by example. It’s interesting then to consider a race (the Tamarians in TNG 5×02 ‘Darmok’) that communicates entirely by example, or by metaphor.

‘Shaka, when the walls fell’ is an example of failure (presumeably a battle that went wrong). We can all do well to consider out failures and see what we learn from them. Although we can and do make mistakes the first time round, this is not reason to give up or feel disheartened, but we should view these times as an opportunity to do better. The best way to learn is by example, and if that example is our own we are only human, and although that means we can fail, it also means that we can do better.

‘Darmok and Jalad at Tanagra’ is further example of lessons learned in the pass (two men defeating a common enemy together). People working together will almost always be more benificial than people working alone, and the lessons learned together will again be more benificial than those just learned by oneself. This is an interesting double metaphor, because it suggests that example can be used to go forward in the future, and it itself is an example of this, but also understanding this will be a benfit to those learning it.

Proud to be geeks

September 21, 2007

I’m going to keep this brief.

Several years ago Bill Gates said something like ‘be careful how you treat geeks, you may end up working for one’ (my girlfriend added ‘or married to one’).

How true this is. It seems that even without realising, more and more people are becoming ‘geeks’. Not necessarily in the classic sense of the word, but let me put it to you this way: how may people do you know that DON’T have a computer, how many people do you know that DON’T have an email address or mobile phone.

More and more people are finding technology interesting and fun. You get people reading such magazines as stuff and SFX, taking an interest in the later mobile phone and the latest TV series. Who would have thought that ‘Lost’ a Sci-Fi would have the attention of so many ‘normal’ people.

It really excites me that people seem to be finally embracing the advantages of science and technology, and that they are slowly becoming part of everyday life (blog is now almost an everyday term). I look forward to the advances we can make in the future.