Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Dynamische Fenster über Funktion ansteuern (https://www.delphipraxis.net/54377-dynamische-fenster-ueber-funktion-ansteuern.html)

cback 3. Okt 2005 13:38


Dynamische Fenster über Funktion ansteuern
 
Hallo,

ich bin momentan dabei eine neue Version von meinem MOD-Editor zu programmieren. Dabei habe ich nun ein sicher kleineres Problem und bräuchte da mal einen kleinen Denkanstoß. :zwinker:

Das Editorfenster kann mehrfach geöffnet werden, falls man mehrere Dateien bearbeitet. Das geht z.B mit so einem Code:


Delphi-Quellcode:
procedure ...;
  var EditorMOD: TEditor_MOD;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Caption := 'CBACK MIRO - Mod Editor';
  EditorMOD.Show;
end;
In diesem Editor gibt es unter anderem eine Prozedur die zu dem Editor Aktionen hinzufügt oder gewisse häufiger auftretende Dinge ausführt. Die kleinste Prozedur "AddAction" sieht dann (wenn man das Fenster "fest" benannt hätte) so aus:

Delphi-Quellcode:
procedure AddAction(action:string);
begin
  Editor_MOD.MiroEdit.SelText := #13#10 + '#' + #13#10 + '#-----[ ' + action + ' ]------------------------------------------'+ #13#10 + '#' + #13#10;
  Editor_MOD.MiroEdit.SetFocus;
end;

Und nun das Problem:

Da ich ja das Fenster selber neu in einem Objekt anlege ist ja der feste Name nicht mehr vorhanden. Sprich die Prozedur weiß nicht mehr auf welches angelegte Fenster sie zugreifen muss. Gibt es da vielleicht eine Funktion, mit der man angeben kann, dass in einem aktiven Fenster etwas stattfinden sollte (Bei Javaskript gibts ja z.B das "this"). Oder anderweitig diese Prozedur so erweitern, dass sie weiß welches Fenster gerade geöffnet ist und die Prozedur gestartet hat (Sender oder so?).


Danke im Vorraus für Antworten. :)

Bye
CBACK

SirThornberry 3. Okt 2005 13:45

Re: Dynamische Fenster über Funktion ansteuern
 
Was hindert dich daran die Fenster nach dem du sie erzeugt hast in einer Liste zu speichern (oder notfalls in einem Array)? damit kannst du sie später auch ohne probleme ansprechen. Wenn das Fenster dann zuerstört/freigegeben wird musst du es natürlich auch wieder aus der Liste entfernen.

cback 3. Okt 2005 13:52

Re: Dynamische Fenster über Funktion ansteuern
 
Naja gibts eventuell was performanteres? Jedes Array nimmt ja wieder bissel Arbeitsspeicher weg (gut das hält sich da noch in grenzen aber man will ja versuchen den Code so optimiert wie möglich zu schreiben) :D Außerdem wird hier:

Code:
procedure ...;
  var EditorMOD: TEditor_MOD;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Caption := 'CBACK MIRO - Mod Editor';
  EditorMOD.Show;
end;
ja nicht wirklich ein anderer Fenstername erzeugt, sondern nur angelegt, angezeigt, fertig. Da hätte ich dann das Problem, dass die Fensternamen ja nicht unterschiedlich sind. Ich müsste also doch irgendwie den Sender abgreifen. Nur wie? :pale:

SirThornberry 3. Okt 2005 14:01

Re: Dynamische Fenster über Funktion ansteuern
 
performanter wird es dadurch ja schon weil du die Fenster bedeutend schneller findest als wenn du alle komponenten durchgehen musst.
Bring mal ein konkretes Beispiel wo du nicht weißt auf welche Editorinstanz du zugreifen musst.
Wenn zum Beispiel in deinem erzeugten Fenster ein Btn-Click ausgelöst wird und du das ganze objectorientiert gelöst hast so bekommst du ja auch die Action in der Fensterklasse.

