Laden...

Grafische Objekte auf GUI verbinden: Ansatz gesucht

Erstellt von metacircle vor 14 Jahren Letzter Beitrag vor 13 Jahren 16.858 Views
M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 14 Jahren
Grafische Objekte auf GUI verbinden: Ansatz gesucht

Hallo Zusammen,

ich fange die Tage meine Studienarbeit an, Thema Softwareentwicklung. Das Projekt welches ich vor mir habe, besteht grundsätzlich darin auf einer GUI Logikbausteine zusammenzusetzen, daraus wird dann eine CAN-Nachricht gebaut und an einen Mikrocontroller geschickt. Die Programmlogik ist alles kein Problem, sowas lernt und übt man auch oft genug.

Das schwierige an der Sache für mich wird die GUI. Ich muss eine GUI erstellen, auf der ich die einzelnen Logikbausteine frei verschieben kann, und bestimmte Verbingungen setzen und entfernen. Programme die so ähnlich aufgebaut sind gibt es wie Sand am Meer (Sämtliche SPICE Programme, Simulink, Petri Netz Tools, etc pp.)

Ich habe natürlich keine Ahnung wie man an sowas in Visual C# herangeht und die GUI mit Visual Studio hinbekommt, daher bin ich auf der Suche nach Beispielen und Tutorials sowie Literatur, alles was mir hilft an das Thema heranzugehen.

Wie in etwas das Ergebnis aussehen soll, seht ihr im Anhang. (Natürlich noch mit GUI außern herum, aber die Arbeitsoberfläche sollte in diese Richtung gehen)
Mir schwebt aber eher ein Grid im Hintergrund vor, automatische Platzierung wird wohl über die Projektdauer von 3 Monaten hinausgehen. Daher erstmal die einfachste bzw. unkomplizierteste Lösung.

Hoffe mein Problem wurde klar und freue mich auf Antworten.

Grüße

O
449 Beiträge seit 2005
vor 14 Jahren

Hallo,

naja ich denke wenn du jeden deiner Logikbausteine ein eigenständiges UserControl verpasst und dem die entsprechenden Eigenschaften und Methoden mitgibst, sollte das gehen.
Das Verschieben mit Drag und Drop sollte auch kein Problem sein. Nur die CAN Nachricht zusammenzubalsteln ist nicht so ganz trivial, denke ich. Für ne Studienarbeit ist das schon ne ganz schöne Packung...

Grüße Oli

Viele Grüße, Oli

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 14 Jahren

Hallo Oli,

danke für deine Antwort. Kannst du mir zum Thema UserControl und wie man sowas entsprechend realisieren kann noch weitere Informationen mitgeben. Das ist leider (noch) nicht meine Materie.

Über die CAN Nachricht mache ich mir keine Sorgen. Dazu gibt es genügend Klassen, ich muss die Nachricht nur aus der Logik zusammenstellen (das ist in meinem Fall nicht schwierig, sofern die Objektbasis gut gelöst ist), der Rest geht dann über die bereitstehenden Klassen.

Grüße

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo metacircle,

ich würde bei sowas dringend von UserControls abraten. Schau dir stattdessen mal [Tutorial] Gezeichnete Objekte mit der Maus verschieben an.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 14 Jahren

Hallo,

ich habe von der zu erstellenden Software ein paar Entwürfe gemacht, und wollte hiermit nur eben Nachfragen ob sich das alles in einer WinForm Anwendung mittels GDI+ realisieren lässt oder ob es evtl. mit WPF einfacher wird, einarbeiten muss ich mich in das eine wie in das andere.

Auf ein paar Anregungen würde ich mich sehr freuen, da das ganze Abseits der Programmlogik für mich immernoch ein relativ großes Fragezeichen ist.

Danke vielmals

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo metacircle,

das bekommst du locker mit GDI+ hin.

Anregungen findest du in dem schon verlinkten Artikel und in [Artikel] Zeichnen in Windows-Programmen.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Puh. Ich stehe praktisch immernoch vor einer riesigen Wand, hätte nicht gedacht, dass man praktisch noch alles so tiefgehend von Hand implementieren muss.

