Making a panel draggable - c#

I am creating a "cropping tool", and i need to make a panel that contains 2 buttons draggable.
Until now i've tried something like this, but the change location event happens only when i click the right button of the mouse...
this.MouseDown += new MouseEventHandler(onRightClickMouse);
private void onRightClickMouse(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point localMouseClickPoint = new Point(e.X, e.Y);
panel1.Location = localMouseClickPoint;
}
}
My question: How can i make that panel draggable in my form?(I mean click on the panel then drag it to a location).

Try something like this:
delegate void updatePanelCallback();
panel1.MouseDown += new MouseEventHandler(onMouseDown);
panel1.MouseUp += new MouseEventHandler(onMouseUp);
System.Timers.Timer runTimer = new System.Timers.Timer(100);
runTimer.Elapsed += new ElapsedEventHandler(onTimerElapsed);
private void onMouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right)
{
return;
}
runTimer.Enabled = false;
}
private void onMouseUp(object sender, MouseEventArgs e)
{
runTimer.Enabled = false;
}
public void updatePanelLocation()
{
if (this.InvokeRequired)
{
this.Invoke(new updatePanelCallback(updatePanelLocation), new object[] {});
}
else
{
Cursor curs = new Cursor(Cursor.Current.Handle);
panel1.Location = curs.Position;
}
}
private void onTimerElapsed(object source, ElapsedEventArgs e)
{
updatePanelLocation();
}

You could try something in two steps, preparing the action on MouseDown event and finishing it on MouseUp.

Related

C# WPF Drag and Drop Button within StackPanel on a Canvas

This may be a basic question but I just started using WPF and I am having troubles trying to do a simple drag and drop.
I created this ToolboxButton class:
public class ToolboxButton : Button
{
private bool _isDragging = false;
private Point _startPoint;
public ToolboxButton(string content)
{
Content = content;
HorizontalAlignment = HorizontalAlignment.Stretch;
Height = 30;
Loaded += ToolboxButton_Loaded;
}
void ToolboxButton_Loaded(object sender, RoutedEventArgs e)
{
PreviewMouseLeftButtonDown += ToolboxButton_PreviewMouseLeftButtonDown;
PreviewMouseMove += ToolboxButton_PreviewMouseMove;
}
void ToolboxButton_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && !_isDragging)
{
Point position = e.GetPosition(null);
if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
{
StartDrag(e);
}
}
}
void ToolboxButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
private void StartDrag(MouseEventArgs e)
{
_isDragging = true;
DataObject data = new DataObject(System.Windows.DataFormats.Text.ToString(), "abcd");
DragDrop.DoDragDrop(e.Source as ToolboxButton, data, DragDropEffects.Move);
_isDragging = false;
}
}
This button is added in a stackpanel like so:
ToolboxButton btnAddButton = new ToolboxButton("Button");
_toolboxView.Children.Add(btnAddButton); // _toolboxView is a stackpanel
And I have a Canvas with the following code:
public class DesignerView : Canvas
{
public DesignerView()
{
AllowDrop = true;
DragOver += DesignerView_DragOver;
Drop += DesignerView_Drop;
PreviewDragOver += DesignerView_PreviewDragOver;
}
void DesignerView_PreviewDragOver(object sender, DragEventArgs e)
{
MessageBox.Show("previewdragover");
}
void DesignerView_DragOver(object sender, DragEventArgs e)
{
MessageBox.Show("dragover");
if (!e.Data.GetDataPresent(typeof(ToolboxButton)))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
void DesignerView_Drop(object sender, DragEventArgs e)
{
MessageBox.Show("drop");
if (e.Data.GetDataPresent(typeof(ToolboxButton)))
{
ToolboxButton droppedThingie = e.Data.GetData(typeof(ToolboxButton)) as ToolboxButton;
MessageBox.Show("You dropped: " + droppedThingie.Content);
}
}
public UIElement GetView()
{
return this;
}
}
Both Canvas and StackPanel are added in the main window like so:
Grid contentGrid = new Grid();
Content = contentGrid;
contentGrid.Children.Add(_toolboxView.GetView());
contentGrid.Children.Add(_designerView.GetView());
None of the MessageBoxes ever fire and I can't find out why. The cursor changes to the "Cannot pin", a dark circle with a diagonal line inside.
Am I missing something ? I want everything to be done in the code without XML.
Maybe I have to do something on the StackPanel but I tried the code of ToolboxButton there and it didn't work either.
As I can see you done all job, just DesignerView_drop left to correct.
use sender object to grab dragged object (in this example button)
void DesignerView_Drop(object sender, DragEventArgs e)
{
MessageBox.Show("drop");
Button btn = (Button)sender;
contentGrid.Children.Add(btn);
}

How to prevent repeating code using events

I am a beginner programmer and I feel like I am repeating code unnecessarily. I want to make a picture puzzle game consisting of 16 pictureboxes. The problem is that I feel like I have to repeat code for each picturebox's events as in the below example:
Point move;
bool isDragging = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
pictureBox1.Left += e.X - move.X;
pictureBox1.Top += e.Y - move.Y;
pictureBox1.BringToFront();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Just create one method for each of your 3 events:
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
// Luckily the sender parameter will tell us which PictureBox we are dealing with
PictureBox pb = (PictureBox)sender;
pb.Left += e.X - move.X;
pb.Top += e.Y - move.Y;
pb.BringToFront();
}
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Then go to each of your 16 picture boxes in the designer and set the MouseUp event handler to point to pictureBox_MouseUp and the MouseMove event handler to point to pictureBox_MouseMove and the MouseDown event handler to point to pictureBox_MouseMove. Do this for each of the 16 picture boxes.
Try to trigger same events for all PictureBox Controls
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
PictureBox pictureBox = sender as PictureBox;
if(isDragging == true)
{
pictureBox .Left += e.X - move.X;
pictureBox .Top += e.Y - move.Y;
pictureBox .BringToFront();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Create a new component contained Image component and set dock parent container. Write your drag drop codes into the new component.
For example,
public partial class DraggablePictureBox : UserControl
{
public DraggablePictureBox()
{
InitializeComponent();
}
/// <summary>
/// Sets image of inner picture
/// </summary>
public Image Image
{
get {
return InnerPictureBox.Image;
}
set
{
InnerPictureBox.Image = value;
}
}
private void InnerPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging == true)
{
this.Left += e.X - move.X;
this.Top += e.Y - move.Y;
this.BringToFront();
}
}
private void InnerPictureBox_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
private void InnerPictureBox_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private Point move;
private bool isDragging = false;
}
Now you have a one drag drop code for images.
One way to combat this would be to put these in methods, for example
MovePicturePox(Point move, Point newPos, PictureBox pb)
{
pb.Left += newPos.X - move.X;
pb.Top += newPos.Y - move.Y;
pb.BringToFront();
}
These methods can then be called like so
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
MovePictureBox(move, new Point(e.X, y.Y), pictureBox1);
}
}

