2

When I try to drag my window with this the window jumps and flickers around:

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MOVE)
    {
        int x = (m.LParam.ToInt32() & 0xffff);
        int y = ((m.LParam.ToInt32() >> 16) & 0xffff);

        if (x < 500)
            Location = new Point(0, y);
        else
            base.WndProc(ref m);
    }
    else
        base.WndProc(ref m);
}
  • must stop jumping
  • WM_MOVE, WM_MOVING, WM_WINDOWPOSCHANGING or other move event must continue firing while dragging the window because I want every new position to be checked.
  • another problem is Location = new Point(0, y); fires another move event (this one should be ignored)

Please help!

Bitterblue
  • 13,162
  • 17
  • 86
  • 124
  • Are you simply trying to prevent moving the window by dragging? Where does the window start (are you setting 0,0 at inception)? – DonBoitnott Jun 06 '13 at 13:24
  • 1
    You are forgetting about the WM_MOVING message. Why this needs to be "winapi" is very unclear, the LocationChanged event works well enough. – Hans Passant Jun 06 '13 at 13:32
  • 1
    Sounds to me like you should be using [WM_WINDOWPOSCHANGING](http://msdn.microsoft.com/en-us/library/windows/desktop/ms632653(v=vs.85).aspx). You can change the WINDOWPOS structure to modify the window position and/or size. Use Marshal.PtrToStructure() to get it out, and Marshal.StructureToPtr() to put it back; very similar to what I did [here](http://stackoverflow.com/a/16932384/2330053) with WM_GETMINMAXINFO. – Idle_Mind Jun 06 '13 at 14:56
  • @Idle_Mind If I modify the windowpos structure that wont fire a move/poschanging event right ? Can you make an answer and help out how to do so (earn points) ? – Bitterblue Jun 06 '13 at 15:12
  • The initial move and "snap" will fire a Move() event, but afterwards none would be generated...it would just stick to the spot. – Idle_Mind Jun 06 '13 at 15:20

2 Answers2

4

Here's an example of using WM_WINDOWPOSCHANGING and modifying the WINDOWPOS structure:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public uint flags;
    }

    public const int WM_WINDOWPOSCHANGING = 0x46;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_WINDOWPOSCHANGING:
                WINDOWPOS wp = (WINDOWPOS)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
                if (true) // ... if somecondition ...
                {
                    // modify the location with x,y:
                    wp.x = 0;
                    wp.y = 0;
                }
                System.Runtime.InteropServices.Marshal.StructureToPtr(wp, m.LParam, true);
                break;
        }

        base.WndProc(ref m);
    }

}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
0

This should do what you want:

protected override void WndProc(ref Message message)
{
    const Int32 WM_SYSCOMMAND = 0x0112;
    const Int32 SC_MOVE = 0xF010;

    switch (message.Msg)
    {
        case WM_SYSCOMMAND:
            Int32 command = message.WParam.ToInt32() & 0xfff0;
            if (command == SC_MOVE)
            {
                Left = 0;
                Top = 0;
                return;
            }
            break;
    }

    base.WndProc(ref message);
}

Hans Passant suggested the LocationChanged event, and it can work quite nicely. In this example, the window is frozen at 0, 0 until the mouse pointer gets outside of a 500, 500 box:

private void Form1_LocationChanged(Object sender, EventArgs e)
{
    if (MousePosition.X > 500 || MousePosition.Y > 500)
        Location = MousePosition;
    else
        Location = new Point(0, 0);
}
DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
  • This event doesn't fire often only once when you start to move the window. I don't want it to stay at `(0, 0)` ALL the time but to decide when I let it move or keep it at one location. – Bitterblue Jun 06 '13 at 13:43
  • You've provided nothing to suggest such logic. You must explain that if you'd like it to be part of the answer. – DonBoitnott Jun 06 '13 at 13:44
  • What is this decision-making process then? What criteria for move versus relocate versus do nothing? Put _that_ in the `if` block and set `Left` and `Top` accordingly. Such as `Left = MousePostion.X` instead of zero. – DonBoitnott Jun 06 '13 at 13:53
  • Sorry maybe this is a misunderstanding. Note the big edit in the question please. – Bitterblue Jun 06 '13 at 14:14
  • The misunderstanding is that we don't know what you want it to do. You grab the window, start to move it, you make it jump to `0, 0`...then what? If you don't want it to stay at `0, 0`, then what determines when it _doesn't_ stay put? – DonBoitnott Jun 06 '13 at 14:16
  • Have you tried a clean form with my `WndProc` above ? Make it `if (true)` and then see what happens! – Bitterblue Jun 06 '13 at 14:24