Laden...

Drag event bei ESC abbrechen; Drop ausserhalb des Fensters kein Absturz; Drop in andere Anwendung?

Erstellt von Frokuss vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.320 Views
F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren
Drag event bei ESC abbrechen; Drop ausserhalb des Fensters kein Absturz; Drop in andere Anwendung?

Hallo Leute,

ich setze mich jetzt aktuell seit ein paar Stunden mit dem Drag and Drop auseinander (mal wieder). Ich habe jetzt mal ein wenig experimentiert und bin dabei an meine Grenzen gestoßen...

Dabei bin ich auf mehrere Probleme gestoßen:
1.) beim drücken von ESC sollte das Drag-Event eigentlich abbrechen... Das QueryContinueDrag -Event wird auch gefeuert... Allerdings wird das DragDrop-Event trotz losgelassener Maustaste (nach dem ESC) beim MouseEnter ausgeführt... Keine Ahnung warum...

2.) Wenn ich den Drop-Auserhalb meines Fensters mache (z.B: Desktop-Oberfläche), muss ich über den Taskmanager nen kill machen...

Folgende Events habe ich erstellt / und mehreren Elementen zugewiesen:

//foreach(KeyValuePair<int, Control>kl in myDic){
//Event ist notwendig um Click und Drag zu differenzieren
kl.Value.liste.objChildsHeadline.MouseDown += new MouseEventHandler(Evt_MouseDown);

//Beim MouseMove wird das Drag-Event gestartet
kl.Value.liste.objChildsHeadline.MouseMove += new MouseEventHandler(Evt_DragStart);

//Event ist notwendig um Click und Drag zu differenzieren
kl.Value.liste.objChildsHeadline.MouseUp += new MouseEventHandler(Evt_MouseUp);

//Wenn der Drag losgelassen wird
kl.Value.liste.objChildsHeadline.DragDrop += new DragEventHandler(Evt_DragDrop);

//"Drag-MouseEnter"
kl.Value.liste.objChildsHeadline.DragEnter += new DragEventHandler(Evt_DragEnter);

//Das Event feuert, aber macht nichts...
kl.Value.liste.objChildsHeadline.QueryContinueDrag += new QueryContinueDragEventHandler(Evt_DragAbbrechen);
//}

Und dazu einmal die Methoden (reduziert und ohne ClickEvent):


		private void Evt_MouseDown(object sender, MouseEventArgs evt){
			isMouseDown = true;
		}
		
		private void Evt_MouseUp(object sender, MouseEventArgs evt){
			isMouseDown = false;
		}

		private void Evt_DragStart(object sender, MouseEventArgs evt){
			if(isMouseDown){
				Control c = (Control)sender;
				string val;
				
				val = c.Text;
				c.DoDragDrop(val, DragDropEffects.Copy | DragDropEffects.Move);
			}
		}

		public void Evt_DragEnter(object sender, DragEventArgs evt){
			if(evt.Data.GetDataPresent(DataFormats.Text)){
				string[] values = Daten.GetStringValues(evt.Data.GetData(DataFormats.Text, true).ToString());
				evt.Effect = DragDropEffects.Copy;
			}
			else  
				evt.Effect = DragDropEffects.None;
		}

//Dieses Event wird trotz des ESC drücken ausgeführt
		public void Evt_DragDrop(object sender, DragEventArgs evt){
			isMouseDown = false;
//mache was mit dem Drop....
		}

//Dieses Event scheint nicht das Drag-Event abzugrechen beim "ESC" drücken...
		private void Evt_DragAbbrechen(object sender, QueryContinueDragEventArgs evt){
			if(evt.EscapePressed){
				evt.Action = DragAction.Cancel;
//Hier war mal eine Testausgabe - die angezeigt wurde...
			}
		}

Meine Fragen sind daher:
1.) Was muss ich beachten, damit das Drag-Event beim ESC drücken auch wirklich abgebrochen wird?
2.) a.) Wie kann ich verhindern, das beim droppen auserhalb des Fensters meine Anwendung nicht abstürzt?
2.) b.) Und wie kann ich es trotzdem ermöglichen, dass ich in einem anderen Fenster (auch aus meiner Anwendung) etwas droppen kann? Soweit bin ich allerdings noch nicht, dass ich dies irgendwie testen könnte...

