I'm trying to add a "snap to grid" functionality to a WinForm application in C#, but I am having a bit of a problem getting the form to move correctly.
The desired result is that the user clicks and drags the form and the position of the form is moved in the desired direction of the mouse but in 50 pixel increments, and always rounded down to the last grid point. The resize of the form is to for the same 50 pixel increment when the border is clicked and dragged.
I have been able to get the resize to work correctly by calculating the new size in the WM_SIZING message in WndProc. I attempted to do the same thing in the WM_MOVING, but I am not getting the correct functionality.
What I get is that the form will not move to any grid point higher (right or down) than it's start location, and when the mouse is moved towards a grid point lower (top or left) by 1 pixel the form jumps 50 pixels. Of course this is the desired movement to the lower point, but it should only move once and then wait for the mouse to move the additional space before making the next jump, however it move 50 pixels for the next 1 pixel of mouse movement.
What I have found is that the position of the window in the Message.LParam is calculated at each message and is only updated when the WM_MOVE is completed. This is true even if the mouse button has not been released. So moving the mouse top or left forces the window to move 50 pixels and on the next message (ie: another 1 pixel of mouse movement) the LParam is now 50 pixels lower and the 1 pixel is enough to snap to the next lower grid point. However, since I don't want the window to move right or down till the mouse has moved 50 pixels from it's first click point, the WndProc leaves the window position the same and it never reaches a point higher than it's starting position. For some reason the WM_SIZING does not do this. It sees the window as changing size even if the size change is not visible on the screen.
Here is my code I am using. The WM_SIZING part has been removed for clarity.
private const int WM_MOVING = 0x216;
private const int WM_MOVE = 0x3;
struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOVING)
{
RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
int w = rc.Right - rc.Left;
int h = rc.Bottom - rc.Top;
rc.Top = ((int)rc.Top / 50) * 50;
rc.Left = ((int)rc.Left / 50) * 50;
rc.Right = rc.Left + w;
rc.Bottom = rc.Top + h;
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}
Thank you for any help or insight to this issue. -Dustin