Visual C#: Drag&Drop möglich?

Niranda

Welt-Boss
Registriert
13.05.2008
Beiträge
2.338
Reaktionspunkte
1
Kommentare
178
Hey,
ich suche eine Möglichkeit folgendes zu realisieren.
Dazu erstmal ein Bild der Oberfläche:

http://dve.kilu.de/projekt/pic_st_v0.02a.jpg

Es sollen Widerstände (dargestellt als simple Rechtecke) aus der Gruppe "Halter" in die Gruppe "Schaltung" vom User verschoben werden können.
Die Position der 3 Widerstände ist in beiden Gruppen festgelegt.
Sprich es findet in der Gruppe "Schalter" nur jeweils 1 Widerstand in einer Lücke platz - und nur in einer Lücke. Wird der Widerstand falsch platziert, so rutscht er automatisch wieder auf seine Ursprungsposition.
In der Gruppe "Halter" sind ebenfalls vordefinierte Positionen festgelegt, auf die jeweils 1 Widerstand platz findet.

Zudem muss kontrolliert werden können, welcher Widerstand auf welcher Position liegt, damit dies später auch richtig ausgewertet/-rechnet werden kann.

Ich hoffe bis hier war das Verständlich. ^^

LG
Nira

PS:
Der Schaltplan in der Gruppe "Schaltung" ist ein Bild in einer PictureBox.

PPS:
Jaja, einschlägige Foren besuchen - leider sind die nicht sooo aktiv:
http://social.msdn.microsoft.com/Forums/de...93-b47baed74d8a
 
Naja - Deine Widerstaende sind ja wahrscheinlich eigene Bilder. Wenn der User diese verschiebt und loslaesst (also "drop") muss das Programm dann einfach die Position des Widerstands pruefen und wenn diese Position nicht innerhalb der "Soll-Toleranz" liegt, dann setzt Du den Widerstand zurueck auf die Halter-Position...
 
Ja genau so mein ich das ja^^ Danke =)
Bloß die tollste Frage der Welt ist leider noch nicht beantwortet:

Wie? :<
 
Du hast ja ein Event beim Loslassen des Mausknopfes. In diesem ueberpruefst Du dann die Positionen Deiner Widerstaende (keine Ahnung - des Image.position-Attribut falls das bei C# so heisst) und wenn die nicht so sind wie Du sie haben willst setzt Du sie auf Deine Wunsch-Positionen zurueck.

Waere sicher hilfreich, wenn Du sagen wuerdest, was genau Du nicht weisst...
 
Ich nehme mal an, die Schaltungen oder was auch immer du da auf der rechten Seite hast, liegen auch in Form von Images vor, oder?
Das Problem ist, daß du links in der PictureBox soweit ich weiß keine Möglichkeit hast, deine Images, die du rüberziehen möchtest, zu positionieren.

Du könntest aber über die PictureBox nochmals PictureBoxen legen und die dann z.b. transparent machen. Und dann für die Images Keys vergeben, die du dann prüfst und den PictureBoxen zuordnest. Nichts besseres ist mir jetzt auf die Schnelle auch nicht eingefallen. Oder du pinselst in die PictureBox. Dann wird es aber mit dem Drag'n Drop etwas problematisch. Mit mehreren PictureBoxen könnte es dann so in etwa aussehen.

Code:
namespace DragNDrop
{
	public partial class Form1 : Form
	{
		private MyImage m_img;
	 
		private struct MyImage
		{
			private string key;
			private Image img;
			
			public MyImage(string Key)
			{
				this.key = Key;
				this.img = Image.FromFile("C:\\Documents and Settings\\twerner\\My Documents\\My Pictures\\Lupe.gif");
			}
			public Image Img
			{
				get { return this.img; }
			}
			public string Key
			{
				get { return this.key; }
			}
		}
		public Form1()
		{
			InitializeComponent();

			pictureBox1.AllowDrop = true;
			pictureBox2.AllowDrop = true;
			
			pictureBox1.DragEnter += new DragEventHandler(pic_DragEnter);
			pictureBox1.DragDrop += new DragEventHandler(pic_DragDrop);
			pictureBox1.MouseDown += new MouseEventHandler(pic_MouseDown);
			pictureBox2.DragEnter += new DragEventHandler(pic_DragEnter);
			pictureBox2.DragDrop += new DragEventHandler(pic_DragDrop);
			pictureBox2.MouseDown += new MouseEventHandler(pic_MouseDown);
			pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
   
		}
		void pictureBox1_Paint(object sender, PaintEventArgs e)
		{
			m_img = new MyImage("LupeTest2");
			pictureBox1.Image = m_img.Img;
		}
		void pic_MouseDown(object sender, MouseEventArgs e)
		{
			PictureBox pic = (PictureBox)sender;
		 
			if (pic.Image != null)
				pic.DoDragDrop(pic.Image, DragDropEffects.Move);
		}
		void pic_DragDrop(object sender, DragEventArgs e)
		{
			PictureBox pic = (PictureBox)sender;
			Image img = (Image)e.Data.GetData(DataFormats.Bitmap);
			if (m_img.Key == "LupeTest1")
			{
				pictureBox3.Image = img;
			}
			else
			{
				pictureBox4.Image = img;
			}
		}
		void pic_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.Bitmap))
			{
				e.Effect = DragDropEffects.Move;
			}
			else
			{
				e.Effect = DragDropEffects.None;
			}
		}
	}
}
Für deinen Fall würde ich halt die Images noch in ner Collection verwalten.
 