Das beispiel was du gepostet hast ist ja nur das erzeugen des Fensters, an welcher Stelle brauchst du denn die Fensterinstanz?

cback 3. Okt 2005 14:06

Re: Dynamische Fenster über Funktion ansteuern
 
Also wenn ich zum Beispiel im Menü auf die Aktion "OPEN" klicken will, dann wird diese Prozedur oben aufgerufen mit

AddAction('OPEN');

Wenn ich den festen Komponentennamen angebe, dann erscheint der Compilerfehler, dass auf unsichtbare oder versteckte Fenster keine Schreibaktion auf Komponenten durchgeführt werden kann.

Gebe ich den Namen des erzeugten Fensters an, welches ich mit EditorMOD angelegt habe (so werden ja alle angelegt), dann erscheint kein Fehler, aber auch kein Text in dem Editorfeld.

Verzichte ich auf die Prozedur und setze den Inhalt allerdings direkt auf den Menüklick funktioniert es, da es ja dann direkt lokal in die Komponenten eingetragen wird.


Ich scheitere da momentan daran, wie ich der Prozedur mitteile von wo ich den Button geklickt habe. Das Objekt hat ja den gleichen Namen (EditorMOD), wird immer nur nochmal neu angelegt und dann angezeigt, also da entsteht eigentlich kein anderer Name dabei. Oder vielleicht intern irgendwo?

Daniel 3. Okt 2005 14:12

Re: Dynamische Fenster über Funktion ansteuern
 
Du schreibst also eine MDI-Anwendung? Und die Routine 'addAction()' soll mit dem jeweils aktuellen Fenster etwas anstellen? Sehe ich das richtig?

Dann schaue doch mal, ob Du mit der Eigenschaft 'ActiveMDIChild' des Hauptfensters weiterkommst. Das liefert nämlich eine Referenz auf genau das Fenster, das Du suchst.

Zitat:

Jedes Array nimmt ja wieder bissel Arbeitsspeicher weg (gut das hält sich da noch in grenzen aber man will ja versuchen den Code so optimiert wie möglich zu schreiben)
Den Speicher, den dieses Array wegnimmt, kannst Du absolut vernachlässigen. Wieviele Fenster kann denn Dein Anwender gleichzeitig öffnen? Oder anders gefragt: Wieviele wird er im Schnitt tatsächlich offen haben, ohne sich in der Fenster-Liste zu verirren? Greifen wir hoch und sagen, Du hättest es mit einem Anwender zutun, der 50 Dokumente gleichzeitg im Sinn behalten kann. Dann hättest Du 50 Pointer á 32bit. Zum "optimierten" Code gehört auch eine gewisse Wartbarkeit sowie eine gewisse Lesbarkeit.

Wenn Du das, was Du beabsichtigst, mit einem solchen Array klar und verständlich in Programmcode umsetzen kannst, machst Du einen sehr großen Schritt in Richtung eines gut strukturierten Programms. Optimiere dort, wo Du tatsächlich große Mengen an Speicher und/oder Rechenzeit verbrätst. Aber nicht an den Stellen, wo es sich um 200 Bytes dreht - das lohnt sich meistens nicht.

Um nochmal auf den Ursprung zu kommen: Sehe Dir mal das MDI-Demo von Delphi an, falls Fragen zum Handling der Fenster auftauchen.

cback 3. Okt 2005 14:18

Re: Dynamische Fenster über Funktion ansteuern
 
Es ist keine echte MDI Anwendung, also die neu erzeugten Forms sind eigenständig und keine MDI Childs eines Hauptforms. Das mit dem Array ist dann wohl doch die einzige Lösung. Die Frage ist nur, da ich das Fenster immer so anlege:

Delphi-Quellcode:
procedure ...;
  var EditorMOD: TEditor_MOD;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Show;
