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...
Related
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
}
}
}
In one of my posts(the link below), I ask how to change tabs while dragging a treenode and hovering over a tab. Now I want do the same thing except with a watermark picbox that is inside another picturebox(a parent sort of speak) that inside a tab.There are two tab pages, two "parent" picboxes(one foreach tab) and one dynamically added picbox on first tab. For more detail read the numbered list below also the code you will need is below the link.
The parent picboxes in both tabs are maxed out in both height and in width to fit the whole tabpage(NOT the header area). The watermark image size is below in the code. Also the watermark is dynamically added.
The reason this semi-copy of the older post failed is because the watermark drag enter event was never called. Meaning the tab never opened after the pic was dragged and was hovering over one of the tabs.Though I'm not 100% sure if I should use the same event with picboxes.
I want to know how I can open tabs while dragging a picbox and hovering over a tab and be able to drop the watermark image on the 2nd parent picbox in tabpage#2 and remove the watermark image in tabpage 1 if there is a copy of the same watermark image.
C# Switch tabs(tabcontrol) while dragging and hovering over a tab
Point mousePos;
bool Movedummytonewtabpic = false;
private void Form1_Load(object sender, EventArgs e)
{
PictureBox picdrag1 = new PictureBox();
picdrag1.Name = "dummytest";
picdrag1.Image = Properties.Resources._previmg;
picdrag1.Size = new Size(52, 42);
picdrag1.SizeMode = PictureBoxSizeMode.AutoSize;
picdrag1.MouseDown += picdrag1_MouseDown;
picdrag1.MouseMove += picdrag1_MouseMove;
picdrag1.DragEnter += picdrag1_DragEnter;
picdrag1.Location = new Point(168, 151);
pictureBox1.Controls.Add(picdrag1);
}
private void picdrag1_DragEnter(object sender, DragEventArgs e)
{
//DragDropEffects.
e.Effect = DragDropEffects.Copy;
Movedummytonewtabpic = true;
}
private void picdrag1_MouseDown(object sender, MouseEventArgs e)
{
mousePos = e.Location;
}
private void picdrag1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int dx = e.X - mousePos.X;
int dy = e.Y - mousePos.Y;
pictureBox1.Location = new Point(pictureBox1.Left + dx, pictureBox1.Top + dy);
}
}
private void tabControl1_DragOver(object sender, DragEventArgs e)
{
if (Movedummytonewtabpic == true )
{
//e.Effect = DragDropEffects.All;
Point clientPoint = tabControl1.PointToClient(new Point(e.X, e.Y));
for (int i = 0; i < tabControl1.TabCount; i++)
{
if (tabControl1.GetTabRect(i).Contains(clientPoint) && tabControl1.SelectedIndex != i)
{
tabControl1.SelectedIndex = i;
}
}
}
}
I have two events wired to a control. A mouse click event plays an audio file. A drag event made up from mouse down, mouse move and mouse up drags the control vertically. By dragging the control vertically the control get assigned a different song.
The problem I have is that when I drag the control the music plays. I do not want this since this is a dragging operation.
Music should play only when control is clicked and note moved.
I think that setting boundaries, e.g. when control moves only 5 pixels play sound otherwise drag control should solve the problem but I tried to create them unsuccessfully.
Can you please guide how to solve this problem preferably with code snippets.
Thank You.
The Drag
int Locked_yLoc; int index;
private void StartDrag(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
sp1.SoundLocation = this.pitch + ".wav";
sp1.Play();
tm1.Interval = 100 * this.noteDuration;
tm1.Start();
isDragging = true;
pitch = e.Y;
this.Location = new Point(this.Location.X, pitch);
}
}
private void StopDrag(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDragging = false;
this.Location = new Point(this.Location.X, Locked_yLoc);
pitch = index;
//lbl8.Text = pitch.ToString();
}
}
private void OnDrag(object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Top = this.Top + (e.Y - pitch);
Locked_yLoc = (int)Math.Round((this.Top + (e.Y - pitch)) / 10.0) * 10;
for (int i = 0; i < yLocation.Length; i++)
{
if (Locked_yLoc == yLocation[i])
{
index = CorrPitch[i];
}
}
}
}
The Click
private void MusicNote_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
sp1.SoundLocation = this.pitch + ".wav";
sp1.Play();
tm1.Interval = 100 * this.noteDuration;
tm1.Start();
}
}
I am trying to make an application in which i have 7 Pictureboxes and i want to drag drop one each time i click then move the mouse on the form. I did make it to some extend by moving the picture-box on the form but i cannot keep the original image. When i drag drop a picture box i want to drag drop just a copy not the whole picture box on the form. Any help will be greatly appreciated. Kind regards.
public Form1()
{
controller = Controller.getController();
InitializeComponent();
this.AllowDrop = true;
this.pbOR.MouseDown += pbOR_MouseUp;
}
private void pbOR_MouseDown(object sender, MouseEventArgs e)
{
downPoint = e.Location;
pbOR.Parent = this;
pbOR.BringToFront();
}
private void pbOR_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pbOR.Left += e.X - downPoint.X;
pbOR.Top += e.Y - downPoint.Y;
}
}
private void pbOR_MouseUp(object sender, MouseEventArgs e)
{
Control c = GetChildAtPoint(new Point(pbOR.Left - 1, pbOR.Top));
if (c == null) c = this;
Point newLoc = c.PointToClient(pbOR.Parent.PointToScreen(pbOR.Location));
pbOR.Parent = c;
pbOR.Location = newLoc;
}
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]);
}
}