tags:

views:

51

answers:

4

I have a winform on which i want to allow the user to move a control.

The control is (for now) a vertical line : label with border and a width of 1.

The context is not very important but i'll give it to you anyways. I have a background with some graphics and i'd like the user to be able to slide a guideline above the graphics. The graphics are made with the NPlots library. It looks something like this: http://www.ibme.de/pictures/xtm-window-graphic-ramp-signals.png

If i can find out how the user can click and drag the label/line control around the screen, i can solve my guideline problem. Please help.

+4  A: 

The code for this can get a bit complex, but essentially you will need to capture the MouseDown, MouseMove, and MouseUp events on your form. Something like this:

public void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if(e.Button != MouseButton.Left)
        return;

    // Might want to pad these values a bit if the line is only 1px,
    // might be hard for the user to hit directly
    if(e.Y == myControl.Top)
    {
        if(e.X >= myControl.Left && e.X <= myControl.Left + myControl.Width)
        {
            _capturingMoves = true;
            return;
        }
    }

    _capturingMoves = false;
}

public void Form1_MouseMove(object sender, MouseEventArgs e) 
{
    if(!_capturingMoves)
        return;

    // Calculate the delta's and move the line here
}

public void Form1_MouseUp(object sender, MouseEventArgs e) 
{
    if(_capturingMoves)
    {
        _capturingMoves = false;
        // Do any final placement
    }
}
Coding Gorilla
Thanks! Works perfectly.
Lily
+1  A: 

In WinForms, you can handle the MouseDown, MouseMove and MouseUp events of a control. On MouseDown, set some bit or reference telling your form what control the mouse was clicked on, and capture the X and Y of the mouse from MouseEventArgs. On MouseMove, if a control is set, adjust its X and Y by the difference between your last captured X and Y and the current coordinates. On MouseUp, release the control.

I would set up an "edit mode" for this; when the user enters this mode, the current event handlers of your form's controls should be detached, and the movement handlers attached. If you want to persist or revert these changes (like you're making a custom form designer your client can use to customize window layouts), you'll also need to be able to take some sort of snapshot of the before and after layouts of the controls.

KeithS
A: 

I wrote a component to do exactly that: move a control on a form (or move a borderless form on the screen). You can even use it from the designer, without writing any code.

http://tomlev2.wordpress.com/2009/05/06/windows-forms-automatically-drag-and-drop-controls-dragmove/

Thomas Levesque
A: 

Here's an extension method that you can use for any control. It uses Rx and is based on the A Brief Introduction to the Reactive Extensions for .NET, Rx post and sample by Wes Dyer.

public static class FormExtensions
{
    public static void EnableDragging(this Control c)
    {
        // Long way, but strongly typed.        
        var downs =
            from down in Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
                eh => new MouseEventHandler(eh),
                eh => c.MouseDown += eh,
                eh => c.MouseDown -= eh)
            select new { down.EventArgs.X, down.EventArgs.Y };

        // Short way.        
        var moves = from move in Observable.FromEvent<MouseEventArgs>(c, "MouseMove")
                    select new { move.EventArgs.X, move.EventArgs.Y };

        var ups = Observable.FromEvent<MouseEventArgs>(c, "MouseUp");

        var drags = from down in downs
                    from move in moves.TakeUntil(ups)
                    select new Point { X = move.X - down.X, Y = move.Y - down.Y };

        drags.Subscribe(drag => c.SetBounds(c.Location.X + drag.X, c.Location.Y + drag.Y, 0, 0, BoundsSpecified.Location));
    }
}

Usage:

Button button1 = new Button();

button1.EnableDragging();

Richard Hein