nsg
nsg

Reputation: 539

How to restrict form movement to horizontal?

I have a standard form with standard title bar that user may grab and move the form around. In certain situations I want to restrict this movement to horizontal only, so no matter how the mouse actually moves, the form remains on same Y coordinate.

To do this, I catch move event and when I detect deviation from Y, I move the form back to the original Y. Like that:

private void TemplateSlide_Move(object sender, EventArgs e)
{
    int y = SlideSettings.LastLocation.Y;
    if (y != this.Location.Y)
    {
        SlideSettings.LastLocation = new Point(this.Location.X, y);
        this.Location=Settings.LastLocation;
    }
}

But this causes a lot of flicker. Also because form actually moves for a brief moment away from desired Y this causes other issues specific to my program.

Is there a way to prevent form from moving away from desired Y coordinate?

Upvotes: 2

Views: 485

Answers (2)

Idle_Mind
Idle_Mind

Reputation: 39142

Trap WM_MOVING and modify the RECT structure in LPARAM accordingly.

Something like:

public partial class Form1 : Form
{

    public const int WM_MOVING = 0x216;

    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    private int OriginalY = 0;
    private int OriginalHeight = 0;
    private bool HorizontalMovementOnly = true;

    public Form1()
    {
        InitializeComponent();
        this.Shown += new EventHandler(Form1_Shown);
        this.SizeChanged += new EventHandler(Form1_SizeChanged);
        this.Move += new EventHandler(Form1_Move);
    }

    void Form1_Move(object sender, EventArgs e)
    {
        this.SaveValues();
    }

    void Form1_SizeChanged(object sender, EventArgs e)
    {
        this.SaveValues();
    }

    void Form1_Shown(object sender, EventArgs e)
    {
        this.SaveValues();
    }

    private void SaveValues()
    {
        this.OriginalY = this.Location.Y;
        this.OriginalHeight = this.Size.Height;
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_MOVING:
                if (this.HorizontalMovementOnly)
                {
                    RECT rect = (RECT)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(RECT));
                    rect.Top = this.OriginalY;
                    rect.Bottom = rect.Top + this.OriginalHeight;
                    System.Runtime.InteropServices.Marshal.StructureToPtr(rect, m.LParam, false);
                }
                break;
        }
        base.WndProc(ref m);            
    }
}

Upvotes: 3

George Johnston
George Johnston

Reputation: 32278

When it's appropriate, just use the Mouse's Y coordinate, substituting the X coordinate with your static value. e.g.

... // e.g Mouse Down
originalX = Mouse.X; // Or whatever static X value you have.

... // e.g Mouse Move
// Y is dynamically updated while X remains static
YourObject.Location = new Point(originalX, Mouse.Y);

Upvotes: 3

Related Questions