Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - TMainMenu... Wie funktionierts?


Dhakiyah - Mi 08.07.09 14:31
Titel: TMainMenu... Wie funktionierts?
Hallo!
Möchte folgendes machen:
Oben in der Leiste soll zum Beispiel erscheinen:
Seiten
- Seite 1
- Seite 2

Wenn ich auf Seite 1 klicken soll unten dann Seite 1 geladen werden. Drücke ich Seite 2, dann Seite 2. Wie gehts? Muss ich zuerst Seite 1 und 2 programmieren und dann über das Menü laden oder wie geht das?
Wisst ihr was ich meine?

LG
Jasmin


Andreas L. - Mi 08.07.09 14:48

Was genau soll denn geladen werden? Verwendest du einen TWebBrowser, TImage, TMemo? Grundsätzlich musst du im Menü-Designer nur auf einen deiner Einträge doppelklicken und kannst dann deinen "Seitenaufruf" implementieren.


Dhakiyah - Mi 08.07.09 14:51

*hust*
Ich weiß nicht, was ich benutze.
Ich weiß nur das ich oben eine Auswahl haben soll und unten die entsprechenden Seiten geladen werden sollen. Ich soll ein Zeiterfassungsprogramm schreiben.
Dann soll oben zum Beispiel sein im Menü:
Urlaubsantrag
Gleitzeitantrag
etc.
Wenn ich dann oben etwas auswähle wird die Seite oder wie man das halt macht geladen... Verstanden?


Andreas L. - Mi 08.07.09 14:55

Schau dir mal TPageControl (Kategorie Win32) an. Wenn du da drauf einen Rechtsklick machst, kannst du weitere Seiten hinzufügen. Ist es das was du suchst?


Dhakiyah - Mi 08.07.09 15:01

Ich weiß es nicht.
Ich weiß auch nicht wie ich es erklären soll... :cry:
Ich denke ich muss mehrere Seiten programmieren und die im Hauptprogramm "laden", aber ich weiß nicht wie...

Ach mist... :cry:


jaenicke - Mi 08.07.09 15:07

Möglichkeiten:


Dhakiyah - Mi 08.07.09 15:11

Und wie lade ich dieses Formular oder was auch immer in die Hauptseite rein?


jaenicke - Mi 08.07.09 15:21

Wenn du mehrere Oberflächen direkt in dem Hauptformular haben willst, dann bleiben nur noch die ersten beiden Möglichkeiten.

TPageControl hat direkt mehrere Seiten, die kannst du wie gesagt über das Kontextmenü hinzufügen.
Für MDI-Formulare stellst du FormStyle des Hauptformulars auf fsMDIForm und das weiterer Formulare auf fsMDIChild. Wenn du jetzt weitere Formulare erzeugst, dann landen diese im Hauptformular.

Theoretisch gäbe es noch die Möglichkeit separate Formulare einzufangen und ins Hauptformular zu legen, aber das ist denke ich der falsche Weg, da das so nicht gedacht ist.


Dhakiyah - Mi 08.07.09 15:30

Ich raffs nicht...
Ich hänge mal die Sachen an.
Also habe eine Unit1 und eine Unit2.
In Unit 1 ist das MainMenu indem man je nachdem Unit1 bzw. Unit2 auswählen kann.
ABER WIE???


jaenicke - Mi 08.07.09 16:02

Na gut, hier mal ein Beispiel mit beiden Methoden. Eigentlich ist es ja wirklich nicht so schwer...


Dhakiyah - Mi 08.07.09 16:15

Das erste hatte ich gemeint.
Jo... Für jemanden der Programmieren kann isses mit Sicherheit nicht schwer... :cry:
Kann ich beim ersten auch einstellen, dass erst ein Fenster geschlossen sein muss, bevor das nächste geöffnet wird?

Gruß Jasmin


zuma - Mi 08.07.09 16:17

also, ich würde es so machen:

pro Anwendungsfall (Urlaubsantrag, Gleitzeitantrag, etc.) ein eigenes Formular erstellen,
das alle Anforderungen des jeweiligen Anwendungsfalls abdeckt.

