Es happert mit dem Dok / View Modell, weiß nicht wie Anwenden

Squeegee

Mitglied
Hallo Gemeinde,
ich versuch mal, mein Problem anschaulich zu zeigen, hoffe, dass mir das gelingt.

Ich hab eine Dok-Klasse, eine View-Klasse und eine selbst erstellte CButton-Klasse. Diese ist von CView abgeleitet.

In der Dok-Klasse gibt es eine Liste aus Strukturen, die Daten, wie Position, Zustand etc. der Buttons speichert.

Aus der View-Klasse heraus, greife ich nun die Daten aus der Dok-Klasse in der OnPaint über eine Schleife ab, die eben solange läuft, bis alle Buttons dargestellt.
In der Schleife selbst rufe ich die Methode CButton::ShowButton(Daten aus Dok-Klasse) auf.
Dies Methode malt nun über die OnPaint des Buttons selbst diesen Button.

Zur Übersicht hier mal die Schleife in der OnPaint der View-Klasse:
Code:
        Button oneButton;  //Die Struktur
	CRotateButton MyButton;  //temporärer Button
	pDoc->ResetListButtons();
	while ( pDoc->GetButton( oneButton ) )   //Hole Daten
	{
		//Zeige den Button mit den Daten aus der Dok
                MyButton.ShowButton(pDC,oneButton.xPos,oneButton.yPos, 
                oneButton.angle, oneButton.usedBitmap);
	}

Ähnlich funktioniert auch die Prüfung, ob der Button geklickt wurde oder nicht.

So, und jetzt kommt mein Problem:
Ist diese Architektur denn korrekt? Entspricht sie dem Dok / View Modell?
Denn wenn ich objektorientiert denke, dann wäre die Position und all die anderen Daten, die ich derzeit in der Dok habe, eine Eigenschaft des Buttons, müssten also dort gespeichert werden und nicht in der Dok. Dann allerdings müsste ich zwecks Serialisierung eine Doppelableitung machen, nämlich von CView und CDokument.
Das allerdings erscheint mir so gar nicht konform mit dem Dok / View Modell zu sein. ;-)

Wer kann mir da weitergehende Gedanken oder Lösungsvorschläge machen. Wie könnte ich die Architektur abändern?

Ich hoffe, das war einigermaßen verständlich, wenn nicht, bitte nachfragen.


In diesem Zusammenhang gleich das nächste Problem:
Die Lösung, die ich zur Zeit habe, funktioniert soweit eigentlich. Und genau das ist mir eigentlich sehr schleierhaft.
Wenn ich genau die Fläche für ungültig erkläre, auf der ein Button ist, dann malt er auch genau diese Fläche neu. Woher weiß meine OnPaint denn nun bei diesem komplexen Aufbau, was sie neuzeichnen soll und was nicht? Eigentlich kann sie ja nur sequentiell abgearbeitet werden. Das hieße ja aber, dass es keinen Unterschied macht, ob ich den gesamten Bildschirm ungültig erkläre oder nur einen Teil, den er arbeitet ja eh die gesamte OnPaint ab !


Grüße und vielen Dank im Voraus

Squeegee
 
Hi,
ob dein Programmierstil richtig ist, kann ich nicht beurteilen. das Doc-View-Modell dient ja nur als Vereinfachung wegen Trennung zwischen Daten und Darstellung. Man muß es nicht verwenden. Und solange dein Programm funktioniert....
Zu deiner zweiten Frage: Natürlich ist es möglich, mit Invalidate() den gesamten Bildschirm für ungültig zu erklären. dann zeichnet die OnPaint-Methode eben den gesamten Bildschirm neu. Mit InvalideRect() wird nur genau der Teil neu gezeichnet, den du für ungültig erklärst. Und dafür ist das Betriebssystem zuständig. Es ist eigentlich eine Zeitfrage, denn mit InvalideRect() ist die Operation natürlich schneller erledigt.

Mfg

langer
 
Hi langer1801,
ja, mein Betreuer sagte auch, wenns funktioniert, sei es doch in Ordnung. Ich will halt Vermeiden, irgendwann später dann auf Grund einer evtl. schlechten Architektur Probleme zu bekommen.
Und da es um mein Diplom geht, möche ich da möglichst sicher sein. :)

Gruß
Squeegee
 
Hallo Squeegee,

das Document/View-Konzept ist am sinnvollsten für Anwendungen, die ihre Daten in Dateien speichern (Document), die dann in einer oder mehreren speziellen Ansichten (View) angezeigt werden.
Wenn deine Buttonsteuerung (z.B. die Positionierung) auf dynamischen (externen) Daten beruht, gehören diese in Dokument, ansonsten kannst du sie eher im View bzw. damit verbunden Strukturen speichern.
Du solltest vielleicht auch mal schreiben, was dein Programm überhaupt leisten soll (Textverarbeitung, Grafikprogramm oder was auch immer) und was du mit dem Buttonview bewirken willst. Das würde bei der Beurteilung deiner Programmstruktur helfen.

Gruß
MCoder
 
Hallo MCoder,
das Programm stellt nachher eine graphische Benutzeroberfläche zur Verfügung, die über einen Touchscreen bedient wird.
Der Kunde kann diesen nachher mit einer Art "Malprogramm" gestalten, dh. genauso viele Buttons hinzufügen wie er braucht und diese frei auf der Oberfläche anordnen.
Daher die Liste, die all dies dann speichert und die ich im "Malprogramm" als Konfigurationsfile erstelle und serialisiere und dann im eigentlich Programm nur aufrufe.

