Win api in C#. Get Hi and low word from IntPtr

HelloWorld picture HelloWorld · Oct 27, 2011 · Viewed 12.5k times · Source

I am trying to process a WM_MOUSEMOVE message in C#.

What is the proper way to get an X and Y coordinate from lParam which is a type of IntPtr?

Answer

xanatos picture xanatos · Oct 27, 2011

Try:
(note that this was the initial version, read below for the final version)

IntPtr xy = value;
int x = unchecked((short)xy);
int y = unchecked((short)((uint)xy >> 16));

The unchecked normally isn't necessary (because the "default" c# projects are unchecked)

Consider that these are the definitions of the used macros:

#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))

#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))

Where WORD == ushort, DWORD == uint. I'm cutting some ushort->short conversions.

Addendum:

one and half year later, and having experienced the "vagaries" of 64 bits .NET, I concur with Celess (but note that 99% of the Windows messages are still 32 bits for reasons of compatibility, so I don't think the problem isn't really big now. It's more for the future and because if you want to do something, you should do it correctly.)

The only thing I would make different is this:

IntPtr xy = value;
int x = unchecked((short)(long)xy);
int y = unchecked((short)((long)xy >> 16));

instead of doing the check "is the IntPtr 4 or 8 bytes long", I take the worst case (8 bytes long) and cast xy to a long. With a little luck the double cast (to long and then to short/to uint) will be optimized by the compiler (in the end, the explicit conversion to int of IntPtr is a red herring... If you use it you are putting yourself at risk in the future. You should always use the long conversion and then use it directly/re-cast it to what you need, showing to the future programmers that you knew what you were doing.

A test example: http://ideone.com/a4oGW2 (sadly only 32 bits, but if you have a 64 bits machine you can test the same code)