end;
woher weiß ich dann wie das Fenster intern heißt? Und wie könnte ich dann auf diese Informationen in der Prozedur zugreifen? Also das Array dann auf jeden Fall schon mal superglobal anlegen damit es überall verfügbar ist. Nur dann das irgendwie ausgelesen bekommen, die Fenster selber werden immer als EditorMOD angelegt. :gruebel:


Schon mal danke an alle für die Antworten. :)

Daniel 3. Okt 2005 14:24

Re: Dynamische Fenster über Funktion ansteuern
 
Wie sehr fühlst Du Dich in der Delphi-Welt zuhause? Ich frage nur, weil ich wissen möchte, wo ich ansetzen soll, wenn ich einen Lösungs-Vorschlag skizziere.

Ich habe aber noch eine andere Frage: Wie hängen diese Fenster zusammen? Warum eine Anwendung, die mehrere Fenster startet (und doch keine MDI-Anwendung ist) und nicht mehrere Instanzen dieser Anwendung, die jeweils ein Fenster bieten? Ich denke da an eine Situation, in der man zum Beispiel 10 x Notepad.exe öffnet.

cback 3. Okt 2005 14:32

Re: Dynamische Fenster über Funktion ansteuern
 
Zitat:

Zitat von Daniel
Wie sehr fühlst Du Dich in der Delphi-Welt zuhause? Ich frage nur, weil ich wissen möchte, wo ich ansetzen soll, wenn ich einen Lösungs-Vorschlag skizziere.

Fortgeschritten würd ich mal bei diesem Thema mit Objekten sagen. :)

Zitat:

Ich habe aber noch eine andere Frage: Wie hängen diese Fenster zusammen? Warum eine Anwendung, die mehrere Fenster startet (und doch keine MDI-Anwendung ist) und nicht mehrere Instanzen dieser Anwendung, die jeweils ein Fenster bieten? Ich denke da an eine Situation, in der man zum Beispiel 10 x Notepad.exe öffnet.
Also es gibt verschiedene Editorenlayouts da ist das dann so meiner Meinung nach etwas übersichtlicher zu handhaben. Vom Leistungsverbrauch her (ich hatte erst mal mit MDI angefangen und fand das dann vom Layout her nicht so) kommt es aber aufs gleiche hinaus. Hier mal ein Screenshot wie das aussieht wenn 2 der Editorfenster geöffnet sind, das blaue dahinter ist dann das Startfenster. Darüber können dann die Editoren aufgerufen werden, sollte das Programm ohne Parameter aufgerufen worden sein (wenn das der Fall ist startet dann die geöffnete Datei automatisch im passenden Editor)

Daniel 3. Okt 2005 14:47

Re: Dynamische Fenster über Funktion ansteuern
 
Fein. :-)