Jedes der Formulare bekommt eine procedure, mit der das Formular sich selber aufruft:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
 type ....  = class(TForm)
   ...
   ...
 private
  ...
  ...
 public
  ... 
  ... 
 end;

procedure ZeigeDeinFormularName; // << wichtig, nach der Formdefiniton

var 
  DeinFormularName: TDeinFormularName;

implementation

procedure ZeigeDeinFormularName; // wichtig, ohne Formularbezeichner (TDeinFormularName.)
begin
 Application.CreateForm(TDeinFormularName, DeinFormularName);
 try
  DeinFormularName.ShowModal;
 finally
  DeinFormularName.Release;
 end;
end;

... weiterer Code ...


Ein weiteres Formular ist dann das Hauptformular.
In diesem werden alle benötigten Units in der 2ten Uses-klausel eingebunden.
Dann machste dein Hauptmenu, wenn du dann auf einen angelegten Menupunkt klickst,
schreibst du an der stelle dein

Delphi-Quelltext
1:
 zeigeDeinFormularName;                    


in deinen Projektoptionen verschiebst du dann unter 'Formulare' noch alle ausser dem Hauptmenue von 'automatisch erzeugen' nach 'Verfügbare Formulare'.
Damit sollte den Problem behoben sein, du hast für alle Anwendungsfälle ein eigenes Formular und das Hautpmenü ist 'nur' noch für die Aufrufe da ;)


jaenicke - Mi 08.07.09 16:25

user profile iconDhakiyah hat folgendes geschrieben Zum zitierten Posting springen:
Kann ich beim ersten auch einstellen, dass erst ein Fenster geschlossen sein muss, bevor das nächste geöffnet wird?
Du kannst ja beim Klick auf den Knopf das bestehende Fenster schließen, alle offenen Kindfenster liegen in dem Array MDIChildren des MDI-Formulars. ;-)


Dhakiyah - Mi 08.07.09 16:27

Ohje... Das ist mir alles zu hoch... :cry:


jaenicke - Mi 08.07.09 16:28

Dann ist doch die einfachste Lösung das PageControl. Ich meine da musst du nichts weiter machen, es kann immer nur eins angezeigt werden und du hast auch nur das eine Formular mit mehreren Seiten. ;-)


ffgorcky - Fr 10.07.09 17:50

Also ich würde das dann auch mit Tabs machen - so wie z.B. in dem Thread "Frage zu: Page Control [http://www.delphi-forum.de/viewtopic.php?t=92628&postorder=asc&highlight=tab+pagecontrol&start=0]"
Um die anderen Tabs zu editieren, müsstest Du dann ja nur den TabIndex während der Entwicklungszeit entsprechend setzen.


Dhakiyah - Do 16.07.09 15:21

Hallo!
Wollte das machen, was Zuma oben erklärt hat, aber irgendwie geht es nicht...

Welchen Namen nehme ich dann für


Delphi-Quelltext
1:
2:
var 
  DeinFormularName: TDeinFormularName;



?????????????????????
Hänge mal die ganzen Dateien an. Vielleicht kann mir ja jemand noch schnell helfen.

LG
Jasmin


Dhakiyah - Do 16.07.09 15:30

Ich habs heraus gefunden.
Nur jetzt öffnet sich das Fenster extra.
Es soll ja unten rein geladen werden in das Hauptformular, wie geht das jetzt?

LG
Jasmin

Edit:
Habe das Hauptformular jetzt auf fsMDIForm und das andere auf fsMDIChild gestellt.

Beim Aufruf kommt jetzt die Fehlermeldung:
Aus einem Sichtbaren Fenster kann kein modales gemacht werden... :(

Wenn ich jetzt das von Zuma wieder lösche und es so mache, wie jaenicke es vorgeschlagen hat, kann ich aber 1000x dieses Fenster öffnen.

Ich möchte genau eine Mischung aus beiden.
Es soll unten ins Hauptformular geladen werden ABER wenn ich ein neues/anderes Fenster aufrufe, soll sich das andere schließen. Es soll immer nur 1 Fenster im Hauptformular zu öffenen sein!!!!


zuma - Do 16.07.09 16:51

user profile iconDhakiyah hat folgendes geschrieben Zum zitierten Posting springen:

Beim Aufruf kommt jetzt die Fehlermeldung:
Aus einem Sichtbaren Fenster kann kein modales gemacht werden... :(


showmodal markieren, F1 drücken ;)

showmodal bedeutet, das du ein Fenster öffnest UND es als (einzig) aktives Fenster einstellst

mach mal aus dem
showmodal ein show;

Dein Schliessen-problem wird sich aber dadurch nicht lösen lassen.

Du müsstest beim Menüklick herausfinden, welches Fenster gerade auf ist
und das dann 'von außen' schließen

z.b (ungetestet, auf die schnelle vor Feierabend ;) )