Zuletzt bearbeitet von einem Moderator:
Hab es eben Zuhause nochmal versucht. Also PictureBox in PictureBox macht Probleme:) Hätte ich mir auch denken können. Aber du kannst die PictureBox beispielsweise durch einen Panel austauschen. Dann geht es einwandfrei. Und das Image kannst du ja trotzdem wieder reinladen, ist ja kein Problem.

Der folgende Code ist zwar nicht sonderlich intuitiv, aber funktioniert. Ob es dir weiterhilft, weiß nicht:)

Es sind zwei Panels mit je drei PictureBoxen, die transparent gehalten sind. Sie sind also nicht sichtbar, nur das Icon ist ersichtlich. Es gibt deren drei verschiedene und jedes hat in meinen Fall jetzt einen Farbcode. Und den prüf ich einfach ab und setze das Icon entsprechend. Man kann es hier nur in der entsprechenden Box fallen lassen, sonst bleibt es am Ursprung.

Eine Prüfung, ob eine PictureBox besetzt ist, sprich, in deinem Fall die Schaltung gesetzt ist, wäre so nun auch kein Problem mehr.

Edit: sollte es dich stören, daß man so das Icon erst ablegen kann, wenn man in die entsprechende PictureBox eintritt, dann musst du halt das DragEnter-Event des Panels abonnieren. Sollte ja kein Problem sein. Und dann prüfst du die Membervarialbe, sprich den Key des Dictionarys, holst dir mit dem Key das entsprechende Icon aus der Collection und lässt es in die entsprechende PictureBox plumsen.

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

namespace DragNDrop
{
	public partial class Form1 : Form
	{
		Dictionary<string, Image> m_myImgCol;
		string m_currentKey;
		