Dann hst Du ja die wesentlichen Dinge schon zusammen. Dein Hauptfenster könnte dann für Deine eigene Fensterverwaltung der Dreh- und Angelpunkt werden. Dort würde ich mir eine Liste (Delphi-Referenz durchsuchenTList) deklarieren (ich find's mit Listen einfacher als mit Arrays) und dann eine Referenz auf jedes neu erzeugte Fenster in dieser Liste ablegen:

Delphi-Quellcode:
procedure ...;
  var EditorMOD: TEditor_MOD;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Show;

  meineFensterListe.add( EditorMOD );
end;
Damit kannst Du Dir einen Überblick über alle derzeit offenen Fenster verschaffen. Jedoch musst Du ein Editor-Fenster wieder aus der Liste rauswerfen, wenn Du es schließt.

Willst Du also eine Aktion mit allen Fenstern machen, läufst Du einfach über die Liste und castest die Listenelemente auf den Typ "TEditor_MOD".

Wenn Du feststellen willst, was das aktuelle Fenster ist, so könntest Du Das Ereignis "onActivate" Deiner Editor-Fenster nutzen und in dem Ereignis-Handler Deinem Hauptfenster mitteilen, wer jetzt gerade aktuell ist:

Delphi-Quellcode:
Hauptfenster.setAktuellesEditFenster( self ); // Pseudocode...
Diese Routine "setAktuellesEditFenster()" merkt sich dann in einer Variablen die Referenz, die sie eben als Parameter erhalten hat.

Und Deiner eingangs angesprochenen Routine "AddAction" könntest Du dann als Parameter eine Referenz auf das Fenster mitgeben, mit dem sie arbeiten soll.



Aber viele Wege führen nach Rom ... mit mehr Kenntnis über die Architektur Deiner Anwendung könnte man vielleicht auch andere sinnvolle Vorschläge bringen. Unter Umständen macht es Sinn, eine Methode wie "addAction()" gleich als Methode Deines Editor-Fensters zu deklarieren. Dann könntest Du mit einem Aufruf wie
Delphi-Quellcode:
AktuellesEditFenster.addAction('');
irgendwas veranstalten.

cback 3. Okt 2005 15:10

Re: Dynamische Fenster über Funktion ansteuern
 
Alles klar, das hat mir schon weitergeholfen. :thumb:

Vielen Dank für die Hilfe :)

mschaefer 3. Okt 2005 16:20

Re: Dynamische Fenster über Funktion ansteuern
 
Moin, zusammen,

also ich habe da bei Torry noch was hilfreiches. Dort findet sich eine Routine, die alle Formualare einer Liste enumeriert.
Um an Daniels TList anzuknüpfen: Könnte mir vorstellen, dass man dort automatisch alle Formulare eintragen lässt.

Kurzum der Link: enumerate all TForms of a Project

Grüße // Martin

Igotcha 3. Okt 2005 16:26

Re: Dynamische Fenster über Funktion ansteuern
 
Warum geht "Self" nicht?

So wie ich das verstanden habe, ist die Funktion bestandteil der Form.

Dann also:

Delphi-Quellcode:
procedure AddAction(action:string);
begin
  Self.MiroEdit.SelText := #13#10 + '#' + #13#10 + '#-----[ ' + action + ' ]------------------------------------------'+ #13#10 + '#' + #13#10;
  Self.MiroEdit.SetFocus;
end;
Gruß Igotcha

cback 3. Okt 2005 16:43

Re: Dynamische Fenster über Funktion ansteuern
 
Self kann man bei Delphi ja nur in so dingen benutzen wie Create(self) usw. aber nicht als bezeichnung des aktiven, das geht nur bei JavaSkript soweit mir bekannt ist. Wenn man nur Self schreibt würde das zu nem undefinierten Bezeichner führen.

cback 3. Okt 2005 17:53

Re: Dynamische Fenster über Funktion ansteuern
 
Hi,

ich habe mal etwas rumexperimentiert und eine wesentlich einfachere und bessere Methode herausgefunden. Bei den ersten uses im Hauptformular wo also Windows, Messages usw. eingebunden ist füge ich einfach den Komponentennamen noch hinzu:

Delphi-Quellcode:
, editor_miro
wobei editor_miro der Name des Forms ist.

Anschließend lege ich die Objektvariable nicht nur lokal an, da wo ich vorher das Fenster geöffnet habe, sondern Superglobal, also in die var-Liste noch vor "implementation"

Delphi-Quellcode:
  EditorMOD : TEditor_MOD;

Das öffnen der Fenster bleibt identisch, nur habe ich halt keine var mehr lokal gebraucht, da diese Superglobal besteht also aus

Delphi-Quellcode:
procedure ...;
  var EditorMOD: TEditor_MOD;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Caption := 'CBACK MIRO - Mod Editor';
  EditorMOD.Show;
end;
wurde nun

Delphi-Quellcode:
procedure ...;
begin
  EditorMOD := TEditor_MOD.Create(self);
  EditorMOD.Caption := 'CBACK MIRO - Mod Editor';
  EditorMOD.Show;
