Solved

C# - Extending Drag and Drop Function even further

Posted on 2007-04-05
14
1,557 Views
Last Modified: 2008-01-09
Hey guys 'n gals,

I need some help extending a function yet again...

I want to know what I would need to modify my existing function, so that PictureBox's located in Panel1 can be dragged around, but cannot be dragged out of Panel1's range, so kind of locked inside. I have tried a few times myself, but keep on getting conflicts with the existing code...


If somebody could help me out here, I would highly appreciate it!

If I need to be more descriptive on what I am trying to achieve, please just let me know.

Here is the original code (working):



        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (Control ctl in panel2.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }
        }

        void ctl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startX = e.X;
                startY = e.Y;
                PictureBox source = (PictureBox)sender;
                pb = new PictureBox();
                pb.Size = source.Size;
                pb.Location = this.PointToClient(panel2.PointToScreen(source.Location));
                pb.Image = source.Image;
                this.Controls.Add(pb);
                pb.BringToFront();
            }
        }

        void ctl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
                startX = e.X;
                startY = e.Y;
            }
        }

        void ctl_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (pb.ClientRectangle.IntersectsWith(panel1.ClientRectangle))
                {
                    pb.Hide();
                    pb.Location = panel1.PointToClient(this.PointToScreen(pb.Location));
                    panel1.Controls.Add(pb);
                    pb.Show();
                }
                else
                {
                    pb.Dispose();
                }
                pb = null;
            }
        }
0
Comment
Question by:Cyber-Drugs
  • 7
  • 6
14 Comments
 
LVL 15

Expert Comment

by:dave4dl
ID: 18861244
check out http://en.csharp-online.net/Graphics,_Multimedia,_and_Printing_Recipes%E2%80%94Recipe_8_4 to see how to move stuff around.

Make sure that the e.X and e.Y are more than zero and less than the width and height (respectively) of the parent panel on mouseup.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 18861888
Here ya go...      (by the way, what version C# are you workin in?)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class VisioStyleDragDropForm : Form
    {
        public VisioStyleDragDropForm()
        {
            InitializeComponent();
        }

        Rectangle prevClip;
        PictureBox pb;
        int startX, startY;
       
        private void VisioStyleDragDropForm_Load(object sender, EventArgs e)
        {
            foreach (Control ctl in panel2.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }
        }

        void ctl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startX = e.X;
                startY = e.Y;
                PictureBox source = (PictureBox)sender;
                pb = new PictureBox();
                pb.Size = source.Size;
                pb.Location = this.PointToClient(panel2.PointToScreen(source.Location));
                pb.Image = source.Image;
                this.Controls.Add(pb);
                pb.BringToFront();
            }
        }

        void ctl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
                startX = e.X;
                startY = e.Y;
            }
        }

        void ctl_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (pb.ClientRectangle.IntersectsWith(panel1.ClientRectangle))
                {
                    pb.Hide();
                    pb.Location = panel1.PointToClient(this.PointToScreen(pb.Location));
                    panel1.Controls.Add(pb);
                    pb.Show();

                    pb.MouseDown += new MouseEventHandler(pb_MouseDown);
                    pb.MouseMove += new MouseEventHandler(pb_MouseMove);
                    pb.MouseUp += new MouseEventHandler(pb_MouseUp);
                }
                else
                {
                    pb.Dispose();
                }
                pb = null;
            }
        }

        void pb_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                prevClip = Cursor.Clip;
                Cursor.Clip = this.RectangleToScreen(new Rectangle(panel1.Location, panel1.Size));
                startX = e.X;
                startY = e.Y;
            }            
        }

        void pb_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                PictureBox pb = (PictureBox)sender;
                pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
            }
        }

        void pb_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Clip = prevClip;
            }            
        }

    }
}
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 18861890
You can do a similar thing with Cursor.Clip() to keep the "tools" from panel2 from being dragged off the form.

Let me know if you need help getting that squared away...
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18863435
Hi Idle_Mind,

I'm using VS 2005 Professional.

Just tried your code, it doesn't throw any errors, but does not work either...

I thought maybe I needed to add the extra foreach Control in panel1 to fix it, tried that and still nothing...

Here's what I added:

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (Control ctl in panel2.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }

            foreach (Control ctl in panel1.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(pb_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(pb_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(pb_MouseUp);
                }
            }
        }





As for Cursor.Clip(), do you mean I can prevent users from dragging objects to parts of the screen which I want to restrict, such as they can't drag off the form, and they can't drag past a certain x/y position?