Ich hoffe ihr könnt mir da irgendwie weiterhelfen...
Liebe Grüße Frokuss

C
2.121 Beiträge seit 2010
vor 4 Jahren

Ich habe zwar schon etwas mit D&D gemacht, aber es ist schon etwas her und das Thema fand ich damals nicht selbsterklärend.
Details weiß ich spontan leider nicht mehr. Könnte mir aber vorstellen dass es normal ist, in jedem Fall ein DragDrop Event zu erhalten. Schließlich lässt der Nutzer die Maus los, egal ob dann gedroppt wird oder ob das inzwischen abgebrochen wurde.
Steht in den DragEventArgs nichts hilfreiches darüber? Dann müsstest du im Abbruchfall in diesem Event einfach nichts weiter machen.

Würde dir raten, ein Beispiel zu suchen und das unter die Lupe zu nehmen.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Sooo Leute, habe mal etwas Zeit gehabt und mich etwas intensiver damit beschäfftigt. Allerdings ist mir das noch nicht zu 100% klar warum wieso und weshalb das alles so zueinander wirkt. Im Folgenden bitte nur berücksichtigen, dass ich keine IT-Ausbildung habe... Auf gehts:

Zunächst brauchen wir einmal 2 Controls, z.B. Labels die irgendwie dem Form zugeführt werden

Label starter = new Label();
Label ziel = new Label();

nach dem Microsoft Gedanken, können wir wiefolgt unseren Drag-Prozess starten (ist jetzt nicht von der Webseite kopiert):

starter.Click += new EventHandler(Evt_DragEventStarten);
public void Evt_DragEventStarten(object sender, EventArgs evt){
  Label l = (Label)sender;
  l.DoDragDrop(val, DragDropEffects.Copy | DragDropEffects.Move);
}

Das Problem hierbei ist, dass diese Arbeitsweise allerdings das Click-Event abwürgt. Daher die Events haben folgende Reihenfolger beim Triggern:

  • MouseDown-Event
  • Click-Event
  • MouseUp-Event
    Daher, das Click und das MouseUp-Event werden "abgewürgt".

Aus dem Grund habe ich nach einer Alternative gesucht. Das bedeutet, dass das Drag-Event erst später starten darf um zu differenzieren, ob ich nun Clicken oder Draggen möchte...

Aus dem Grund habe ich Folgendes gemacht:


bool isMouseDown = false;

starter.MouseDown += new MouseEventHandler(Evt_MouseDown);
starter.MouseUp += new MouseEventHandler(Evt_MouseUp);
starter.MouseMove += new MouseVentHandler(Evt_DragStarten);

private void Evt_MouseDown(object sender, MouseEventArgs evt){
  isMouseDown = true;
}

private void Evt_MouseUp(object sender, MouseEventArgs evt){
  isMouseDown = false;
}

//Startet DoDragDrop wenn die Maustaste gedrückt gehalten ist und dann die Maus bewegt wird
private void Evt_DragStarten(object sender, MouseEventArgs evt){
  if(isMouseDown){
    Label l = (Label)sender;
    string val = "Dies sind meine Beispieldaten, die ich übertragen möchte";
    l.DoDragDrop(val, DragDropEffects.Copy | DragDropEffects.Move);
  }
}

Zwischen dem MouseDown-Event und dem MouseMove-Event gibt es nun Wechselwirkungen. Wenn der Anwender einen Klick durchführt, wird in der Regel die Mouse im Klick-Prozess nicht bewegt. Wird sie allerdings im Klick-Prozess bewegt, treffe ich hier die Annahme, dass der Anwender das Element draggen will. Daher wird bei gedrückter Maustaste das Drag-Event gestartet.