Mit einem Klick (oder besser einem Patscher auf den Touchscreen :) ) sieht der Button für eine bestimmte Zeit anders aus, um danach wieder in den Grundzustand zurückzukehren.
Während dieser Zeit kann der Benutzer dannn an einem anderen Rechner auf bestimmte Funktionen zugreifen.

Ich habe hier nur die Grundfunktion beschrieben... Natürlich steckt noch entsprechende Funtionalität dahinter, die ist aber Architekturunabhängig


Gruß Squeegee
 
Hallo Squeegee,

nach meiner Meinung ist dein Ansatz hinsichtlich der Doc/View-Architektur in Ordnung.

Du hattest gestern folgendes geschrieben:
Squeegee hat gesagt.:
Wenn wenn ich objektorientiert denke, dann wäre die Position und all die anderen Daten, die ich derzeit in der Dok habe, eine Eigenschaft des Buttons, müssten also dort gespeichert werden und nicht in der Dok.
Die Eigenschaften, also z.B. die Eigenschaft "Farbe" gehören natürlich zum Button, aber der Wert "grün" muss nicht zwangsläufig auch beim Button gespeichert werden. Die Werte zu den Eigenschaften können durchaus von außerhalb kommen. Wenn du also die Zuordnungen hinsichtlich "Eigenschaft" und "Wert der Eigenschaft" entsprechend
berücksichtigst, solltest du zu einem richtigen objektorientierten Ansatz kommen.

Noch eine kleine Anmerkung: Bei einer von CView abgeleiteten Klasse sollte zum Zeichnen der Member OnDraw() überladen werden und kein MessageHandler für OnPaint eingerichtet werden.
 
Hallo MCoder,
also nachdem mir jetzt mehrere Leute gesagt haben, dass die Architektur so in Ordnung ist, werd ich das jetzt mal so lassen.
Deine Ausführungen haben mir aber trotzdem, vor allem im objektorientierten Denken, sehr weitergeholfen, danke schon mal!

Noch eine kleine Anmerkung: Bei einer von CView abgeleiteten Klasse sollte zum Zeichnen der Member OnDraw() überladen werden und kein MessageHandler für OnPaint eingerichtet werden.

Das allerdings hab ich nicht verstanden :)
ich habe die OnDraw in meiner CRotateButton überladen, da diese jedoch protected ist, kann ich ja nicht darauf zugreifen. Und public wollte ich sie nicht machen (geht das überhaupt beim überladen?) Also hab ich getreu meinem Prof eine Hilfsmethode geschrieben.
Na ja, geschrieben ist übertrieben, die ShowButton(...) macht nix anderes als meine überladene OnDraw aufzurufen.
War das so falsch? Mit war nicht bewusst, dass das ein Message-Handler ist, hab sowas bisher (zumindest gewollt :) ) noch nie gemacht.


Gruß Squeegee
 
Da habe ich wahrscheinlich auch noch nicht alles verstanden.

Hat deine Klasse CRotateButton nun CView oder CButton als Basisklasse? Wenn du mit OnDraw arbeitest, tippe ich auf Ersteres. Allerdings ist dann der Klassenname etwas irreführend.

Weshalb deine OnDraw protected ist, verstehe ich auch nicht. Bei meinen Views füge ich sie üblicherweise mit dem Klassenassistenen ein und da wird sie public. Warum willst du denn darauf zugreifen? OnDraw wird vom System aufgerufen, also ähnlich wie OnPaint.
 
Die CRotateButton ist von CView abgeleitet...
Stimmt allerdings, dass der Name leicht irreführend ist, aber es ist nunmal ein Button :( ,
da ist mir nix schlaueres eingefallen.
Die OnDraw hab ich mir ebenfalls über den Assi geholt, allerdings ist mir grade aufgefallen, dass die tatsächlich in allen anderen Fällen public ist. Da war der Assi wohl mies drauf und hat mir die protected gemacht, sehr witzig!

Hmm, na ja und jetzt wären wir wieder beim Ursprungsproblem: Ich hab das immer noch nicht so ganz gecheckt, wann den nun genau eine beliebige OnDraw aufgerufen wird. Derzeit kreiere ich meine CRotateButton ja rein temporär in der OnDraw der eigentlichen View-Klasse (siehe Code ganz am Anfang) und rufe die OnDraw (die ich dann jetzt public machen werde) von dort aus manuell auf.

Ginge Folgendes:
In meiner CList in der Dok-Klasse mache ich mir Instanzen von CRotateButton mit den entsprechenden Daten (Position, Drehung usw.).
Würden die Views von diesen Instanzen dann automatisch bei Invalidate() gezeichnet?


Und wo wir grade so schön drüber reden: Kennst du irgendeine Quelle, Buch, Homepage, oder sonstwas die das MFC-Grundgerüst nicht nur als Gottgegeben ansieht, sondern die auch erklärt, wo die einzelnen Instanzen gebildet werden, und so...
Ich weiß zu Beispiel bis heute nicht wo die Instanzen meiner beiden Views liegen, ich hab nie welche gemacht, trotzdem tuts :confused:


Schon mal vielen Dank für deine Geduld...
Grüße Squeegee
 
Zitat aus dem MSDN zu OnDraw:
Called by the framework to render an image of the document. The framework calls this function to perform screen display, printing, and print preview, and it passes a different device context in each case. There is no default implementation.
 
Zurück