im Hauptmenu ne Var

Delphi-Quelltext
1:
 FAufgerufen : integer;                    

deklarieren
im Menüklick dann immer als erstes

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
 case Faufgerufen of
  1 : schließeDeinFormularName;
  2 : schließeDein2tesFormularName;
  else
  end;
  FAufgerufen := 1// oder 2 oder 3, usw..
  zeigeDasFormularXY;


in jedem Fenster (wie ZeigeDeinFormularname)
die procedure einbauen :


Delphi-Quelltext
1:
2:
3:
4:
5:
procedure schließeDeinFormularName;
begin
 if Assigned(DeinFormularName) then
  DeinFormularName.Release;
end;


Dhakiyah - Fr 17.07.09 09:01

@jaenicke:

Wie hast du das gemacht, das du mit nur einer Procedure auf alle Seiten zugreifst?
Und wie stellt man das ein, dass er die Tabs-Überschrift/Button nicht anzeigt sondern nur die reine Seite?


Delphi-Quelltext
1:
2:
3:
4:
procedure TfrmPageControl.mniExamplePage1Click(Sender: TObject);
begin
  pgcPages.ActivePageIndex := (Sender as TMenuItem).Tag;
end;


@zuma:
Könntest du ein komplettes Beispiel machen (wenns geht ohne irgendwelche namen zu ändern, einfach so lassen wies ist)... Ich blicke da irgendwie nicht so ganz durch...

Gruß Jasmin


zuma - Fr 17.07.09 09:14

muss sehen, ob ich heute ein bissl zeit finde, dann nehm ich mal dein zip, passe es entsprechend an und lade es wieder hoch


Dhakiyah - Fr 17.07.09 09:24

Egal wie ich es mache ob mit TPagecontrol oder MDI, es geht einfach nix...

Ich habe gekuckt wie jaenicke das macht und es klappt einfach nicht und ich weiß net warum...
Ach alles mist... :bawling:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, Kalender, Protokoll, Zeitnachtrag, Gleitzeitantrag,
  Urlaubsantrag, StdCtrls;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Datei1: TMenuItem;
    Anmelden1: TMenuItem;
    Passwortndern1: TMenuItem;
    Beenden1: TMenuItem;
    bersicht1: TMenuItem;
    Protokoll1: TMenuItem;
    Kalender1: TMenuItem;
    Antrge1: TMenuItem;
    Urlaubsantrag1: TMenuItem;
    Zeitnachtrag1: TMenuItem;
    Gleitzeitantrag1: TMenuItem;
    Hilfe1: TMenuItem;
    Info1: TMenuItem;
    procedure Kalender1Click(Sender: TObject);
    procedure Protokoll1Click(Sender: TObject);
    procedure Urlaubsantrag1Click(Sender: TObject);
    procedure Zeitnachtrag1Click(Sender: TObject);
    procedure Gleitzeitantrag1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Gleitzeitantrag1Click(Sender: TObject);
begin
  Gleitzeitantrag := TGleitzeitantrag.Create(Self);
  Gleitzeitantrag.Show;
end;

procedure TForm1.Kalender1Click(Sender: TObject);
begin
  Application.Initialize;
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end;

procedure TForm1.Protokoll1Click(Sender: TObject);
begin
  Application.Initialize;
  Application.CreateForm(TForm3, Form3);
  Application.Run;
end;

procedure TForm1.Urlaubsantrag1Click(Sender: TObject);
begin
  Application.Initialize;
  Application.CreateForm(TForm4, Form4);
  Application.Run;