Cheers for all the help thus far!
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 18863824
For my code above, start with a form. Then add panel1 on the right and leave it blank.  Add panel2 on the left and some PictureBoxes to it.  Set the Image properties on the PBs so you have some "tools".  Drag the tools from panel2 to panel1.  Now you should be able to drag the copied images around inside panel1 but not able to drag them outside its bound.  This works perfectly on my system (C# 2005 Express).

That is basically how Cursor.Clip() works.  You pass it a Rectangle and the cursor will stay inside that area.  I store the current clipping region on MouseDown() and then restore it on MouseUp().

"I thought maybe I needed to add the extra foreach Control in panel1 to fix it"

Nice try, but since the user is dynamically adding PictureBoxes to panel1 at run-time, this code in the Load() event isn't doing much!  =)
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18863928
Aha, I see what I did wrong, you added the function calls inside the MouseUp function from the original code!! And now the mouse is restricted!! That is brilliant, thank you VERY much yet again Idle_Mind!! Silly question for you though (slightly off-topic), how do you capture the onClick event and pass it to a new function, like you have done so with the MouseDown/MouseUp/MouseMove events?


Cheers!
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 18864337
Well...just wire it up in the ctl_MouseUp() method the same way as the others:
                   
                    pb.MouseDown += new MouseEventHandler(pb_MouseDown);
                    pb.MouseMove += new MouseEventHandler(pb_MouseMove);
                    pb.MouseUp += new MouseEventHandler(pb_MouseUp);
                    pb.Click += new EventHandler(pb_Click);

Then you have this stub to work with:

        void pb_Click(object sender, EventArgs e)
        {
            PictureBox pb = (PictureBox)sender;
            // do something with "pb"...
        }

Just remember that the MouseDown() event that is already wired up will fire first!  What do you want to happen in the Click() event?
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 18864360
You can also add extra functions for the PictureBoxes by assigning a ContextMenu to them.  Below I have added the ability to Delete the PBs after they have been placed:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class VisioStyleDragDropForm : Form
    {
        public VisioStyleDragDropForm()
        {
            InitializeComponent();
        }

        Rectangle prevClip;
        PictureBox pb;
        int startX, startY;
        ContextMenu cm = new ContextMenu();

        private void VisioStyleDragDropForm_Load(object sender, EventArgs e)
        {
            foreach (Control ctl in panel2.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }
            MenuItem delete = new MenuItem("Delete");
            delete.Click += new EventHandler(delete_Click);
            cm.MenuItems.Add(delete);
        }

        void delete_Click(object sender, EventArgs e)
        {
            MenuItem mi = (MenuItem)sender;
            ContextMenu cm = (ContextMenu)mi.GetContextMenu();
            PictureBox pb = (PictureBox)cm.SourceControl;
            pb.Dispose();
        }

        void ctl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                prevClip = Cursor.Clip;
                Cursor.Clip = this.RectangleToScreen(this.ClientRectangle);
                startX = e.X;
                startY = e.Y;
                PictureBox source = (PictureBox)sender;
                pb = new PictureBox();
                pb.Size = source.Size;
                pb.Location = this.PointToClient(panel2.PointToScreen(source.Location));
                pb.Image = source.Image;
                this.Controls.Add(pb);
                pb.BringToFront();
            }
        }

        void ctl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
                startX = e.X;
                startY = e.Y;
            }
        }

        void ctl_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Clip = prevClip;
                if (pb.ClientRectangle.IntersectsWith(panel1.ClientRectangle))
                {
                    pb.Hide();
                    pb.Location = panel1.PointToClient(this.PointToScreen(pb.Location));
                    panel1.Controls.Add(pb);
                    pb.ContextMenu = cm;
                    pb.Show();

                    pb.MouseDown += new MouseEventHandler(pb_MouseDown);
                    pb.MouseMove += new MouseEventHandler(pb_MouseMove);
                    pb.MouseUp += new MouseEventHandler(pb_MouseUp);
                }
                else
                {
                    pb.Dispose();
                }
                pb = null;
            }
        }

        void pb_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                prevClip = Cursor.Clip;
                Cursor.Clip = this.RectangleToScreen(new Rectangle(panel1.Location, panel1.Size));
                startX = e.X;
                startY = e.Y;
            }            
        }

        void pb_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                PictureBox pb = (PictureBox)sender;
                pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
            }
        }

        void pb_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Clip = prevClip;
            }            
        }

    }
}
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18864551
Idle_Mind,

I want to add a Selection box (border) to a picture with the onClick event, something I'm sure will be fairly easy, and I was also about to add a context menu for extra features like changing Z-Index and Delete with a few others... Seems you beat me to the punch!

Thank you veyr very much for all your help with this! I have another question open at the moment which nobody has had a look at, if you get a chance, maybe you have some ideas:


http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_22496236.html



Thanks again!!
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 18865065
Try this out...

Made it so the BorderStyle changes when you click on a PB.

