Hallo Leute Ich habe eine Frage zum Konzept, Visual Studio MFC betreffend. Bisher habe ich ein MFC SDI C++ Projekt erstellt nun möchte ich in die Client Area etwas zeichnen. Genauer gesagt habe ich in der Client Area verschiede Elemente eines davon ist ein Singnal Plot über die Zeit, ähnlich einem Oszilloskop. Nun möchte ich für jeden Bereich des Client Areas eine eigene Klasse erstellen. Beispielsweise eine Klasse CSignalPlot, in dieser Klasse werden alle Berechnungen und Datentransfers, die das Signal betreffen durchgeführt. Nun möchte ich von dieser Klasse aus das Signal auf dem Bilschirm ausgeben. Nun weiss ich nicht wie dies funktioniert, irgendwie brauche ich eine OnDraw() Methode... Ich wäre froh um einige Inputs; ist mein Ansatz korrekt? Kann ich für jeden Bereich in meinem Client Fenster eine Klassse erstellen und so meinen Code klar strukturieren? Oder wie entspricht dies nicht dem MFC Konzept? Anmerkung: Ich möchte vermeiden dass ich den ganzen Code zum Zeichnen in der CmyprojectView Klasse einfügen muss, das erscheint mir sehr unübersichtlich und unstrukturiert.
David schrieb: > Ich wäre froh um einige Inputs; ist mein Ansatz korrekt? Kann ich für > jeden Bereich in meinem Client Fenster eine Klassse erstellen und so > meinen Code klar strukturieren? Oder wie entspricht dies nicht dem MFC > Konzept? Zunächst mal ist einer der wichtigsten Punkte in der Document-View Architektur, die klare uns konsequente Trennung zwischen Document und View. Ein Document hält die Daten. Punkt. D.h. die Messwerte deines Signals sind im Document beheimantet (und da mglw. wieder in einer Klasse, von der du ein Objekt als Member im Document hältst). Um die Daten anzuzeigen, gibt es eine (oder mehrere) View Klassen. Das Document hält die Daten, die View entscheidet, wie sie anzuzeigen sind. > Anmerkung: Ich möchte vermeiden dass ich den ganzen Code zum Zeichnen in > der CmyprojectView Klasse einfügen muss, das erscheint mir sehr > unübersichtlich und unstrukturiert. Niemand hindert dich, für einen bestimmten Anzeigetyp eine Diagrammklasse zu machen, die weiß, wie man ein Diagramm anzeigt (inklusive Achsen und Beschriftungen). Dieses Diagramm kriegt von der View den Datencontainer mitgegeben, den es darstellen soll und das Diagramm weiß auch, wo auf dem HDC es sich malen soll, wenn seine OnDraw Methode von der OnDraw Methode des View aufgerufen wird. Und auch ja. Im Prinzip hindert dich auch niemand, auf einem View mehrere Diagramme gleichzeitig an unterschiedlichen Stellen anzuzeigen. Obwohl es meist vernünftiger ist, für jedes Diagramm ein eigenes Fenster aufzumachen. > irgendwie brauche ich eine OnDraw() Methode... Die View hat eine. Die wird auch aufgerufen. Die VIew kann jetzt selber was zeichnen, oder sie kann natürlich auch auf anderer Klasse weitergeben, denen den CDC zur Verfügung stellen und die malen dann da drinn rum. Zum Beispiel die Achsen eines Diagramms. Oder die Daten des Datencontainers, die sich der View vom Document holt. Wobei dich wieder nichts und niemand daran hindert, für bestimmte Teilaspekte eine eigene KLasse zu kreieren. Es spricht nichts dagegen, zb für ein Raster eine Klasse einzusetzen, die dann eben in den Draw-Prozess eingebunden wird, indem die von der Klasse zur Verfügung gestellte OnDraw Methode von 'höherer Instanz aus' aufgerufen wird. Aber überleg dir gut, welche Daten * Dokument-spezifisch * View-spezifisch sind. Diese Trennung ist das um und auf in der Document-View Architektur.
:
Bearbeitet durch User
David schrieb: > Ich möchte vermeiden dass ich den ganzen Code zum Zeichnen in > der CmyprojectView Klasse einfügen muss, das erscheint mir sehr > unübersichtlich und unstrukturiert. So ist es aber vorgesehen. Das macht nix, der OnDraw-Handler des Views kann ja die Draw-Funktionen Deiner zum Dokument gehörenden SignalPlot- und weiß-nicht-was-Objekte aufrufen. Damit hast Du Deinen zum SignalPlot-Objekt gehörenden Draw-Code dort, wo Du ihn haben willst, nur daß das kein OnDraw-Handler mehr ist, sondern eine von Dir vorgegebene Draw-Funktion, der natürlich vom View der gewünschte Devicekontext zu übergeben ist. Bist Du Dir sicher, daß Du Dich jetzt noch in die MFC einarbeiten willst? Wenn Du als Anfänger mit einer GUI-Klassenbibliothek arbeiten möchtest, würde ich Dir raten, um die MFC einen Bogen zu machen, weil sie a) ziemlich schlecht dokumentiert, b) ziemlich unübersichtlich und c) nur auf genau eine Plattform beschränkt ist. Von der Denkweise her recht nah verwandt ist wxWidgets, das den Vorteil hat, auch unter Linux und OS X verwendet werden zu können.
Rufus Τ. Firefly schrieb: > Bist Du Dir sicher, daß Du Dich jetzt noch in die MFC einarbeiten > willst? Wenn Du als Anfänger mit einer GUI-Klassenbibliothek arbeiten > möchtest, würde ich Dir raten, um die MFC einen Bogen zu machen, weil > sie a) ziemlich schlecht dokumentiert, b) ziemlich unübersichtlich und > c) nur auf genau eine Plattform beschränkt ist. d) in die Jahre gekommen. Böse Zungen würden auch Auslaufmodell sagen e) eigentlich nicht besonders gut aufgebaut, was zum Teil den beschränkten Fähigkeiten des C++ Compilers aus dem Jahre 1992 (bzw. früher) geschuldet ist. Persönlich verwende ich die MFC immer noch gerne. Nach all den Jahren ist es einfach ein Framework, dass ich kennen gelernt habe und mit dem ich gut umgehen kann. Empfehlen würde ich sie trotzdem niemand mehr, ausser vielleicht als Framework um sich in die Document-View Architektur einzuarbeiten. Aber da gibt es auch andere (bessere) Möglichkeiten.
Danke für die rasche Anwort, dies ist sehr hilfreich. Die genannten Nachteile von MFC habe ich am Rande bereits etwas mitgekriegt, habe sie jedoch als Gerücht abgetan :/...mein Fehler. Ich habe MFC gewählt, da mein Vorgänger damit gearbeitet hat. Womöglich könnt Ihr mir helfen eine passendere Grundlage für mein Programm zu finden. (Anstelle von MFC) Vorgaben: a) Das Programm muss in Visual Studio in C++ geschrieben werden. b) Die Datenverarbeitung muss so schnell wie möglich sein, es werden "grössere" Mengen an Daten analyziert und geplotet. c) Es dürfen keine merklichen Verzögerungen zwischen Userinteraktionen und Reaktion vom Program bestehen (ist vermtlich eine Frage von meiner Implementierung). c) Das Programm muss nicht Platformunabhängig sein. (falls dies überhaupt möglich ist mit Visual C++) Noch einige Worte zum Programm: Das Programm ist eine Usersoftware zur Anylsierung von EKG Signalen, es werden EKG Signale von langer Dauer mithilfe verschiedener Algorithmen analysiert und dargestellt. Der User kann mithilfe der Analyseresultaten einen Report erstellen und diesen speichern/drucken. Verschieden Files müssen geladen und gepseichert werden können. Für weitere Hilfestellungen wäre ich äusserst Dankbar :) Gruss David
David schrieb: > Ich habe MFC gewählt, da mein Vorgänger damit gearbeitet hat. Heißt das, das Pgm existiert schon und du baust es weiter aus? Denn in dem Fall tut sich der Fragenkomplex auf: Verwirft man ein bestehendes Programm bzw. schreibt es neu? Mit neuen Programm-Fehlern. Und das ist nicht gut. Ganz abgesehen davon, dass man eine derartige Aktion bei den Projektverantwortlichen bzw. Firmenleitung nur schwer durchdrücken kann, sofern es nicht massive Vorteile verspricht. Denn ein 'Neu-schreiben' kostet erst mal Geld, ohne dass man etwas von aussen ersichtliches dafür bekommt. Das ist nichts, was die Verkäufertruppe draussen verkaufen kann. > a) Das Programm muss in Visual Studio in C++ geschrieben werden. > b) Die Datenverarbeitung muss so schnell wie möglich sein, es werden > "grössere" Mengen an Daten analyziert und geplotet. > c) Es dürfen keine merklichen Verzögerungen zwischen Userinteraktionen > und Reaktion vom Program bestehen (ist vermtlich eine Frage von meiner > Implementierung). > c) Das Programm muss nicht Platformunabhängig sein. (falls dies > überhaupt möglich ist mit Visual C++) Deine 'Anforderungspunkte' sind nicht wirklich die ausschlaggebenden Kriterien. Denn die werden auf heutigen PCs mit Leichtigkeit erfüllt. Das Problem mit der MFC ist ganz einfach eine Frage der Zukunftstauglichkeit. Deshalb sind Neuentwicklungen mit der MFC nicht mehr zielführend. > Das Programm ist eine Usersoftware zur Anylsierung von EKG Signalen, es > werden EKG Signale von langer Dauer mithilfe verschiedener Algorithmen > analysiert und dargestellt. Der User kann mithilfe der Analyseresultaten > einen Report erstellen und diesen speichern/drucken. Verschieden Files > müssen geladen und gepseichert werden können. Das ist alles recht Standard und nichts aussergewöhnliches. Ist mit jedem Framework machbar. Persönlich würde ich wahrscheinlich zu Qt greifen. Aber auch nur deswegen, weil ich das Framework schon kenne. Abgesehen davon hab ich da keine Präferenzen in diese Richtung. 'Das Beste' ist immer das, womit man umgehen kann :-)
:
Bearbeitet durch User
Karl Heinz schrieb: > Heißt das, das Pgm existiert schon und du baust es weiter aus? > Denn in dem Fall tut sich der Fragenkomplex auf: Verwirft man ein > bestehendes Programm bzw. schreibt es neu? Das existierende Programm ist nur ein Entwurf, es ist sehr schlecht strukturiert und meine Aufgabe ist es, das Programm neu zu schreiben und zu erweitern, in einer klaren Struktur (Klassen und so). Dennoch werde ich versuchen möglichst viele Implementierungen aus dem existierenden Programm zu übernehmen.
Ich habe kürzlich für mich etwas ähnliches programmiert aber ich arbeite privat lieber mit der WTL und GDI+ geht aber auch mit der MFC und GDI+. Da habe ich auch verschiedene Bereiche in meinem View, die sich auch dynamisch ändern können. Du musst nur beim Programmstart die GDI+ initialisieren und am Programmende wieder beenden, das ist alles. Und natürlich die Header einbinden ;) Also habe ich eine virtuelle Oberklasse, für meine Zeichenobjekte, mit der Methode GetPath() geschrieben, die einen GrapicsPath zurückliefert. Das hat den Vorteil, das deine abgeleiteten Klassen nichts selbst zeichnen sondern nur grafische Objekte (Linien, Kurven, Texte usw.) zu dem Graph hinzufügen. Der View klappert die dynamische Liste mit den zu zeichnenden Objekten ab, holt sich den Path von jedem Objekt, skaliert und verschiebt ihn mit Hilfe einer Transformationsmatrix an den richtigen Platz und zeichnet ihn dort. Zusätzlich noch double buffering und fertig. Das ist mit der GDI+ wirklich total easy. Für Scrolling und Zooming brauchst du nur die Transformationmatrix ändern, und nichts bei den Objekten neu berechnen.
An: Hans-Georg Lehnard Ich denke das mit dem GDI+ kriege ich hin. Doch was Sie noch beschrieben haben mit der virtuellen Oberklasse klingt für mich sehr interessant, doch es scheint etwas mein Programierwissen zu überschreiten. Könnten Sie mir womöglch noch etwas auf die Sprünge helfen? Wie ich es verstanden habe, kann ich für jedes Element in meinem Client Bereich (also Beispielsweise für den Signalplot) eine Klasse von dieser virtuellen Oberklasse ableiten (Bsp.: class CsignalPlot : public DievirtuelleOberklasse). In dieser virtuellen Oberklasse gibt es die Methode GetPath() (die ist selbstgeschrieben nehme ich mal an?). Diese GetPath() Methode rufe ich in der OnDraw() Methode auf, um den Graphicspath, der den Signalplot enthält, zu erhalten. Ist dies soweit korrekt? Wo implementiere ich nun das Doublebuffering?
Das mit der Ableitung ist so richtig. Der Sinn dahinter ist, das der View nur die virtuelle Oberklasse kennen muss mit der Methode Getpath() und deshalb nicht angepasst werden muss, wenn mal eine neue abgeleitete Klasse dazu kommt. Der GraphicPath braucht auch keinen Graphic Context und muss deshalb nicht innerhalb einer Draw Methode erstellt/geändert werden. Für das double Buffering erzeugst du in deinem View einen (kompatiblen) Memory Context zeichnest in diesen und kopierst dann den Memory Context auf deinen Bildschirm. Damit verhinderst du flackern beim Zeichnen. Dafür gibts genügend Beispiele im Netz. Das einzige Problem mit der GDI+ ist, das alle Bücher und der Großteil der Onlinedokumentationen für .NET geschrieben sind. Aber wenn du mal begriffen hast, wie die C++ Syntax sich von der .Net Syntax unterscheidet ist das auch kein Problem mehr.
:
Bearbeitet durch User
Danke für die Hilfe, ich werde dies so umsetzen. Dieses Forum ist für mich bisher unübertroffen :) Schönen Tag David
So, ich habe mich die letzen Stunden mit diesem Problem beschäftigt, nun sind noch einige Fragen aufgetaucht. Ich erstelle einen Graphicspath in einer Zeichnen-Klasse ( welche von meiner virtuellen Oberklasse abgeleitet ist) und füge diesem Path meine gewünschten Figuren zu. Anschliessend rufe ich in meiner CmyprojectView::OnDraw() Methode meine GetPaht() Mehtode auf und bekomme den GraphicsPath zurück. Diesen GraphicsPath gebe ich nun auf den Bildschirm aus
1 | graphics.DrawPath(myPen,myGraphicsPath) |
Das Problem ist, ich möchte ein ganzes Bild in meiner Zeichnen-Klasse erstellen mit Hintergund, Achsen, Signallinie und das ganze in verschiednen Farben und nicht nur Shapes. Anschliessend möchte ich dieses ganze Bild an die CmyprojectView::OnDraw() Methode übergeben und dort ausgeben. Wie kann ich das machen?
Du wolltest mehrere (unabhängige) Bereiche oder ? Aber in Wirklichkeit willst du nur die Zeichenbefehle, die normalerweise im View stehen in eine eigene Klasse packen. Das macht meines Erachtens nicht viel Sinn, denn du gewinnst dadurch überhaupt nichts und hast nur eine zusätzliche Klasse und einen zusätzlichen Methodenaufruf. Vergiss alles was ich geschrieben habe und schreib dir dann eine Klasse mit einer Draw Methode welche alles malt was du willst. Du musst nur dieser Draw Methode die Client Grösse deines Views und den Grafic Context übergeben. Diese Klasse solltest du dann aber "IchMaleAllesWasDerViewSonstMalt" taufen ;)
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.