end;

procedure TForm1.Zeitnachtrag1Click(Sender: TObject);
begin
  Application.Initialize;
  Application.CreateForm(TForm5, Form5);
  Application.Run;
end;

end.


Dhakiyah - Fr 17.07.09 09:29

Habs heraus gefunden...
Hatte vergessen es auf MDIChild umzustellen...

GRML...

Was ist der Unterschied?
Code von jaenicke (der nicht geht bei mir)

Delphi-Quelltext
1:
2:
3:
frmExampleChild2 := TfrmExampleChild2.Create(Self);
  frmExampleChild2.WindowState := wsMaximized;
  frmExampleChild2.Show;


Code den ich jetzt verwende:

Delphi-Quelltext
1:
2:
3:
Application.Initialize;
  Application.CreateForm(TForm6, Form6);
  Application.Run;


Xentar - Fr 17.07.09 09:50

Da das ganze mit dem MainMenu nichts mehr zu tun hat, schlage ich vor, dass es hier weitergeht:
http://www.delphi-forum.de/viewtopic.php?t=93711


ffgorcky - Fr 17.07.09 10:43

Zum Thema Child-/MutterFenster:
Also wenn ich die Frage jetzt gerade richtig verstehe, dann müsstest Du nach Möglichkeit schon während der Entwicklung oder in FormOnCreate(*üblicheParameter*) einstellen, dass das Fenster ein "Überfenster"/"Mutterfenster" ist...
Dann hoffe ich, dass das gehen könnte, denn dann ist es ja noch nicht sichtbar...

Edit: Oh - ähm, jetzt habe ich gerade den Beitrag über meinem gelesen - das klingt, als wäre dieses Thema abgeschlossen!


Xentar - Fr 17.07.09 10:51

Na, abgeschlossen noch nicht, aber das mit dem Create lassen wir besser erstmal beiseite ;)


jaenicke - Fr 17.07.09 18:08

user profile iconDhakiyah hat folgendes geschrieben Zum zitierten Posting springen:
@jaenicke:

Wie hast du das gemacht, das du mit nur einer Procedure auf alle Seiten zugreifst?
Ich habe die Eigenschaft Tag der Menüeinträge entsprechend dem Index der dazugehörigen Seite gesetzt. Markiere einfach einmal bei mir die Menüeinträge und schau im Objektinspektor. ;-)
Und dann benutze ich diesen Index und sage, dass diese Seite angezeigt werden soll. Sender ist der Menüeintrag, der angeklickt wurde. Und dessen (im Objektinspektor gesetzte) Eigenschaft Tag lese ich aus.

Delphi-Quelltext
1:
2:
  pgcPages.ActivePageIndex := (Sender as TMenuItem).Tag;
end;


user profile iconDhakiyah hat folgendes geschrieben Zum zitierten Posting springen:
Und wie stellt man das ein, dass er die Tabs-Überschrift/Button nicht anzeigt sondern nur die reine Seite?
Klick einmal deine einzelnen Seiten an (die TabSheets). Dann siehst du im Objektinspektor die Eigenschaft TabVisible. Setze die auf False, dann ist der Tab der Seite nicht sichtbar.

Zudem ist es sinnvoll beim PageControl selbst den TabStyle auf tbsButtons zu setzen, damit außen der Rahmen nicht da ist.

In Delphi kannst du zum Entwurf der Oberfläche über die Strukturanzeige oben links zwischen den Seiten wechseln.


Dhakiyah - Mo 20.07.09 10:24

Hallo!
Also nach Absprache mit meinem Ausbilder, mache ich es jetzt auf diese Art und Weise.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure Tfrm_mdi_main.Protokoll1Click(Sender: TObject);
var i: integer;
begin
  with frm_mdi_main do
    for I := MDIChildCount-1 downto 0 do
      MDIChildren[I].Close;
  Application.CreateForm(Tfrm_mdi_protokoll, frm_mdi_protokoll);
  Application.Run;
end;


Aber trotzdem danke für die Infos auch mit TabSheet, da weiß ich jetzt wenigstens, dass es noch solche Möglichkeiten gibt.

LG
Jasmin