How can I use MouseLeave / Enter as a boolean?

I am fairly new to C# and I am trying to change the color of a menustrip item when the mouse 'leaves' the button after its selected. But I can't use the MouseLeave as a boolean as it is an event. It tells 'MouseLeave can only appear on the left hand side of +='. Any tips?
Here is what I tried to do:
if (e.Item.MouseLeave)
{
using (Brush b = new SolidBrush(Color.FromArgb(80, 80, 80)))
{
e.Graphics.FillRectangle(b, e.Graphics.ClipBounds);
}
}
You can have a global boolean:
private void frm_Load(object sender, EventArgs e)
{
ctrl.MouseEnter += ctrl_MouseEnter;
ctrl.MouseLeave += ctrl_MouseLeave;
}
private bool bMouseInside = false;
private void ctrl_MouseEnter(object sender, EventArgs e)
{
bMouseInside = true;
}
private void ctrl_MouseLeave(object sender, EventArgs e)
{
bMouseInside = false;
}
To use in your code:
if (!bMouseInside)
{
// using (Brush b etc..
}
As MouseLeave is an event on a control, try something like this:
On creating the control, add a method to the event handler:
control.MouseLeave += control_MouseLeft;
Then define the action that you want to occur in your control_MouseLeft method.
void control_MouseLeft(objet sender, EventArgs e)
{
using (Brush b = new SolidBrush(Color.FromArgb(80, 80, 80)))
{
e.Graphics.FillRectangle(b, e.Graphics.ClipBounds);
}
}

Simple button move

I have a card game application, and I want to create a simple animation that will make the button move when it is clicked and dragged.
I have tried:
bool _Down = false;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
_Down = true;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
_Down = false;
button1.Location = e.Location;
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (_Down)
{
button1.Location = e.Location;
}
}
This doesn't work either. The effect I get is that when the button is clicked and dragged, the button is not visible until the mouse is released, and also, the button doesn't actually stay at the location of the mouse.
I also tried:
bool _Down = false;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
_Down = true;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
_Down = false;
button1.Location = Cursor.Position;
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (_Down)
{
button1.Location = Cursor.Position;
}
}
This works better than the first one as the button is visible when dragged and stops at mouse position, but the only problem is that Cursor.Position returns the cursor position in relativeness to the screen, not the form therefore. The button doesn't actually move at the pace of the cursor.
What can I do to achieve what I want?
Moving Control at runtime is very easy:
Point downPoint;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
downPoint = e.Location;
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) {
button1.Left += e.X - downPoint.X;
button1.Top += e.Y - downPoint.Y;
}
}
Try this
private void button1_MouseUp(object sender, MouseEventArgs e)
{
_Down = false;
button1.Location = PointToClient(Cursor.Position);
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (_Down)
{
button1.Location = PointToClient( Cursor.Position);
}
}

Get Mouse State without access to MouseEventArgs?

I have a form with many, many controls. I need to detect if the mouse is down or if it's up. Most of the time, I don't have MouseEventArgs.
Is there a quick and easy way to tell if the mouse is down without mouseEventArgs?
Is there an alternative, or is something like this the only way?:
foreach (Control c in this.Controls)
{
c.MouseUp += new MouseEventHandler(globalMouseUp);
c.MouseDown += new MouseEventHandler(globalMouseDown);
}
bool isMouseUp = true;
private void globalMouseDown(object sender, MouseEventArgs e)
{
isMouseUp = false;
}
private void globalMouseUp(object sender, MouseEventArgs e)
{
isMouseUp = true;
}
You can try checking with a timer:
private void timer1_Tick(object sender, EventArgs e) {
this.Text = "Mouse Is " + (Control.MouseButtons == MouseButtons.Left);
}
ChecK Control.MouseButtons static property:
if (Control.MouseButtons == MouseButtons.Left)
{
}

Categories