I also noticed that if you move the mouse too fast while dragging the PBs in panel1 that the mouse would "escape" the PB and be moving in the panel instead of the PB...so I added some code that keeps the PB in sync with the mouse when that happens.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class VisioStyleDragDropForm : Form
    {
        public VisioStyleDragDropForm()
        {
            InitializeComponent();
        }

        bool pbDown = false;
        PictureBox selectedPB;
        Rectangle prevClip;
        PictureBox pb;
        int startX, startY;
        ContextMenu cm = new ContextMenu();

        private void VisioStyleDragDropForm_Load(object sender, EventArgs e)
        {
            prevClip = Cursor.Clip;
            foreach (Control ctl in panel2.Controls)
            {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }
            MenuItem delete = new MenuItem("Delete");
            delete.Click += new EventHandler(delete_Click);
            cm.MenuItems.Add(delete);
            panel1.Click += new EventHandler(panel1_Click);
            panel1.MouseMove += new MouseEventHandler(panel1_MouseMove);
        }

        void panel1_Click(object sender, EventArgs e)
        {
            if (selectedPB != null)
            {
                selectedPB.BorderStyle = BorderStyle.None;
                selectedPB = null;
            }
        }

        void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (selectedPB != null && pbDown)
            {
                System.Diagnostics.Debug.Print("Too Fast!...panel1_MouseMove(" + e.X.ToString() + ", " + e.Y.ToString() + ")");
                Point pt = panel1.PointToScreen(new Point(e.X, e.Y));
                pt = selectedPB.PointToClient(pt);
                MouseEventArgs mea = new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0);
                pb_MouseMove(selectedPB, mea);
            }
        }

        void delete_Click(object sender, EventArgs e)
        {
            MenuItem mi = (MenuItem)sender;
            ContextMenu cm = (ContextMenu)mi.GetContextMenu();
            PictureBox pb = (PictureBox)cm.SourceControl;
            pb.Dispose();
        }

        void ctl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Clip = this.RectangleToScreen(this.ClientRectangle);
                startX = e.X;
                startY = e.Y;
                PictureBox source = (PictureBox)sender;
                pb = new PictureBox();
                pb.Size = source.Size;
                pb.Location = this.PointToClient(panel2.PointToScreen(source.Location));
                pb.Image = source.Image;
                this.Controls.Add(pb);
                pb.BringToFront();
            }
        }

        void ctl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (pb != null)
                {
                    pb.Location = new Point(pb.Location.X + (e.X - startX), pb.Location.Y + (e.Y - startY));
                    startX = e.X;
                    startY = e.Y;
                }
            }
        }

        void ctl_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (pb != null)
                {
                    Cursor.Clip = prevClip;
                    if (pb.ClientRectangle.IntersectsWith(panel1.ClientRectangle))
                    {                        
                        pb.Hide();
                        pb.Location = panel1.PointToClient(this.PointToScreen(pb.Location));
                        panel1.Controls.Add(pb);
                        pb.ContextMenu = cm;
                        pb.Show();

                        pb.MouseDown += new MouseEventHandler(pb_MouseDown);
                        pb.MouseMove += new MouseEventHandler(pb_MouseMove);
                        pb.MouseUp += new MouseEventHandler(pb_MouseUp);
                    }
                    else
                    {
                        pb.Dispose();
                    }
                    pb = null;
                }
            }
        }

        void pb_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                pbDown = true;
                if (selectedPB != null)
                {
                    selectedPB.BorderStyle = BorderStyle.None;
                    selectedPB = null;
                }
                selectedPB = (PictureBox)sender;
                selectedPB.BorderStyle = BorderStyle.FixedSingle;
                selectedPB.BringToFront();
                Rectangle pnl = this.RectangleToScreen(new Rectangle(panel1.Location, panel1.Size));
                pnl.X = pnl.X + 1;
                pnl.Width = pnl.Width - 2;
                pnl.Y = pnl.Y + 1;
                pnl.Height = pnl.Height - 2;
                Cursor.Clip = pnl;
                startX = e.X;
                startY = e.Y;
            }            
        }

        void pb_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                PictureBox localPB = (PictureBox)sender;
                if (localPB == selectedPB)
                {
                    localPB.Location = new Point(localPB.Location.X + (e.X - startX), localPB.Location.Y + (e.Y - startY));
                }
            }
        }

        void pb_MouseUp(object sender, MouseEventArgs e)
        {
            pbDown = false;
            Cursor.Clip = prevClip;
        }

    }
}
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18867166
Maybe I copied something wrong, but I'm getting these errors:

Error      1      'System.Drawing.Point.x' is inaccessible due to its protection level      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      69      82      CartoLogix
Error      2      'System.Drawing.Point.y' is inaccessible due to its protection level      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      69      88      CartoLogix
Error      3      The name 'pnt' does not exist in the current context      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      157      31      CartoLogix
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18867194
Nevermind, it was a typo, but I have noticed a few flaws in the code...


Select a picturebox (adds a border)
Unselected the picturebox (moves top and left 1px)

also

right click a picturebox (brings a context menu)
click anywhere else to remove the context menu (a border is added to the picturebox)
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18867320
Fix for the first problem:

        void panel1_Click(object sender, EventArgs e)
        {
            if (selectedPB != null)
            {
                selectedPB.BorderStyle = BorderStyle.None;
                selectedPB.Location = new Point(selectedPB.Location.X + 1, selectedPB.Location.Y + 1);
                selectedPB = null;
            }
        }


working on a fix for the context menu issue as we speak.
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18867368
Ok, seems that change fixed the other bug at the same time, woo!


Just need to get my treeView code working, but while i'm waiting for replies on that, i'll start on my other features. Cheers for all the help Idle_Mind, you're very knowledgable and helpful! :o)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction                                                 Was the var keyword really only brought out to shorten your syntax? Or have the VB language guys got their way in C#? What type of variable is it? All will be revealed.   Also called…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now