Cancel dragging if the destination picturebox already has an image - c#

I am making a drapandrop and it's working nice. But I want it to give a message whenever I try to drag an image into a picture that already contains one, that won't work... When I click on an image and drag it to the same picturebox where it came from (like I click on picturebox1 and drop it on picturebox1 it just gets blank), it just disappears.public partial class Form1 : Form
public Form1()
{
InitializeComponent();
pictureBox1.AllowDrop = true;
pictureBox2.AllowDrop = true;
pictureBox3.AllowDrop = true;
pictureBox4.AllowDrop = true;
pictureBox5.AllowDrop = true;
pictureBox6.AllowDrop = true;
}
void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
DoDragDrop(sender, DragDropEffects.Move);
}
void pictureBox_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
void pictureBox_DragDrop(object sender, DragEventArgs e)
{
PictureBox pb = e.Data.GetData(typeof(PictureBox)) as PictureBox;
if (pb.Image != null)
{
((PictureBox)sender).Image = pb.Image;
pb.Image = null;
}
else
{
MessageBox.Show("The picturebox already contains an image.");
}
}
}
}

pb is a reference to the PictureBox that is being dragged. since you are droping on the same PictureBox you are dragging, pb and senrder are both referencing the same PictureBox, so the pb.Image = null; code line is clearing the image in the PictureBox. you need to add to your condition a check that pb is different then sender, like this:
if (pb.Image != null && !pb.Equals(sender))
edit
Basically, You should use the DragEnter Event for that. If the PictureBox already contains an Image, you can set the e.Effect to DragDropEffects.None. that will also provide a better solition to the problem you described in the first place.

Related

Drag'n Drop : tell the sender when drop occurs

I'm using c# 3.5 / winforms
On my form, I have 2 picturebox PB1 and PB2 (and lots of others controls), in a panel.
The user can drag PB1 to PB2. But he can also cancel the drop by release the left button anywhere on the form or outside the form.
PB1 can be dragged a fixed number of times. When the drag start, I decrease a variable in PB1 and if it reach 0, the PB became invisible.
But if the user cancel the drag, PB1 must know that to increase the variable and set the visibility of PB1.
My problem is : how PB1 can know when a drag is canceled (or actually, dropped, even on a valid control) ? Remember that the user can release the drag outside of the form, so I can't use the Drop event on the form. I try the GiveFeedback and the QueryContinueDrag events, but they are fired as long as the drag continue, but not when it stop.
Some code :
class COPGOJetonImage
{
private PictureBox PB1;
public COPGOJetonImage()
{
PB1 = new PictureBox();
//here I initialize PB1
((Control)PB1).AllowDrop = true; //in case of
PB1.MouseDown += OnMouseDown;
}
public void OnMouseDown(object sender, MouseEventArgs ev)
{
PB1.DoDragDrop(PB1.Image, DragDropEffects.Copy);
}
}
"there are 1 to 4 valid targets."
In this example we are dragging pictureBox1, and pictureBox2 thru pictureBox5 are the valid drop targets. We create a DataObject with a custom name to encapsulate pictureBox1 during the drag/drop operation. In the drop targets, we only allow a drop if the custom name is present in the thing being dragged. This ensures we only get a DragDrop event from pictureBox1 itself, and we know it's safe to decrement our drop counter. We can retrieve pictureBox1 back from the DataObject and change its state so that it can no longer be dropped:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int DropsLeft = 5;
private string DataFormatName = "YourUniqueDataFormatNameHere";
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.MouseMove += PictureBox1_MouseMove;
PictureBox[] pbs = new PictureBox[] { pictureBox2, pictureBox3, pictureBox4, pictureBox5 };
foreach (PictureBox pb in pbs)
{
pb.AllowDrop = true;
pb.DragEnter += Pb_DragEnter;
pb.DragDrop += Pb_DragDrop;
}
}
private void PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DataObject data = new DataObject(DataFormatName, pictureBox1);
pictureBox1.DoDragDrop(data, DragDropEffects.Copy);
}
}
private void Pb_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName))
{
e.Effect = DragDropEffects.All;
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void Pb_DragDrop(object sender, DragEventArgs e)
{
DropsLeft--;
// retrieve the data
PictureBox pb = (PictureBox)e.Data.GetData(DataFormatName);
if (DropsLeft == 0)
{
MessageBox.Show("No more drops left!");
pb.Enabled = false;
pb.BackColor = Color.Red; // for visual effect
}
}
}

C# Drag and Drop - Muliple Pictures Box to Panel or Flow layout panel

