How to allow user to move a control on the form
I have a winform on which i want to allow the user to开发者_Go百科 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.
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
}
}
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.
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://www.thomaslevesque.com/2009/05/06/windows-forms-automatically-drag-and-drop-controls-dragmove/
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();
Well in all honesty there is a simpler way where by you initialize a global boolean variable called whatever you like, in this case, isMouseClicked
. On your control you wish to allow dragging you go to its mouse down event,
Make sure these event are your control events not your forms event.
if (e.button == MouseButtons.left)
//this is where you set the boolean to true
Then go to its mouse move event
if (isMouseClicked == true)
//You then set your location of your control. See below:
Button1.Location = new Point(MousePosition.X, MousePosition.Y);
On your mouse up make sure to set your isMouseClicked
to false
;
精彩评论