		public Form1()
		{
			InitializeComponent();

			Image img = Image.FromFile("C:\\Users\\Public\\Pictures\\Sample Pictures\\Humpback Whale.jpg");
			Image trialImg1 = Image.FromFile("C:\\Users\\Togge\\Pictures\\icons_win\\blau_butterfly_win.ico");
			Image trialImg2 = Image.FromFile("C:\\Users\\Togge\\Pictures\\icons_win\\green_butterfly_win.ico");
			Image trialImg3 = Image.FromFile("C:\\Users\\Togge\\Pictures\\icons_win\\rot_butterfly_win.ico");

			panel1.BackgroundImage = img;
			panel2.BackgroundImage = img;

			foreach (PictureBox item in panel1.Controls)
			{
				((PictureBox)item).BackColor = Color.Transparent;
				((PictureBox)item).AllowDrop = true;
				((PictureBox)item).DragEnter += new DragEventHandler(pic_DragEnter);
				((PictureBox)item).DragDrop += new DragEventHandler(pic_DragDrop);
				((PictureBox)item).MouseDown += new MouseEventHandler(pic_MouseDown);
				((PictureBox)item).BorderStyle = BorderStyle.FixedSingle;
			}
			foreach (PictureBox item in panel2.Controls)
			{
				((PictureBox)item).BackColor = Color.Transparent;
				((PictureBox)item).AllowDrop = true;
				((PictureBox)item).DragEnter += new DragEventHandler(pic_DragEnter);
				((PictureBox)item).DragDrop += new DragEventHandler(pic_DragDrop);
				((PictureBox)item).MouseDown += new MouseEventHandler(pic_MouseDown);
				((PictureBox)item).BorderStyle = BorderStyle.FixedSingle;
			}
			m_myImgCol = new Dictionary<string, Image>();
			m_myImgCol.Add("blau", trialImg1);
			m_myImgCol.Add("green", trialImg2);
			m_myImgCol.Add("rot", trialImg3);

			pictureBox1.Image = m_myImgCol["blau"];
			pictureBox2.Image = m_myImgCol["green"];
			pictureBox3.Image = m_myImgCol["rot"];
		}

		void pic_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.Bitmap))
			{
				e.Effect = DragDropEffects.Move;
			}
			else
			{
				e.Effect = DragDropEffects.None;
			}
		}
		void pic_DragDrop(object sender, DragEventArgs e)
		{
			PictureBox pic = (PictureBox)sender;
			Image image = (Image)e.Data.GetData(DataFormats.Bitmap);
			if (m_currentKey == "blau" && (pic == pictureBox1 || pic == pictureBox4))
			{
				pic.Image = m_myImgCol[m_currentKey];
				if (pic == pictureBox1)
				{
					pictureBox4.Image = null;
				}
				else
				{
					pictureBox1.Image = null;
				}
			}
			if (m_currentKey == "green" && (pic == pictureBox2 || pic == pictureBox5))
			{
				pic.Image = m_myImgCol[m_currentKey];
				if (pic == pictureBox2)
				{
					pictureBox5.Image = null;
				}
				else
				{
					pictureBox2.Image = null;
				}
			}
			if (m_currentKey == "rot" && (pic == pictureBox3 || pic == pictureBox6))
			{
				pic.Image = m_myImgCol[m_currentKey];
				if (pic == pictureBox3)
				{
					pictureBox6.Image = null;
				}
				else
				{
					pictureBox3.Image = null;
				}
			}
		}
		void pic_MouseDown(object sender, MouseEventArgs e)
		{
			PictureBox pic = (PictureBox)sender;
		  
			if (pic.Image != null)
			{
				if (pic == pictureBox1 || pic == pictureBox4)
				{
					m_currentKey = "blau";
				}
				else if(pic == pictureBox2 || pic == pictureBox5)
				{
					m_currentKey = "green";
				}
				else if (pic == pictureBox3 || pic == pictureBox6)
				{
					m_currentKey = "rot";
				}
				pic.DoDragDrop(pic.Image, DragDropEffects.Move);
			}
		 }
	}
   
}
Eine Alternative wäre höchstens, daß Zeug mit einem Graphic-Object selbst zu pinseln. Dann ist der Aufwand aber ungleich höher, weil du DragNDrop komplett selbst implementieren müsstest. Glaube ich zumindest:)

Edit: jojo, hast ja recht:)
 