Habe jetzt aber dieses TutorialGezeichnete Objekte mit der Maus verschieben durchgearbeitet und einige Fragen dazu.

a) Ich möchte nicht in meinem Form zeichnen, sondern in einem gesonderten Panel. Wie biege ich das dahingehend um. Ich habe nämlich die Funktion des _rectangle noch nicht ganz verstanden.

b) Ich möchte ja Schlussendlich nicht Rechtecke und Kreise zeichnen, sondern Rechtecke mit Beschriftung und Anschlüssen. Wie setze ich sowas als einzelnes Objekt um?

c) Wie realisiere ich ein Grid und für die Objekte darauf Snap to Grid? Muss ich dabei das Grid auch erst mittels GDI+ zeichnen lassen?

Für weiter Hilfe bin ich dankbar, ich schiebe hier schon beinahe Panik weil ich schon seit 2 Tagen immernoch am Punkt 0 bin und bisher noch keinen Ausweg sehe.

Danke

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

a) Ich möchte nicht in meinem Form zeichnen, sondern in einem gesonderten Panel. Wie biege ich das dahingehend um. Ich habe nämlich die Funktion des _rectangle noch nicht ganz verstanden.

mit _rectangle hat das überhaupt nichts zu tun. Die Lösung steht in [Artikel] Zeichnen in Windows-Programmen:

Welches OnPaint/Paint muss ich denn nun überschreiben/verwenden?

Man muss immer das OnPaint/Paint von dem Control überschreiben/verwenden, in das man zeichnen will.

b) Ich möchte ja Schlussendlich nicht Rechtecke und Kreise zeichnen, sondern Rechtecke mit Beschriftung und Anschlüssen. Wie setze ich sowas als einzelnes Objekt um?

Indem du in der Draw-Methode des Objekts alles zeichnest, was gezeichnet werden soll.

Respektive, indem du in den Graphics.Path des Objekts alles packst, was gezeichnet werden soll.

c) Wie realisiere ich ein Grid und für die Objekte darauf Snap to Grid?

Wenn du einmal die initiale Position des Objekts auf ein Vielfaches des Gridabstands gerundet hast, musst du doch beim Verschieben nur die tatsächliche Differenz (bzw. tatsächliche Summe der Differenzen) auf ein Vielfaches des Gridabstands runden.

Muss ich dabei das Grid auch erst mittels GDI+ zeichnen lassen?

Das würde ich anbieten. Natürlich kannst du das Grid auch einmal in eine Bitmap zeichnen und dann die Bitmap jedesmal auf den Schirm.

herbivore

328 Beiträge seit 2006
vor 13 Jahren

mal eine Frage zwischendurch @herbivore

Du meintest vorhin "ich würde bei sowas dringend von UserControls abraten. ". Nun wollte ich fragen warum da abraten würdest. Ich hätte das und/oder/... Gatter nämlich als UserControl gemacht.

Also meiner Meinung nach wäre das viel einfacher, auch beim "erstellen" der Endfunktion. Da schaut man sich dann die Eingangs bzw Ausgangs Property (welche man natürlich selber implementieren muss) des Usercontrol an, und damit weiß ich welche Gatter miteinander verbunden sind.

Wenn man die ganzen Gatter nur mit Rechtecken zeichnet stelle ich mir dass doch recht kompliziert vor!

Träume nicht dein Leben sondern lebe deinen Traum.
Viele Grüße, David Teck

2.921 Beiträge seit 2005
vor 13 Jahren

s. auch ProFormX
und von dort GfxFramework für die Initialisierung.

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

Gelöschter Account
vor 13 Jahren

Da schaut man sich dann die Eingangs bzw Ausgangs Property (welche man natürlich selber implementieren muss) des Usercontrol an, und damit weiß ich welche Gatter miteinander verbunden sind.

du wirst bei zeichnen probleme bekommen ,wenn du das ganze ein wenig aufhübschen willst, da die zeichenlogik hirarchisch aufgebaut ist und transparenz in gdi etwas... eigen ist.

du bist wirklich besser beraten, indem du keine usercontrols für die einzelnen elemente nimmst.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo TripleX,

