Reputation: 1421
I am trying to read the lParam x and y coordinates from WM_MOVE win32 message and getting strange values. I need to extract them from the lParam IntPtr somehow.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms632631(v=vs.85).aspx
Thanks
Upvotes: 3
Views: 3474
Reputation: 32278
In addition to what Simon Mourier already posted (which covers a number of standard macros), this method returns a Point()
from a message.LParam
.
MSDN suggests to use the
GET_X_LPARAM
andGET_Y_LPARAM
macros (defined inWindowsX.h
) to extract the coordinates, warning against the possible wrong results returned by theLOWORD
andHIWORD
macros (defined inWinDef.h
), because those return unsigned integers.
These are the definitions of the suggested macros:
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
What's important is that these values must be signed, since secondary monitors return negative values as coordinates.
public static Point PointFromLParam(IntPtr lParam)
{
return new Point((int)(lParam) & 0xFFFF, ((int)(lParam) >> 16) & 0xFFFF);
}
Upvotes: 6
Reputation: 139065
.NET Reference source is a gold mine. In an internal System.Windows.Forms.NativeMethods+Util class you will find these helpers, that talk the same as WM_MOVE documentation (high-order word = HIWORD, low-order word = LOWORD, etc.)
public static int MAKELONG(int low, int high) {
return (high << 16) | (low & 0xffff);
}
public static IntPtr MAKELPARAM(int low, int high) {
return (IntPtr) ((high << 16) | (low & 0xffff));
}
public static int HIWORD(int n) {
return (n >> 16) & 0xffff;
}
public static int HIWORD(IntPtr n) {
return HIWORD( unchecked((int)(long)n) );
}
public static int LOWORD(int n) {
return n & 0xffff;
}
public static int LOWORD(IntPtr n) {
return LOWORD( unchecked((int)(long)n) );
}
public static int SignedHIWORD(IntPtr n) {
return SignedHIWORD( unchecked((int)(long)n) );
}
public static int SignedLOWORD(IntPtr n) {
return SignedLOWORD( unchecked((int)(long)n) );
}
public static int SignedHIWORD(int n) {
int i = (int)(short)((n >> 16) & 0xffff);
return i;
}
public static int SignedLOWORD(int n) {
int i = (int)(short)(n & 0xFFFF);
return i;
}
Upvotes: 2
Reputation: 101746
Coordinates in Windows messages are often two signed 16-bit numbers packed into a 32-bit number.
Ideally you should extract these as signed numbers emulating the GET_X_LPARAM
/GET_Y_LPARAM
macros:
IntPtr lparam = (IntPtr) 0xfffeffff; // -1 x -2 example coordinate
uint lparam32 = (uint) lparam.ToInt64(); // We want the bottom unsigned 32-bits
short x = (short) (((uint)lparam32) & 0xffff);
short y = (short) ((((uint)lparam32) >> 16) & 0xffff);
Console.WriteLine(string.Format("coordinates: {0} x {1}", x, y));
In the case of WM_MOVE
you could also extract them as unsigned numbers (ushort
) since the client area will never be negative.
Upvotes: 0