I'm currently implementing drag & drop function in C# Window Forms. I've created multiple pictures box on left navigation, so user can drag and drop to right side panel.
But it does look like pictures box can not drop to the panel directly.
When i compile, it runs. But, when I drag and drop it makes following error:
"unable to cast object of type 'System.Windows.Forms.Panel' to type 'System.Windows.Forms.PictureBox'."
Please suggest how can i make drag and drop "picutre 1, 2, 3" to the panel accordingly.?
private void Form3_Load(object sender, EventArgs e)
{
pictureBox4.DragEnter += new DragEventHandler(pictureBox4_DragEnter);
pictureBox4.DragDrop += new DragEventHandler(pictureBox4_DragDrop);
pictureBox4.MouseDown += new MouseEventHandler(pictureBox4_MouseDown);
panel2.AllowDrop = true;
}
private void pictureBox4_DragDrop(object sender, DragEventArgs e)
{
PictureBox pb = (PictureBox)sender;
pb.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
}
private void pictureBox4_MouseDown(object sender, MouseEventArgs e)
{
PictureBox pb = (PictureBox)sender;
pb.Select();
pb.DoDragDrop(pb.Image, DragDropEffects.Copy);
panel1.Show();
}
private void panel2_DragDrop(object sender, DragEventArgs e)
{
PictureBox pb = (PictureBox)sender;
pb.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
}
private void panel2_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Bitmap))
{
e.Effect = DragDropEffects.Copy;
}
else
{
e.Effect = DragDropEffects.None;
}
}
I suppose in this code your sender is actually a Panel. Check it's type in the debugger:
private void panel2_DragDrop(object sender, DragEventArgs e)
{
PictureBox pb = (PictureBox)sender;
pb.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
}
As a good principle always do typecasting like this:
PictureBox pb = sender as PictureBox; // will give you null if it can't be cast to PictureBox
if(pb != null)
{
// do something...
}

Listview Large Icon right click to open ContextMenuStrip

In my project I have a ListView and I would like to open my ContextMenuStrip when I clicked right button in the large icon. I tried many things but I am unsuccessful. When I right click inside of ListView the ContextMenuStrip opens, but I want to see just when I right clicked the large icon.
Also I need to help about get the clicked icon's name (properties).
This is a quick and dirty solution; please do put more work into it than I did..
// a class level reference, prepare it where you want..
ContextMenuStrip ms = new ContextMenuStrip();
You should either code the MouseDown or the MouseUp event:
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
// disassociate from listview at first:
listView1.ContextMenuStrip = null;
// check for right button
if (e.Button != System.Windows.Forms.MouseButtons.Right) return;
// get item info:
ListViewHitTestInfo hi = listView1.HitTest(e.Location);
// no item hit:
if (hi.Item == null) return;
// calculate the image rectangle:
// this contains the unscrolled y coordinate:
Point iloc = listView1.GetItemRect(hi.Item.Index).Location;
// we combine it with the x-position:
Rectangle r = new Rectangle(new Point (hi.Item.Position.X, iloc.Y),
imageList1.ImageSize);
// no image hit:
if ( !r.Contains(e.Location) ) return;
// maybe prepare or change the menue now..
// here I display the image name from the keys array:
ms.Items[0].Text = imageList1.Images.Keys[hi.Item.ImageIndex];
ms.Location = e.Location;
// associate with listview and show
listView1.ContextMenuStrip = ms;
ms.Show();
}
Can you please try the following and let see wether it works or not...
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (listView1.FocusedItem.Bounds.Contains(e.Location) == true)
{
contextMenuStrip1.Show(Cursor.Position);
}
}
}
This should work
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
ListView listView = sender as ListView;
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
ListViewItem item = listView.GetItemAt(e.X, e.Y);
if (item != null)
{
item.Selected = true;
contextMenuStrip1.Show(listView , e.Location);
}
}
}
Search the listview item on mouse click location. If it is there, show the menu.........

Manipulating drag and drop images in windows forms c#