end;


Soo und im Editorfenster die Prozedur sieht nun einfach so aus:
Delphi-Quellcode:
procedure AddAction(action:string);
begin
  EditorMOD.MiroEdit.SelText := #13#10 + '#' + #13#10 + '#-----[ ' + action + ' ]------------------------------------------'+ #13#10 + '#' + #13#10;
  EditorMOD.MiroEdit.SetFocus;
end;


So kann ich diese Prozedur nun auch nutzen wenn mehrere Fenster geöffnet werden und es wird auch im richtigen Fenster zugeordnet. Ich brauche also kein Array, keine Liste, nix. Also die einzige Änderung ist, das Objekt für die Multi-Fenster nicht lokal, sondern Superglobal anzulegen, wie beispielsweise das beim Hauptformular von Delphi gemacht wird.


:bounce1:

Khabarakh 3. Okt 2005 18:08

Re: Dynamische Fenster über Funktion ansteuern
 
:gruebel: Wie schickst du dann Actions an Fenster, die nicht das zuletzt erstellte sind? Oder geht es nur um dieses?

cback 3. Okt 2005 18:12

Re: Dynamische Fenster über Funktion ansteuern
 
Ich kann die Actions in allen Fenstern senden, das Windows API macht nämlich den Rest, das Fenster muss von Delphi so nur erzeugt werden. Wo es dann letztendlich hingeht verwaltet das Windows Fenstersystem. Die Actions werden nur in dem Fenster angezeigt, von wo sie aufgerufen wurden, also genau so wie es sein soll. :-D

Igotcha 3. Okt 2005 18:18

Re: Dynamische Fenster über Funktion ansteuern
 
Zitat:

Zitat von cback
Self kann man bei Delphi ja nur in so dingen benutzen wie Create(self) usw. aber nicht als bezeichnung des aktiven, das geht nur bei JavaSkript soweit mir bekannt ist. Wenn man nur Self schreibt würde das zu nem undefinierten Bezeichner führen.

Nee nee, "Self" ist das Objekt selber.

Khabarakh 3. Okt 2005 18:20

Re: Dynamische Fenster über Funktion ansteuern
 
Ich muss zugeben, dass ich von Actions keine Ahnung habe :oops: .
Aber trotzdem, wenn diese Funktion - von wem auch immer - aufgerufen wird, wird doch immer das Edit im zuletzt erstellten Formular geändert?
Delphi-Quellcode:
procedure AddAction(action:string);
begin
  EditorMOD.MiroEdit.SelText := #13#10 + '#' + #13#10 + '#-----[ ' + action + ' ]------------------------------------------'+ #13#10 + '#' + #13#10;
  EditorMOD.MiroEdit.SetFocus;
end;

marabu 3. Okt 2005 18:28

Re: Dynamische Fenster über Funktion ansteuern
 
Hallo Sebastian,

lass dich nicht vom Namen täuschen - es geht hier nicht um TAction. Außerdem stolperst du gerade über den nicht vorhandenen qualifier vor dem procedure identifier "AddAction" - da steht mitnichten TEditorMod.AddAction. Und außerdem wäre der Zugriff über die globale Form-Variable bei mehreren Instanzen ein grober Fehler.

Grüße vom marabu

cback 3. Okt 2005 18:54

Re: Dynamische Fenster über Funktion ansteuern
 
Japp dieser Weg funktioniert prima. Das Form wird nur erzeugt, die Verwaltung selbst übernimmt das Windows Fenstersystem intern, das muss Codetechnisch nicht nochmal explizit gemacht werden, da dies Teil der API ist. Also auch keine Konfikte oder ähnliches. Und mit dem AddAction nicht täuschen lassen, so heißt nur die Prozedur. Ich könnte sie auch "SchreibinEdit" nennen oder so. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz