tags:

views:

1261

answers:

3

Is there anyway to control where you can move a form?

So if i move a form, it can only be moved on the vertical axis and when i try to move it horizontally, nothing happens.

I dont want a buggy implementation like locationchanged or move event and poping it back inline. I no there is a way using something like a WndProc override but after searching for a while, i couldnt find anything. Please help

+1  A: 

You would most likely want to override WndProc and handle the WM_MOVING message. According to MSDN:

The WM_MOVING message is sent to a window that the user is moving. By processing this message, an application can monitor the position of the drag rectangle and, if needed, change its position.

This would be a way to do it, however, you would obviously need to tweek it for your needs:

using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace VerticalMovingForm
{
    public partial class Form1 : Form
    {
        private const int WM_MOVING = 0x0216;
        private readonly int positionX;
        private readonly int positionR;

        public Form1()
        {
            Left = 400;
            Width = 500;                            
            positionX = Left;
            positionR = Left + Width;
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_MOVING)
            {
                var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                r.Left = positionX;
                r.Right = positionR;
                Marshal.StructureToPtr(r, m.LParam, false);
            }
            base.WndProc(ref m);                
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    }
}
driis
+2  A: 

For example:

using System.Runtime.InteropServices;

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x216)  // WM_MOVING = 0x216
    {
        Rectangle rect = 
           (Rectangle) Marshal.PtrToStructure(m.LParam, typeof (Rectangle));
        if (rect.Left < 100)
        {
            // compensates for right side drift
            rect.Width = rect.Width + (100 - rect.Left);
            // force left side to 100
            rect.X = 100;
            Marshal.StructureToPtr(rect, m.LParam, true);
        }
    }
    base.WndProc(ref m);
}

The above code sets a minimum lefthand position of 100.

There is no need to recreate the RECT structure, like driis did, the .NET native Rectangle works fine. However, you have to set the location via the X property, since Left is a Get only property.

Costa Rica Dev
+1 for using as much native CLR code as possible.
Mystere Man
You will also have to handle other messages, because WM_MOVING is not called when the window is first created. Either you neet to explicitly set your windows position on creation, or you need to ensure that when it's created it's within the limits you desire.
Mystere Man
A: 

VB.NET Version:

Protected Overloads Overrides Sub WndProc(ByRef m As Message)
    If m.Msg = &H216 Then
        ' WM_MOVING = 0x216
        Dim rect As Rectangle = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Rectangle)), Rectangle)
        If rect.Left < 100 Then
            ' compensates for right side drift
            rect.Width = rect.Width + (100 - rect.Left)
            ' force left side to 100
            rect.X = 100
            Marshal.StructureToPtr(rect, m.LParam, True)
        End If
    End If
    MyBase.WndProc(m)
End Sub
eschneider