Zuletzt bearbeitet von einem Moderator:
Klos,

Code:
es gibt 
   ein code-Tag
	   da bleibt auch deine Einrückung
		   erhalten
biggrin.gif
 
Zuletzt bearbeitet von einem Moderator:
Danke Klos
smile.gif

Find leider nicht die Zeit mich damit zu befassen... werd bzw muss ich aber noch^^

LG
Nira (=
 
Nach dem ich gerade viel Zeit habe, habe ich nochmals etwas gebastelt. Es zeigt nun haargenau das Verhalten, was du wahrscheinlich wolltest.
Ich habe mir für dieses Beispiel eine Multipicture-Box gebaut, die von Control erbt. Mit der normalen .Net-PictureBox hast du hier keine Chance.

Mit dieser Multipicture-Box kannst du nun aber mehrere Images in der Box verwalten und sie auch positionsmäßig ausrichten. In dem Beispiel verwende ich wieder drei Images, die nach Farbe bestimmt werden.

Wenn du eines anklickst, dann ändert sich der Cursor nun, sobald du damit in die zweite MultipictureBox eintrittst. Du kannst das Image dann einfach fallen lassen, es positioniert sich an der richten Stelle.

Ich habe hier ein eigenes Objekt vom Typ ImageWithBounds vorgesehen, daß die benötigten Daten speichert.

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

namespace DragNDrop
{
	public partial class Form1 : Form
	{
		//private members
		private MultiPictureBox m_pic1;
		private MultiPictureBox m_pic2;
		private bool m_isMaximized = true;
		private int m_SendingBox;
		
		public Form1()
		{
			InitializeComponent();

			//initialize the controls
			m_pic1 = new MultiPictureBox();
			m_pic1.AllowDrop = true;
			m_pic1.BackColor = Color.White;

			m_pic1.Location = new Point(10, 10);
			m_pic1.Size = new Size(300, this.ClientSize.Height - 20);
			
			m_pic2 = new MultiPictureBox();
			m_pic2.AllowDrop = true;
			m_pic2.BackColor = Color.White;

			m_pic2.Location = new Point(this.ClientSize.Width - (m_pic1.Width + 10), 10);
			m_pic2.Size = new Size(300, this.ClientSize.Height - 20);

			this.Controls.Add(m_pic1);
			this.Controls.Add(m_pic2);

			//events
			this.SizeChanged += new EventHandler(Form1_SizeChanged);
			m_pic1.DragDrop += new DragEventHandler(m_pic_DragDrop);
			m_pic1.DragEnter += new DragEventHandler(m_pic_DragEnter);
			m_pic1.MouseDown += new MouseEventHandler(m_pic_MouseDown);
			m_pic2.DragDrop += new DragEventHandler(m_pic_DragDrop);
			m_pic2.DragEnter += new DragEventHandler(m_pic_DragEnter);
			m_pic2.MouseDown += new MouseEventHandler(m_pic_MouseDown);

			ImageWithBounds Pic1Blue;
			ImageWithBounds Pic2Red;
			ImageWithBounds Pic3Yellow;
			
			Rectangle rectInnerBounds = new Rectangle(new Point(10, 10), new Size(20, 20));
		   

			for (int i = 0; i < 3; i++)
			{
				switch (i)
				{ 
					case 0:
					   
						Pic1Blue = new ImageWithBounds();
						Pic1Blue.pImage = Image.FromFile("C:\\Documents and Settings\\twerner\\My Documents\\My Pictures\\icons_win\\blau_butterfly_win.ico");
						Pic1Blue.pName = "blue";
						Pic1Blue.pBounds = rectInnerBounds;
						
						m_pic1.pImages.Add(Pic1Blue);
						
						break;
					
					case 1:
					   
						Pic2Red = new ImageWithBounds();
						Pic2Red.pImage = Image.FromFile("C:\\Documents and Settings\\twerner\\My Documents\\My Pictures\\icons_win\\rot_butterfly_win.ico");
						Pic2Red.pName = "red";

						rectInnerBounds.Y = rectInnerBounds.Y + 100;
						
						Pic2Red.pBounds = rectInnerBounds;

						m_pic1.pImages.Add(Pic2Red);

						break;
				   
					case 2:
						
						Pic3Yellow = new ImageWithBounds();
						Pic3Yellow.pImage = Image.FromFile("C:\\Documents and Settings\\twerner\\My Documents\\My Pictures\\icons_win\\gelb_butterfly_win.ico");
						Pic3Yellow.pName = "yellow";

						rectInnerBounds.Y = rectInnerBounds.Y + 100;
						
						Pic3Yellow.pBounds = rectInnerBounds;

						m_pic1.pImages.Add(Pic3Yellow);

						break;
				}
			}
		}
		void m_pic_DragDrop(object sender, DragEventArgs e)
		{
			MultiPictureBox pic = (MultiPictureBox)sender;
			if (pic == m_pic2 && m_SendingBox == 1)
			{
				m_pic2.pImages.Add((ImageWithBounds)e.Data.GetData(typeof(ImageWithBounds)));
				m_pic1.pImages.Remove((ImageWithBounds)e.Data.GetData(typeof(ImageWithBounds)));
			}
			else
			{
				m_pic1.pImages.Add((ImageWithBounds)e.Data.GetData(typeof(ImageWithBounds)));
				m_pic2.pImages.Remove((ImageWithBounds)e.Data.GetData(typeof(ImageWithBounds)));
			}
		}
		void m_pic_MouseDown(object sender, MouseEventArgs e)
		{
			MultiPictureBox pic = (MultiPictureBox)sender;
			Point pt = new Point(e.Location.X, e.Location.Y);

			//is needed, in order to store, which is the target box
			if (pic == m_pic1)
			{
				m_SendingBox = 1;
			}
			else
			{
				m_SendingBox = 2;
			}
			
			foreach (ImageWithBounds item in pic.pImages)
			{
				switch (item.pName)
				{ 
					case "blue":

						if ((pt.X >= item.pBounds.X && pt.X <= item.pBounds.X + item.pBounds.Width)
							&& (pt.Y >= item.pBounds.Y && pt.Y <= item.pBounds.Y +
							item.pBounds.Height))
						{
							//cursor hits the blue image
						  
							pic.DoDragDrop(item, DragDropEffects.Move);

							return;
						}

						break;
					case "red":

						if ((pt.X >= item.pBounds.X && pt.X <= item.pBounds.X + item.pBounds.Width)
							&& (pt.Y >= item.pBounds.Y && pt.Y <= item.pBounds.Y +
							item.pBounds.Height))
						{
							//cursor hits the red image
						  
							pic.DoDragDrop(item, DragDropEffects.Move);

							return;
						}

						break;
					case "yellow":

						if ((pt.X >= item.pBounds.X && pt.X <= item.pBounds.X + item.pBounds.Width)
							&& (pt.Y >= item.pBounds.Y && pt.Y <= item.pBounds.Y +
							item.pBounds.Height))
						{
							//cursor hits the yellow image
						  
							pic.DoDragDrop(item, DragDropEffects.Move);

							return;
						}
						break;
				}
			}
		}

		void m_pic_DragEnter(object sender, DragEventArgs e)
		{
			if ((MultiPictureBox)sender == m_pic2 && m_SendingBox == 1)
			{
				if (e.Data.GetDataPresent(typeof(ImageWithBounds)))
				{
					e.Effect = DragDropEffects.Move;
				}
			}
			else if((MultiPictureBox)sender == m_pic1 && m_SendingBox == 2)
			{ 
				if (e.Data.GetDataPresent(typeof(ImageWithBounds)))
				{
					e.Effect = DragDropEffects.Move;
				}
			}
		}
		void Form1_SizeChanged(object sender, EventArgs e)
		{
			//redraw the controls if the size of the form has changed
			if (m_isMaximized)
			{
				m_isMaximized = false;

				m_pic1.Location = new Point(10, 10);
				m_pic1.Size = new Size(500, this.ClientSize.Height - 20);

				m_pic2.Location = new Point(this.ClientSize.Width - (m_pic1.Width + 10), 10);
				m_pic2.Size = new Size(500, this.ClientSize.Height - 20);
			}
			else
			{
				m_isMaximized = true;

				m_pic1.Location = new Point(10, 10);
				m_pic1.Size = new Size(300, this.ClientSize.Height - 20);

				m_pic2.Location = new Point(this.ClientSize.Width - (m_pic1.Width + 10), 10);
				m_pic2.Size = new Size(300, this.ClientSize.Height - 20);

			}
		}
	}
	

	public class MultiPictureBox : Control
	{ 
		//the collection, which is used to store our images
		private ImageWithBoundsCollection m_Images = new ImageWithBoundsCollection();

		//read-only access to the images collection 
		public ImageWithBoundsCollection pImages
		{
			get { return m_Images; }
		}
		//to display the picture name or not
		private bool m_bShowNames = false;

		public bool pbShowNames
		{
			get { return m_bShowNames; }
			set 
			{ 
				m_bShowNames = value;
				OnShowNamesChanged(EventArgs.Empty);
			}
		}

		public MultiPictureBox()
		{
			//called, if the count of the image collection has changed
			m_Images.CollectionChanged += new EventHandler(m_Images_CollectionChanged);
		}

		void m_Images_CollectionChanged(object sender, EventArgs e)
		{
			//the count of images has changed, so we have to redraw the control
			Invalidate();
		}

		#region Overridden functions

		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);

			//draw the images in the multipicture box
			foreach (ImageWithBounds image in m_Images)
			{
				if (image.pImage == null)
					continue;
				
				e.Graphics.DrawImage(image.pImage, image.pBounds);
				
				if (m_bShowNames && !string.IsNullOrEmpty(image.pName))
				{
					e.Graphics.DrawString(image.pName, SystemFonts.DefaultFont, Brushes.Black,
						new PointF(image.pBounds.X, image.pBounds.Y + image.pBounds.Height));
				}
			}
		}

		#endregion

		protected virtual void OnShowNamesChanged(EventArgs e)
		{
			Invalidate();

			EventHandler handler = ShowNamesChanged;
			if (handler != null)
				handler(this, e);
		}

		public event EventHandler ShowNamesChanged;
	}
	//this class store an image object
	public class ImageWithBounds
	{
		
		private string m_Name;
		
		public string pName
		{
			get { return m_Name; }
			set { m_Name = value; }
		}

		private Image m_Image;
		public Image pImage
		{
			get { return m_Image; }
			set { m_Image = value; }
		}

		private Rectangle m_Bounds;
		public Rectangle pBounds
		{
			get { return m_Bounds; }
			set 
			{ 
				m_Bounds = value; 
				
			}
		}
	}
	//the collection, which stores the images of the control
	public class ImageWithBoundsCollection : KeyedCollection<string, ImageWithBounds>
	{
		protected override string GetKeyForItem(ImageWithBounds item)
		{
			return item.pName;
		}

		protected override void InsertItem(int index, ImageWithBounds item)
		{
			base.InsertItem(index, item);
			OnCollectionChanged(EventArgs.Empty);
		}

		protected override void RemoveItem(int index)
		{
			base.RemoveItem(index);
			OnCollectionChanged(EventArgs.Empty);
		}

		protected virtual void OnCollectionChanged(EventArgs e)
		{
			EventHandler handler = CollectionChanged;
			if (handler != null)
				handler(this, e);
		}

		public event EventHandler CollectionChanged;
	}

	
}
 
Zuletzt bearbeitet von einem Moderator:
Zurück