erstmal kann ja so eine Zeichnung potenziell beliebig viele Elemente enthalten, ein Form aber nicht beliebig viele (User)Controls. Siehe Optimierungsideen für die Darstellung von sehr vielen Controls?.

Außerdem handelt man sich Probleme ein, wenn die Controls sich (teilweise) überdecken. Stichwort: Transparenz in Windows Forms.

Weiterhin ist es ziemlich kompliziert, Verbindungslinien zeichnen, wenn sie über über andere UserControls laufen.

Es gibt noch ein paar andere Punkte wie relative Koordinaten, Click-Through usw. die man zwar in den Griff bekommt, aber um die man sich kümmern muss.

Insgesamt kommt dann eben meine Empfehlung heraus, hierfür keine UserControls zu verwenden.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo,

ich bin es mal wieder. Habe am WE einiges noch gegoogelt und nachgelesen und finde nach wie vor die ganze Geschichte in Winforms + GDI+ sehr komplex und an habe schon öfters gelesen, dass die Geschichte mit WPF teilweise wohl etwas einfacher wäre.

Ist da was dran, soll ich lieber WPF angehen oder scheint das mit Winforms nur auf den ersten Blick so "schwierig".

Danke für eure Geduld.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

WPF ist auf jeden Fall komplexer als GDI, das heißt es gibt viel mehr Möglichkeiten. Dadurch geht mehr, aber man muss auch mehr beachten bzw. wissen. Wenn du mit GDI Schwierigkeiten hast, ist WPF nichts für dich. Was du vorhast, ist mit GDI sehr einfach zu realisieren. GDI ist die angemessene Technik dafür. Es gibt keinen Grund, nach Alternativen zu suchen.

Sorry, wenn ich das so sage. Schon dass sich auf alle deine Fragen, die für dich eine unüberwindlich Wand darstellten, sehr einfache Antworten geben ließen, lässt doch vermuten, dass die Ursachen nicht in der verwendeten Technik liegen, sondern in anderen Voraussetzungen. An denen solltest du arbeiten.

Gerade mit den beiden genannten Tutorials an der Hand, sollte man einen lauffähigen Prototypen, mit dem man Objekte, wie du sie darstellen und verbinden willst, schon mal auf den Schirm bekommt und verschieben kann, locker innerhalb eines Tages hinbekommen.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo herbivore,

danke für deine Antwort.

Es sieht für mich so aus, dass jedes einzelne Teilproblem was ich löse, zig neue aufkommen lässt.

Also ich habe es mittlerweile z.B. hinbekommen ein Objekt wie ich es wünsche komplett in einen GraphicsPath zu packen. Bei GDI finde ich eben ungewöhnlich, dass alles gezeichnete einfach in Pixeln verschwindet und man (außergewöhnlichen) Aufwand treiben muss sich die gezeichneten Objekte zu merken. Das ist z.B. auch das erste, von dem ich finde (falls ich es korrekt verstanden habe), was bei WPF viel einfacher ist, weil die Objekte nicht verschwinden. Daher habe ich z.B. ein Drag & Drop Tutorial auf WPF Basis innerhalb von 15min kapiert, währen ich mir bei der GDI+ Geschichte immernoch schwer tue.

Die nächste Hürde für mich ist dann nun, wie ich innerhalb eines GraphicsPath verschiedene Bereiche unterscheide. Also z.B. Maus über dem Logikbaustein --> Drag & Drop Funktion, aber Maus über einem Anschluss des Logikbausteins --> Funktion um Verbindungslinie zu zeichnen und somit ich im Hintergrund den 2 Beteiligten Objekten zuweisen.

Da ich auf den erstellten Objekten am Ende diverse Algorithmen laufen lassen muss ist das essentiell. Aber gerade diese Algorithmen habe ich mir schon komplett im Kopf zurechtgelegt und das stellt auch bei der Implementierung für mich kein Problem dar, ganz im Vergleich zur Oberfläche.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

Die nächste Hürde für mich ist dann nun, wie ich innerhalb eines GraphicsPath verschiedene Bereiche unterscheide.

nimm mehrere GraphicsPaths. Entweder in einem Objekt, dass mehrere GraphicsPaths enthält oder in mehreren Objekten, die je einen GraphicsPaths enthalten, aber dann untereinander gekoppelt sind.

Ich sehe da wirklich die Probleme nicht.

herbivore

Gelöschter Account
vor 13 Jahren

Bei GDI finde ich eben ungewöhnlich, dass alles gezeichnete einfach in Pixeln verschwindet und man (außergewöhnlichen) Aufwand treiben muss sich die gezeichneten Objekte zu merken.

deswegen baut man sich zuerst den graphicspath zusammen und erst dann zeichnet man einfach nur noch den graphicspath.

ich habe das gefühl das du keine gute kapselung erzielt hast... denn wie bereits mehrfach erwähnt, ist dein vorhaben ansich nicht gerade schwer umzusetzen.

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Also ich habe es jetzt wohl über die erste und schwierigste Hürde geschafft. Habe endlich das Zeichen und Drag n Drop Prinzip in GDI+ kapiert. Ist ja echt nicht schwierig 😃 Ich habe wohl am Anfang erwartet, dass das ganz anders funktioniert und daher mir schwer getan.

Jetzt habe ich aber schon erste andere Problemchen:

  • Meine Zeichenfläche ist ein Panel (Double Buffered). Jetzt weiß man aber nicht wie komplex die zu erstellende Konfiguration wird (d.h. wieviele Bausteine verwendet werden). Was gibt es da für Lösungen. Soll ich das Panel einfach sehr groß machen (3000x3000 Pixel) oder gibt es eine Möglichkeit das Dynamisch zu tun. (Die max Anzahl der Elemente ist durch die angeschlossene Hardware begrenzt auf < 200, genau Zahl habe ich nicht im Kopf).

  • Nochmal zum Zeichenpanel, wie kann ich verhindern, dass über den Rand gezeichnet werden kann. Ich kann z.B. im Moment ein Objekt über den Sichtbaren Rand schieben.

Was noch eine kleine Herausforderung darstellt ist die Verbindungen zwischen den Logikblöcken zu zeichnen bzw auch vom Benutzer manuell verändern zu lassen, ich hoffe ich darf sobald ich soweit bin noch ein paar Fragen stellen.

Danke soweit.

Viele Grüße

Gelöschter Account
vor 13 Jahren

as noch eine kleine Herausforderung darstellt ist die Verbindungen zwischen den Logikblöcken zu zeichnen

ist ein wenig rechenarbeit aber auch nciht besonders aufwändig. schau dir z.b. das sql management studio von ms an. insbesondere den diagramm designer. das ist in etwa das was du realisieren willst. schau dir an, wie die verbindungen aussehen und ab wann sie einen knick um 90° machen. sowas ist 30 zeilen code (also die logik nicht das layout)

bzw auch vom Benutzer manuell verändern zu lassen,

das ist weiter auch kein problem. du musst ja nur feststellen, ob und wo ein benutzer auf eine linie klickt. das verhalten ist also analog zu den anderen objekten. wenn du es schlau machst. imlizierst du dieses verhalten oder zumindest die erkennung des klicks durch vererbung.

Jetzt weiß man aber nicht wie komplex die zu erstellende Konfiguration wird (d.h. wieviele Bausteine verwendet werden). Was gibt es da für Lösungen. Soll ich das Panel einfach sehr groß machen (3000x3000 Pixel) oder gibt es eine Möglichkeit das Dynamisch zu tun.

wieder ist das etwas rechenaufwand (btw mit rechenaufwand meine ich nicht cpu last sondern schul-mathematik). ein panel hat auch einen virtuellen bereich. den erreichst du mit autoscroll-eigenschaften. hierbei musst du dich allerdings ein wenig umstellen, da der virtulle bereich und der offset ein wenig ungewohnt ermittelt werden. das kannst du aber mit ein paar tests selber herausfinden 😃
HINT: du musst auf jeden fall AutoscrollMinSize berechnen und setzen. und das bei jeder änderung der größe oder position eines beliebigen beinhaltenden objektes.

Nochmal zum Zeichenpanel, wie kann ich verhindern, dass über den Rand gezeichnet werden kann. Ich kann z.B. im Moment ein Objekt über den Sichtbaren Rand schieben.

zeichne nur die objekte, die auch sichtbar sind. das verhalten gilt für alle objekte und sollte daher vererbt werden. biete hierzu z.B. eine IsVisible eigenschaft an, die berechnet, ob die eigenen ausmaße (location + path) noch innerhalb eines bereiches (sichtbarer Rectangle) liegt. zeiche aber auch teilweise sichtbare elemente.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

Soll ich das Panel einfach sehr groß machen (3000x3000 Pixel) oder gibt es eine Möglichkeit das Dynamisch zu tun.

kannst du dir aussuchen. Die Größe des Panels kannst du ja zu jedem Zeitpunkt so groß setzen, wie du oder der Benutzer es gerne hätten. Dabei kannst du Vorgaben des Benutzers und die tatsächliche (momentane) Größe der Zeichnung einbeziehen.

Nochmal zum Zeichenpanel, wie kann ich verhindern, dass über den Rand gezeichnet werden kann.

So wie man bei Snap to Grid die Positionen runden muss, muss man hier die Positionen hinsichtlich Min- und Max-Wert begrenzen. Das geht genauso einfach.

HINT: du musst auf jeden fall AutoscrollMinSize berechnen und setzen.

Siehe auch Panel-Autoscroll ohne Controls.

ich hoffe ich darf sobald ich soweit bin noch ein paar Fragen stellen.

Ehrlich gesagt wäre es mir lieber, wenn unsere "Anschubfinanzierung" Wirkung zeigen würde und du jetzt selber den Dreh findest. Auch die aktuellen Fragen waren wieder alle so einfach zu beantworten, dass ich meine, dass du da auch selber hättest drauf kommen können oder sogar müssen.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Ehrlich gesagt wäre es mir lieber, wenn unsere "Anschubfinanzierung" Wirkung zeigen würde und du jetzt selber den Dreh findest. Auch die aktuellen Fragen waren wieder alle so einfach zu beantworten, dass ich meine, dass du da auch selber hättest drauf kommen können oder sogar müssen.

Also gut, ich werde nurnoch bei Dingen fragen bei denen ich wirklich ums Biegen und Brechen nicht weiterkomme.

Habe hier ein paar kleine Fragen nur zur Ergänzung (im Moment stecke ich nirgends fest)

Ich habe das Panel jetzt mittels AutoScrollMinSize etwas größer gemacht.

Damit das Scrollen keinen Ärger macht habe ich im Paint Ereigniss folgende Zeile hinzugefügt

e.Graphics.TranslateTransform(pnlDraw.AutoScrollPosition.X, pnlDraw.AutoScrollPosition.Y);

Spart das theoretisch nicht ein paar Systemresourcen wenn ich das nur ins Scroll Ereigniss packe, da dieses nicht so oft wie das Paint Ereignis aufgerufen wird?

Das nächste ist, dass die mouselocation bei den Mouse Events natürlich nicht "mitscrollt" daher rufe ich im OnMouseMove Ereignis jedesmal eine Korrekturfunktion auf, die dann in

Point currentMouseLocation = CorrectLocation(e.Location)

mittels

private Point CorrectLocation(Point falseLocation)
        {
            int correctedX, correctedY;
            correctedX = falseLocation.X - pnlDraw.AutoScrollPosition.X;
            correctedY = falseLocation.Y - pnlDraw.AutoScrollPosition.Y;
            return new Point(correctedX, correctedY);
        }

die Positionskoordinaten intern ständig korrigiert. Kann man das irgendwie umgehen, dass nicht ständig die Position neu berechnet werden muss sondern ich das direkt abgreifen kann. Wird sowas bereitgestellt oder ist das schon richtig was ich tue?

Ich habe noch keinerlei Gefühl dafür, wieviel Resourcen durch ständiges feuern von Events und dadurch ständigen Funktionsaufruf unnütz verbraten werden...sorry.

Hoffe ich nerve nicht zu sehr mit meinem Anfänger Fragen.

Danke + Gruß

Gelöschter Account
vor 13 Jahren

Spart das theoretisch nicht ein paar Systemresourcen wenn ich das nur ins Scroll Ereigniss packe,

gezeichnet wird nur im paint ereigniss. das selbe gilt für alles was mit dem graphics objekt auch nur berührungen hat.

Das nächste ist, dass die mouselocation bei den Mouse Events natürlich nicht "mitscrollt" daher rufe ich im OnMouseMove Ereignis jedesmal eine Korrekturfunktion auf, die dann in....

brauchst du die mouselocation zeischengespeichert? ich würde sie immer neu berechnen, wenn ich sie bruache. wenn ich sie nciht bruache, muss ich sie ja auch nciht neu berechnen.

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

brauchst du die mouselocation zeischengespeichert? ich würde sie immer neu berechnen, wenn ich sie bruache. wenn ich sie nciht bruache, muss ich sie ja auch nciht neu berechnen.

Im Moment lasse ich (.u.a. zu Debugzwecken) die echte (also korrigierte) Mausposition ständig über ein Label ausgeben, ansonsten hast du natürlich recht, könnte ich es wohl nur berechnen wenn ich es brauche. Dann fällt es zumindest beim simplen Mausbewegen über die Oberfläche ohne Aktionen durchzuführen weg.

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Ich überlege gerade was der sinnvollste Ansatz für die "Speicherung" der Verbindungslinien ist.

  • Die Linien automatisch über einen Algorithmus zeichnen lassen und nicht zu speichern. Der Benutzer hätte hier keinen Einfluss auf den Linienverlauf.

  • Die Linien genau wie die Objekte in einer eigenen Liste merken. Hier wäre die Frage ob man aus einem graphicsPath einzelne Objekte rausbekommt, wäre ja nötig wenn man aus einer aus 3 Linien zusammengesetzten Verbindung (horizontal, vertikal, horizontal) z.B. nur die vertikale Linie ein wenig nach rechts oder links schieben möchte.

Danke + Gruß

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

welchen Ansatz du wählst, hängt doch nur davon ab, welche Einflussmöglichkeiten du dem Benutzer geben möchtest.

Die Graphics-Path-Geschichte würde ich ganz pragmatisch sehen. Wenn der GraphicsPath "geändert" werden soll, erstellst du einfach einen neuen (oder verwendest GraphicsPath.Reset und füllst ihn neu).

herbivore

Gelöschter Account
vor 13 Jahren

Die Linien genau wie die Objekte in einer eigenen Liste merken.

exakt so geht das. die linien sind genauso grafische objekte wie alle anderen teile.

Hier wäre die Frage ob man aus einem graphicsPath einzelne Objekte rausbekommt, wäre ja nötig wenn man aus einer aus 3 Linien zusammengesetzten Verbindung (horizontal, vertikal, horizontal) z.B. nur die vertikale Linie ein wenig nach rechts oder links schieben möchte.

der graphicspath ist der ausdruck der drei objekte. es kann ja sein, das der user möchte, das die linie mehr kanten hat, da der velrauf komplizierter ist.. also bruachst du horizontale linien und vertikale linien und du bruachst ein objekt das weiß welche linien mit welchen verknüpft sind und das ganze natürlich so gestaltet, das theoretisch unendlich viele linien miteinander verknüft werden können.

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo,

bin mittlerweile sehr gut vorangekommen, bin mit dem bisherigen Ergebnis auch sehr zufrieden. Habe nur eine Frage zu "Gezieltes OwnerDrawing" - schnelles Zeichnen bewegter Objekte .

Und zwar habe ich es genau so wie im Artikel umgesetzt implementiert. Einmal im Konstruktor meiner Objekte:

this._boundsPath = new GraphicsPath();

            _boundsPath.AddPath(_image, false);

            _boundsPath.Widen(new Pen(Brushes.Black, 4));

            _bounds = _boundsPath.GetBounds();

Und in einer RefreshBounds Methode:

_boundsPath.Reset();
            _boundsPath.AddPath(_image,false);
            _boundsPath.Widen(new Pen(Brushes.Black, 4));
            _bounds = _boundsPath.GetBounds();

Wenn das Objekte nun bewegt wird erfolgen folgende Aufrufe:

pnlDraw.Invalidate(Rectangle.Ceiling(movingLogicBlock.bounds));
            movingLogicBlock.RefreshBounds();
            pnlDraw.Invalidate(Rectangle.Ceiling(movingLogicBlock.bounds));

Funktioniert soweit auch alles, nur stimmen die Bounds nicht ganz, denn das optische Ergebnis ist teilweise folgendes: Siehe Anhang.

Jemand eine Ahnung woran es liegen könnte? Wenn ich den Pen der für widen verwendet wird auf Größe 20 setze ist das Problem behoben, ist diese Lösung hier angebracht oder mehr schlecht als recht?

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

Rectangle.Ceiling liefert ein Rechteck, bei dem die Zahlenwerte der vier Komponenten des ursprünglichen Rechtecks gerundet sind. Das liefert nicht zwangsläufig Rechteck, das das ursprüngliche Rechteck in alle Richtungen nach außen umschließt, wie du es bräuchtest. Ein solches musst du wohl selbst berechnen.

herbivore

Gelöschter Account
vor 13 Jahren

bedenke das du die pens auch wieder manuell disposen musst, sonst bekommst du schnell eine outofmemoryexception wegen gdi+ handle mangel.

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Das sollte kein Thema mehr sein. Habe es anders gelöst. Jedes Objekt kennt seinen Bereich nun als Rectangle, berechnet aus Objekttyp + Objektmittelpunkt (letzteren brauche ich sowieso für diverse andere Dinge auch, war also schon vorhanden).

Eventuell dazu noch eine grundsätzliche Frage: Was muss ich generell selbst disposen, bzw wieso greift hier der Garbage Collector nicht?

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

der Garbage Collector greift ja, nur bei solchen knappen Ressourcen zu spät.

Desposen muss du alles, was IDisposable implementiert, was du selbst erzeugt hast und was auch kein anderer braucht. Das passt aber aber nicht mehr wirklich in den Thread.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo,

jetzt habe ich doch noch ein neues Problem bekommen, funktioniert soweit zwar alles, aber sobald ich die Autoscrollposition vom Ursprung wegbewege geht es schief, da meine _bounds dann nichtmehr stimmen, und mir gerade nichts einfällt wie ich das Problem löse. Meine Objekte kennen ihre Position immer in absoluten Koordinaten. D.h. wenn ich z.B. mein Zeichenpanel nach unten scrolle wird beim Bewegen eines Objekts aber der falsche Bereich invalidiert...ein wenig schwierig zu erklären. Eventuell kann mir jemand einen Tipp geben.

private void drawingPanel_Paint(object sender, PaintEventArgs e)
        {
            //move the point of origin of the graphics depending on the autoscrollposition
            e.Graphics.TranslateTransform(pnlDraw.AutoScrollPosition.X, pnlDraw.AutoScrollPosition.Y);

            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            //draw all logic blocks
            foreach (LogicBlock item in currentConfig.logicBlockList)
                item.Draw(e.Graphics);
            
            //draw all connections
            foreach (Connection item in currentConfig.connectionList)
                item.Draw(e.Graphics);
        }
private void pnlDraw_MouseMove(object sender, MouseEventArgs e)
        {
            if (movingLogicBlock != null)
            {
                movingLogicBlock.Move(currentMouseLocation.X - lastMouseLocation.X, currentMouseLocation.Y - lastMouseLocation.Y);

                pnlDraw.Invalidate(movingLogicBlock.bounds);

                movingLogicBlock.RefreshBounds(currentMouseLocation.X - lastMouseLocation.X, currentMouseLocation.Y - lastMouseLocation.Y);

                lastMouseLocation = currentMouseLocation;

                pnlDraw.Invalidate(movingLogicBlock.bounds);
            }
            CorrectLocation(e.Location, ref currentMouseLocation);
            //maybe this can be removed in the final version
            tsslMousePosition.Text = string.Format("X = {0}; Y= {1}", currentMouseLocation.X, currentMouseLocation.Y);
        }
private void CorrectLocation(Point falseLocation, ref Point realLocation)
        {
            realLocation.X = falseLocation.X - pnlDraw.AutoScrollPosition.X;
            realLocation.Y = falseLocation.Y - pnlDraw.AutoScrollPosition.Y;
        }

Also das Verhalten ist schlicht, dass ich das Objekt beim bewegen nicht sehe, lasse ich es los erscheint es natürlich an der korrekten Position.

Ich denke ich muss auf irgendeine Weise die Autoscrollpositions beim Invalidaten berücksichtigen, hat da jemand eine Idee?

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo metacircle,

du hast doch das Problem erkannt. Es ist in meinen Augen reine Fummelarbeit herauszufinden, an welchen Stellen um die AutoScrollPosition korrigiert werden muss. Das kriegst du sicher auch alleine hin. Jedenfalls sehe ich keinen Grund, warum wir diese Arbeit abnehmen sollen.

Ziemlich sicher ist, dass du da, wo die AutoScrollPosition berücksichtigen musst, diese addieren und nicht subtrahieren musst.

herbivore

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo herbivore,

da hast du schon recht, es soll mir auch niemand die Arbeit abnehmen.

Ziemlich sicher ist, dass du da, wo die AutoScrollPosition berücksichtigen musst, diese addieren und nicht subtrahieren musst.

Also dass in der Funktion CorrectLocation das Minus richtig ist habe ich auch nur durch probieren herausgefunden. Da ich ständig die korrekte Mausposition ausgeben lasse habe ich da ein wenig experimentiert.

Ich finde nur gerade keine sinnvolle Lösung mein Problem anzupacken.

Eventuell ein neues temporäres Rectangle einführen, welche das _bounds rectangle kopiert und dann entsprechend der autoscrollposition verschiebt 🤔

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Hallo,

ich habe eine Lösung gefunden, und zwar korrigiere ich das Rectangle welches den Bereich eines Objektes umschließt sobald ein Objekt zum Bewegen gesetzt wird, beim Rücksetzen des Bewegens wird das Rectangle wieder entsprechend zurück korrigiert.

Funktioinert. Nur hat sich dadurch eine neue Lücke aufgetan. Da ich das Panel mit dem Mausrad scrollen kann, siehe meinen anderen Thread hier und während des Drag n Drop Vorgangs mit dem Mausrad scrolle, haut es mir alles zusammen.

Das Scrollen mit dem Mausrad löst auch kein Scroll Event aus.

Ich bräuchte eine Möglichkeit das Scrollen mit dem Mausrad während des bewegen eines Objekts zu blockieren oder ein Ereignis welches das Mausrad auslöst und dann mein Rectangle wieder korrigiert.

Bräuchte hier etwas hilfe, stehe gerade in einer Sackgasse...

2.760 Beiträge seit 2006
vor 13 Jahren

Ich bräuchte eine Möglichkeit das Scrollen mit dem Mausrad während des bewegen eines Objekts zu blockieren oder ein Ereignis welches das Mausrad auslöst und dann mein Rectangle wieder korrigiert.

Wenn dein Panel auf dem du zeichnest den Fokus hat sollte an und für sich das MouseWheel Event gefeuert werden (verwette ich jetzt allerdings auch nicht meinen Hintern für 😉

Ansonsten wirds etwas umständlicher aber die Message kommt ja irgendwann bei deinem Control an da es ja sonst gar nicht scrollen würde.

Du kannst die WndProc des Controls überschreiben und dann folgende Message handlen wie du das möchtest (z.B. verwerfen wenn gerade ein Objekt gezogen wird): WM_MOUSEWHEEL

M
metacircle Themenstarter:in
24 Beiträge seit 2010
vor 13 Jahren

Ich habe jetzt die einfachste und naheliegendste Lösung gewählt, sobald ein Drag und Drop Vorgang im Gange ist bekommt einfach kurzzeitig etwas anderes den Focus, sobald das Objekt wieder abgelegt ist, bekommt das Panel den Focus zurück.

Möchte mich an dieser Stelle einmal bei allen die mir hier geholfen haben bedanken, bin sehr zufrieden mit der Software die bisher entstanden ist. Jetzt kommt eine neue Herausforderung, dazu aber auch ein neuer Thread.

Danke + Gruß