I am trying to write a program which will allow a user to drag and drop images into the program and then be able to select the image, move it about, re-size it, crop it etc.
So far I have created a windows form which consists of a panel. A user can drag a picture file onto the panel and a picturebox will be created at the coordinates of the mouse when it is dropped and an image is loaded in the picturebox. I can add several images in this fashion.
Now I want to allow the user to manipulate and move about the images that they have dropped into the panel.
I have tried searching for solutions but cant seem to find an answer which I understand.
Any help is much appreciated..
This is my current code
private void panel1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
private void panel1_DragDrop(object sender, DragEventArgs e)
{
String[] imagePaths = (String[])e.Data.GetData(DataFormats.FileDrop);
foreach (string path in imagePaths)
{
Point point = panel1.PointToClient(Cursor.Position);
PictureBox pb = new PictureBox();
pb.ImageLocation = path;
pb.Left = point.X;
pb.Top = point.Y;
panel1.Controls.Add(pb);
//g.DrawImage(Image.FromFile(path), point);
}
}
You can get the mouse position when the user initially clicks and then track the mouse position in the PictureBox's MouseMove event. You can attach these handlers to multiple PictureBoxes.
private int xPos;
private int yPos;
private void pb_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
xPos = e.X;
yPos = e.Y;
}
}
private void pb_MouseMove(object sender, MouseEventArgs e)
{
PictureBox p = sender as PictureBox;
if(p != null)
{
if (e.Button == MouseButtons.Left)
{
p.Top += (e.Y - yPos);
p.Left += (e.X - xPos);
}
}
}
For dynamic PictureBoxes you can attach the handlers like this
PictureBox dpb = new PictureBox();
dpb.MouseDown += pb_MouseDown;
dbp.MouseMove += pb_MouseMove;
//fill the rest of the properties...

C# Drag and Drop from one Picture box into Another

I'm working in visual studio 2012 with C# and I need to Drag a Picture box into another picture box, basically replace the target Picturebox Image with the Dragged Picture box image.
How do I do this?
Please be specific and try to explain as simplest and as best as possible.
I'm extremely new to programming, and a bit desperate so please be patient with me.
Drag+drop is hidden on the PictureBox control. Not sure why, it works just fine. The probable guidance here is that it will not be obvious to the user that you could drop an image on the control. You'll have to do something about that, at least set the BackColor property to a non-default value so the user can see it.
Anyhoo, you'll need to implement the MouseDown event on the first picturebox so you can click it and start dragging:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
var img = pictureBox1.Image;
if (img == null) return;
if (DoDragDrop(img, DragDropEffects.Move) == DragDropEffects.Move) {
pictureBox1.Image = null;
}
}
I assumed you wanted to move the image, tweak if necessary if copying was intended. Then you'll have to implement the DragEnter and DragDrop events on the second picturebox. Since the properties are hidden, you should set them in the form's constructor. Like this:
public Form1() {
InitializeComponent();
pictureBox1.MouseDown += pictureBox1_MouseDown;
pictureBox2.AllowDrop = true;
pictureBox2.DragEnter += pictureBox2_DragEnter;
pictureBox2.DragDrop += pictureBox2_DragDrop;
}
void pictureBox2_DragEnter(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(DataFormats.Bitmap))
e.Effect = DragDropEffects.Move;
}
void pictureBox2_DragDrop(object sender, DragEventArgs e) {
var bmp = (Bitmap)e.Data.GetData(DataFormats.Bitmap);
pictureBox2.Image = bmp;
}
This does allow you to drag an image from another application into the box. Let's call it a feature. Use a bool flag if you want to disallow this.
Hans's answer led me to the correct solution. The problem with that answer is that putting DoDragDrop inside MouseDown will prevent MouseClick events from firing.
Here's my solution:
private void PictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
var pb = (PictureBox)sender;
if (pb.BackgroundImage != null)
{
pb.DoDragDrop(pb, DragDropEffects.Move);
}
}
}
private void PictureBox_DragEnter (object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void PictureBox_DragDrop (object sender, DragEventArgs e)
{
var target = (PictureBox)sender;
if (e.Data.GetDataPresent(typeof(PictureBox)))
{
var source = (PictureBox)e.Data.GetData(typeof(PictureBox));
if (source != target)
{
// You can swap the images out, replace the target image, etc.
SwapImages(source, target);
}
}
}
Full working example on my GitHub.
You can use mouse enter and leave events to do this easily. For example you have two picture boxes pictureBox1 and pictureBox2. And you want to drag the image from picture box1 and drop it onto picture box2 do somthing like this.
private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
{
if (a == 1)
{
pictureBox1.Image = pictureBox2.Image;
a = 0;
}
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
a = 1;
}
Where 'a' is just a lock or key which checks whether the mouse has entered the control on which we want to drop this image on. Hope it helped, worked for me.
You can't set AllowDrop on PictureBox...set it for your whole form.
Code Snippet
Form1.AllowDrop = true;
Use the Form DragEnter, DragDrop events, they will work even if you drop it over the pictureBox.
private void Form1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
int x = this.PointToClient(new Point(e.X, e.Y)).X;
int y = this.PointToClient(new Point(e.X, e.Y)).Y;
if(x >= pictureBox1.Location.X && x <= pictureBox1.Location.X + pictureBox1.Width && y >= pictureBox1.Location.Y && y <= pictureBox1.Location.Y + pictureBox1.Height)
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
pictureBox1.Image = Image.FromFile(files[0]);
}
}

Categories