Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

winapi

intptr

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?

like image 641
HelloWorld Avatar asked Oct 27 '11 08:10

HelloWorld


People also ask

What is WinAPI in C?

The Windows API, informally WinAPI, is Microsoft's core set of application programming interfaces (APIs) available in the Microsoft Windows operating systems.

How do I use Win API?

To call a Windows API using the DllImport attributeOpen a new Windows Application project by clicking New on the File menu, and then clicking Project. The New Project dialog box appears. Select Windows Application from the list of Visual Basic project templates. The new project is displayed.

Is WinAPI C or C++?

Most Win Api is C. There are couple exceptions (dor example COM IFAIR). But almost every code in MSDN says C++..

What is WinAPI used for?

Using the Windows API, you can develop applications that run successfully on all versions of Windows while taking advantage of the features and capabilities unique to each version. (Note that this was formerly called the Win32 API.


1 Answers

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)

like image 54
xanatos Avatar answered Sep 19 '22 20:09

xanatos