Hieraus ergibt sich allerdings wieder ein neues Problem, Da hier ein MouseMove-Event verwendet wurd, wird dies im übertragenen Sinne unaufhaltsam getriggert. Also braucht das Event Evt_DragStarten auch eine Hilfsvariable um dieses Verhalten zu begrenzen (Anmerkgung: Ich habe mehrere Elemente die gedragget werden können die auch zugleich ein Drop-Ziel sein können:

bool isDragStarted = false;

private void Evt_DragStarten(object sender, MouseEventArgs evt){
  if(isMouseDown && !isDragStarted){//geändert
    Label l = (Label)sender;
    string val = "Dies sind meine Beispieldaten, die ich übertragen möchte";
    l.DoDragDrop(val, DragDropEffects.Copy | DragDropEffects.Move);

    isDragStarted = true;//hinzugefügt
  }//ab hier hinzugefügt
  else if(!isMouseDown && isDragStarted){
    isDragStarted = false;
  }
}

Und genau an dieser Stelle habe ich etwas eigenartiges festgestellt: So wie ich Evt_DragStarten aufgebaut habe, wird dieses genau 2 mal ausgeführt... An sich nicht eigenartig. Allerdings veränderte sich der Mauszeiger mit der Mausbewegung, meine Hilfs-MessageBoxen wurden hingegen erst nach dem Ausführen des Drop-Events angezeigt... Keine Ahnung warum.

Theoretisch würde das ganze jetzt an dieser Stelle ganz gut funktionieren - sofern die Drop-Methode implementiert wäre; Allerdings möchte der Anwender eventuell auch den Drop-Vorgang abbrechen... Dafür brauchen wir mal wieder eine weitere Hilfsvariable... Eventuell gehts auch mit nur 2 Variablen aber das war mir jetzt etwas zu viel Fummelarbeit...

//Die Namen können minimal abweichen, da ich nun aus meinem Code kopiere!

bool isMouseDown = false;
bool isDragStarted = false;
bool isDragCancle = false;

starter.MouseDown += new MouseEventHandler(Evt_MouseDown);
starter.MouseMove += new MouseEventHandler(Evt_DragStart);
starter.MouseUp += new MouseEventHandler(Evt_MouseUp);
starter.DragDrop += new DragEventHandler(Evt_DragDrop);
starter.DragEnter += new DragEventHandler(Evt_DragEnter);
starter.QueryContinueDrag += new QueryContinueDragEventHandler(Evt_DragAbbrechen);
starter.DragLeave += new EventHandler(Evt_DragLeave);//relevant, wenn man in DragEnter den Style des Objektes verändert...

		private void Evt_MouseDown(object sender, MouseEventArgs evt){
			//Eventuelle Prüfung der Maustaste (Primärtaste [idR die rechte])
			isMouseDown = true;
			isDragCancle = false;
		}

		private void Evt_MouseUp(object sender, MouseEventArgs evt){
			//Eventuelle Prüfung der Maustaste (Primärtaste [idR die rechte]) siehe Evt_MouseDown
			isMouseDown = false;
		}

		private void Evt_DragStart(object sender, MouseEventArgs evt){
			if(isMouseDown && !isDragStarted && !isDragCancle){
				Control c = (Control)sender;
				string val =  c.Text;
				
				c.DoDragDrop(val, DragDropEffects.Copy | DragDropEffects.Move);
				isDragStarted = true;
			}
			else if(!isMouseDown && isDragStarted){
				isDragStarted = false;
			}
		}

public void Evt_DragEnter(object sender, DragEventArgs evt){
//irgendwelche Styles... oder z.B:
//evt.Effect = DragDropEffects.None;
//evt.Effect = DragDropEffects.Copy;
}

		public void Evt_DragDrop(object sender, DragEventArgs evt){
			isMouseDown = false;
			
			if(!isDragCancle){
				MessageBox.Show(evt.Data.GetData(DataFormats.Text, true).ToString());
			}
		}

		private void Evt_DragLeave(object sender, EventArgs evt){
//Styles "Rückgängig machen
		}
		
		private void Evt_DragAbbrechen(object sender, QueryContinueDragEventArgs evt){
			if(evt.EscapePressed){
				evt.Action = DragAction.Cancel;
				isDragCancle = true;
			}
		}

Das ist jetzt mein Code stark reduziert. Vielleicht noch hilfreich zu erwähnen wäre, dass bei einem Abbrechen (über ESC-Taste) das MouseDown-Event auf jeden Fall getriggert wird. Das Click-Event wird hingegen nur getriggert, wenn die Maus sich auf dem gleichen Objekt befindet, auf dem das MouseDown-Event getriggert wurde...

Ich hoffe es wird irgendwann mal jemanden helfen sich in diesem Wald zurecht zu finden. Und wenn einer sich frei fühlt ein Tutorial draus zu machen, gerne, kopiert so viel ihr wollt 😄

Grüße Frokuss

PS: Es könnten durch aus Fehler enthalten sein, da ich vieles direkt im Browserfenster geschrieben habe...

EDIT: In meiner Version habe ich mit einem Objekt gearbeitet, welches vom Label erbt und bereits dort ein Klick-Event zugewiesen wurde. Aus dem Grund taucht hier nirgendswo das Click-Event auf.

C
2.121 Beiträge seit 2010
vor 4 Jahren

Dass man beim Start von D&D erst auf eine Bewegung wartet um den normalen Klick zu unterscheiden, ist normale Vorgehensweise.

Sobald DoDragDrop aufgerufen wird, passiert meines Wissens alles innerhalb dieser Routine, bis die Maus losgelassen wird. Ich vermute du hast da noch ein Problem mit den vielen Hilfsvariablen. So kompliziert muss das eventuell gar nicht sein.

Ich würde zuerst die Methoden so benennen dass man sieht was sie tun. Evt_DragStarten ist nicht "drag starten" sondern "Mouse move". Selbes mit dem Event QueryContinueDrag, da steckt eine Methode namens Evt_DragAbbrechen drin. Wenn der Name einem etwas anderes vorgaukelt als dahinter steckt, kannst du nur verlieren.

So wie ich Evt_DragStarten aufgebaut habe, wird dieses genau 2 mal ausgeführt

Wie stellst du das fest? Messageboxen halte ich dafür nicht geeignet, die setzen sich in den Vordergrund und bringen dir die ganzen Zustände durcheinander.

Es könnten durch aus Fehler enthalten sein, da ich vieles direkt im Browserfenster geschrieben habe...

Das heißt der Code wurde so gar nicht ausgeführt? Es wäre schon hilfreich über Auswirkungen zu reden die zum gezeigten Code passen.

Such dir wirklich ein gescheites Tutorial dazu. Ich habs gerade selbst versucht, hab spontan nichts gefunden das sich nicht mit zig Nebenschauplätzen befasst sondern nur auf D&D eingeht. Aber es muss irgendwas dazu geben.
Schau dir auch die Doku zu allen beteiligten Methoden an, die geben sicher auch Hinweise auf die Wechselwirkungen.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Sobald DoDragDrop aufgerufen wird, passiert meines Wissens alles innerhalb dieser Routine, bis die Maus losgelassen wird. Ich vermute du hast da noch ein Problem mit den vielen Hilfsvariablen. So kompliziert muss das eventuell gar nicht sein. Die habe ich erst nachträglich eingearbeitet, weil es nicht so funktionierte wie erwartet..

Ich würde zuerst die Methoden so benennen dass man sieht was sie tun. Evt_DragStarten ist nicht "drag starten" sondern "Mouse move". Selbes mit dem Event QueryContinueDrag, da steckt eine Methode namens Evt_DragAbbrechen drin. Wenn der Name einem etwas anderes vorgaukelt als dahinter steckt, kannst du nur verlieren. Ja, du hast da nicht ganz unrecht.

Es könnten durch aus Fehler enthalten sein, da ich vieles direkt im Browserfenster geschrieben habe...
Das heißt der Code wurde so gar nicht ausgeführt? Es wäre schon hilfreich über Auswirkungen zu reden die zum gezeigten Code passen. Ich habe genau einen einzigen Satz fett hervorgehoben. Darunter folgt der kopierte Code.

Allerdings war das Thema für mich bereits abgeschlossen und sollte nur dazu dienen, falls jemand mal auf ähnliche Probleme stößt.
Gruß

2.207 Beiträge seit 2011
vor 4 Jahren

Hallo Frokuss,

Meine Fragen sind daher: ...

kannst du bitte nur ein Thema pro Thread erstellen? [Hinweis] Wie poste ich richtig? Es ist unmöglich für uns dem Thread einen gescheiten Titel zu geben. Ausserdem gehen die Antworten hier im Thread im schlimmsten Fall in drei Richtungen (da drei Fragen). Das ist für dich mühsam nachzuvollziehen, für den nächsten Hilfesuchenden noch weniger, da er nicht im Kontext ist und für uns Admins und Mods nahezu unmöglich zu lenken. Bitte achte darauf das nächste Mal. Da der Thread schon Antworten hat bleibt er auf.

Gruss

Coffeebean

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 4 Jahren

Sorry, werde ich in Zukunft versuchen zu beachten.

Gruß Frokuss