Delphi-PRAXiS
Seite 1 von 2  1 2      

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 Menüs zur Laufzeit (https://www.delphipraxis.net/39744-menues-zur-laufzeit.html)

DelphiSourcer 7. Feb 2005 11:51


Menüs zur Laufzeit
 
Hallo, liebe Delphianer!

Weil ich in die Tiefen der Delphi-Programmierung einsteigen will und als fortgeschrittener nun auch die Interna besser verstehen will, bin ich dabei,
Menüs zur Laufzeit zu erstellen und zur Laufzeit uneingeschränkt darauf zuzugreifen. Außerdem halte ich diese Vorgehensweise bei der Erstellung mehrsprachiger Anwendungen für unabdingbar, da ich dann die Captions der Menüeinträge leicht an die gewünschte Sprache anpassen kann. Leider funktionirt der Code noch nicht. Deshlb bitte ich um Eure Hilfe und zeige Euch an dieser Stelle meinen Quellcode:

{-----------------------------------------------------------------------------
Unit Name: main
Author: Projektmaster
Purpose: Building menus at runtime
History:
-----------------------------------------------------------------------------}


unit main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls;

type
TForm1 = class(TForm)
LBox: TListBox;
btnShow: TButton;
btnEnde: TButton;
procedure FormCreate(Sender: TObject);
procedure Beenden1Click(Sender: TObject);
procedure btnShowClick(Sender: TObject);
procedure btnEndeClick(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
Menu: TMainMenu;
MenuItems: array of TMenuItem;
SubItems: array of TMenuItem;
Datei,
Bearbeiten,
Fenster,
Hilfe: TMenuItem;

Neu,
Oeffnen,
N1,
Beenden: TMenuItem;

end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
//Hier will ich zur Laufzeit mein Menü aufbauen.
//Grund:
// Das soll später mehrsprachig werden
// Da werden dann den Captions ResourceStrings
// zugewiesen, die von der gewünschten Sprache
// abhängen.

Menu := TMainMenu.Create(self);
Datei := TMenuItem.Create(Self);
Datei.Caption := 'Datei';

Bearbeiten := TMenuItem.Create(Self);
Bearbeiten.Caption := 'Bearbeiten';

Fenster := TMenuItem.Create(Self);
Fenster.Caption := 'Fenster';

Hilfe := TMenuItem.Create(Self);
Hilfe.Caption := 'Hilfe';

Neu := TMenuItem.Create(self);
Neu.Caption := 'Neues Projekt öffnen...';
N1 := TMenuItem.Create(self);
N1.Caption := '-';
Oeffnen := TMenuItem.Create(self);
Beenden := TMenuItem.Create(self);
Beenden.Caption := 'Programm &Verlassen';
Beenden.OnClick := Beenden1Click;
Oeffnen.Caption := 'Existierendes Projekt öffnen...';

Menu.Items.Add(Datei);
Menu.Items.Items[0].Insert(0,Neu);
// Sobald ich Untermenüs einfügen will, Wird Exception
// EListError ausgelöst
// Meldung: Listenindex überschreiete das Maximum (1)
// Menu.Items.Items[1].Add(Oeffnen);
// Menu.Items.Items[2].Add(N1);
// Menu.Items.Items[3].Add(Beenden);

Menu.Items.Add(Bearbeiten);
Menu.Items.Add(Fenster);
Menu.Items.Add(Hilfe);

end;

procedure TForm1.Beenden1Click(Sender: TObject);
begin
Close;
end;

procedure TForm1.btnShowClick(Sender: TObject);
var i,j,k: Integer;
begin
if Menu <> nil then
if Menu.Items.Count > 0 then
for i:=0 to Menu.Items.Count-1 do
LBox.Items.Add(Menu.Items[i].Caption);

//Warum wird hier die Exception EListError ausgelöst, Meldung:
//Listenindex überschreiete das Maximim (4)
//wenn ich diesen Code ausführe ?
{

Ich will hier die Untermenüs anzeigen, weil ich lernen will,
wie sich das Menü, das ich so wunderbar mit dem Designer er-
stellen läßt, denn nun intern aufbaut.

j := 0; // wenn ich das gleiche mit for... mache, gleiches Erebnis.
while j <= Menu.Items[i].Count-1 do begin
LBox.Items.Add(Menu.Items[i].Items[j].Caption);
inc(j);
end;
}
end;

procedure TForm1.btnEndeClick(Sender: TObject);
begin
Close;
end;

end.

Warum werden die in den Kommentaren angegebenen Exceptions ausgelöst? Wie kann ich mein Problem lösen?

DelphiSourcer

sniper_w 7. Feb 2005 12:04

Re: Menüs zur Laufzeit
 
Du musst wissen, dass nach einer FOR Schleife, die LoopVariable ein undefiniertes Wert hat. Ja, so ist es.

So klappt es :-D

Delphi-Quellcode:
for i:=0 to Menu.Items.Count-1 do
 for j:=0 to Menu.Items[i].Count-1 do
  LBox.Items.Add(Menu.Items[i].Items[j].Caption);

mr47 7. Feb 2005 12:14

Re: Menüs zur Laufzeit
 
[ot]
Herzlich willkommen in der DP! :-D Benutz bitte die den Code-Tag, damit der Quellcode von dir leserlicher wird :!:
[/ot]

urs.liska 7. Feb 2005 12:36

Re: Menüs zur Laufzeit
 
Hallo DelphiSourcer.
Zunächst mal solltest Du die Delphi-Code-Tags verwenden, dann ist Dein Code lesbar (geht auch noch nachträglich mit "Edit").
Zitat:

Zitat von DelphiSourcer
Delphi-Quellcode:
Menu.Items.Add(Datei); //Zeile 1
Menu.Items.Items[0].Insert(0,Neu); //Zeile 2 
// Sobald ich Untermenüs einfügen will, Wird Exception
// EListError ausgelöst
// Meldung: Listenindex überschreiete das Maximum (1)
// Menu.Items.Items[1].Add(Oeffnen);
// Menu.Items.Items[2].Add(N1);
// Menu.Items.Items[3].Add(Beenden);

Menu.Items.Add(Bearbeiten);
Menu.Items.Add(Fenster);
Menu.Items.Add(Hilfe);

Wenn ich das richtig verstehe (ich habe das so noch nie gemacht), sieht die Sache so aus:
Zeile 1 erzeugt das Objekt
Delphi-Quellcode:
Menu.Items[0]
Das ist das Menü "Datei". Dieses hat noch keine Untermenüpunkte.
Der Aufruf in Zeile 2 ginge auch kürzer:
Delphi-Quellcode:
Menu.Items[0].Insert(0, Neu) // wg. Default-Property
// alternativ:
Menu.Items[0].Add(Neu)
Damit existiert das Objekt Menu.Items[0].Items[0] (nämlich "Datei->Neu").
Das Objekt Menu.Items[1] existiert aber noch nicht, deshalb wird bei Deinem Versuch, mit Menu.Items[1].Add(Oeffnen) auf das Objekt zuzugreifen, eine Exception ausgelöst.
Der Abschnitt müsste also (wie gesagt, wenn ich es richtig sehe) so aussehen:
Delphi-Quellcode:
Menu.Items.Add(Datei);
Menu.Items[0].Add(Neu);
Menu.Items[0].Add(Oeffnen); /etc.
Den zweiten problematischen Abschnitt habe ich mir nicht angesehen, aber vielleicht hat sich das ja auch erledigt- sofern mein Vorschlag funktioniert.

HTH
Urs

roderich 7. Feb 2005 12:54

Re: Menüs zur Laufzeit
 
hallo DelphiSourcer,

für mehrsprachige Menues müßtest Du aber weder die MenuItems zur Laufzeit erzeugen noch ResourceStrings verwenden.
-> Beim Umschalten der Sprache kannst du auch einfach nur die Captions ändern
-> Den Sinn von ResourceStrings habe ich noch nie verstanden. Wir verwenden Ascii-Dateien mit den Spracheinträgen, die an die Tags der Komponenten gekoppelt sind. Der riesige Vorteil ist der, daß man Sprachdateien einfach mit einem Texteditor ändern kann, ohne das Projekt neu kompilieren zu müssen.

Roderich

DelphiSourcer 7. Feb 2005 13:52

Re: Menüs zur Laufzeit
 
Hallo, allerseits!

Danke wie verrückt für Eure schnelle Hilfe.

sniper_w schreibt, dass es so hier funktioniert:

[ot]
for i:=0 to Menu.Items.Count-1 do
for j:=0 to Menu.Items[i].Count-1 do
LBox.Items.Add(Menu.Items[i].Items[j].Caption);
[/ot]

Perfekt, funktioniert auch, Danke

mr47 schreibt:

[ot]
Herzlich willkommen in der DP! Very Happy Benutz bitte die den Code-Tag, damit der Quellcode von dir leserlicher wird Exclamation
[/ot]

Ok, werde ich beherzigen. Habe bei obigem Quelltext in dieser Antwort das Tag gleich mal verwendet, um zu sehen, ob es wie gewünscht funktioniert.

urs.liska schreibt:

[ot]
Damit existiert das Objekt Menu.Items[0].Items[0] (nämlich "Datei->Neu").
Das Objekt Menu.Items[1] existiert aber noch nicht, deshalb wird bei Deinem Versuch, mit Menu.Items[1].Add(Oeffnen) auf das Objekt zuzugreifen, eine Exception ausgelöst.
Der Abschnitt müsste also (wie gesagt, wenn ich es richtig sehe) so aussehen:
Quellcode: markieren
Menu.Items.Add(Datei);
Menu.Items[0].Add(Neu);
Menu.Items[0].Add(Oeffnen); /etc.
[/ot]

Du hast recht, das war der Grund, warum ich keine weiteren Menüpunkte einfügen konnte. Zu dem anderen Problem hat mir sniper_w bereits gehlfen. Sein Tipp ist hier der richtige.


roderich schreibt:

[ot]
für mehrsprachige Menues müßtest Du aber weder die MenuItems zur Laufzeit erzeugen noch ResourceStrings verwenden.
-> Beim Umschalten der Sprache kannst du auch einfach nur die Captions ändern
[/ot]

Gut und schön, aber wie ordne ich dann den Spracheintrag der richtigen Caption zu? Von Hand ist es klar, aber um die Captions spracabhängig aus einer Datei zu lesen, muss ich zur Laufzeit auf die Menüeinträge zugreifen können. Und durch meine Laufzeitmenüs in meinem Programm, weiß ich nun, wie ich die Captions dann erreiche.

[ot]
-> Den Sinn von ResourceStrings habe ich noch nie verstanden. Wir verwenden Ascii-Dateien mit den Spracheinträgen, die an die Tags der Komponenten gekoppelt sind. Der riesige Vorteil ist der, daß man Sprachdateien einfach mit einem Texteditor ändern kann, ohne das Projekt neu kompilieren zu müssen.
[/ot]

[ot]
-> Den Sinn von ResourceStrings....
[/ot]

Ich nehme an, das man damit verschiedene Stringkonstanten nach folgendem Muster anlegt:

[ot]
ResourceString
sDatei = 'Datei';
sFile = 'File';
............
sBearbeiten = 'Bearbeiten';
sEdit = 'Edit';
............

type TLanguage = (english, german, french, .... );

begin
case Language of
english: Menu.Items[0].Caption := sFile;
german: Menu.Items[0].Caption := sDatei;
french: ...;
end;
end;
[/ot]

Sprachdatei verwenden, ist natürlich auch ein Vorschlag. Werde das testen.

Ich danke Euch noch einmal allen für Eure unkomplizierte schnelle Hilfe und

grüße Euch

DelphiSourcer

DelphiSourcer 7. Feb 2005 13:54

Re: Menüs zur Laufzeit
 
Ich sehe gerade, dass die Tags zwar zu sehen sind, aber der eingeklammerte Text nicht so eingerückt wird, wie erwartet. Ich schlage vor, wir eröffnen ein neues Thema zu diesem Punkt. Werde gleich mal die Frage posten.

DelphiSourcer

scp 7. Feb 2005 14:18

Re: Menüs zur Laufzeit
 
Wenn man Resourcestrings sinnvoll nutzen möchte, kann man auch gleich die "Sprachfunktion" der selbigen nutzen. Erstellt man eine .rc-Datei von Hand, kann man in etwa so vorgehen:
Code:
STRINGTABLE
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
{
65264, "Copying..."
65265, "Optimizing..."
}
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
{
65264, "Kopiere..."
65265, "Optimiere..."
}
So bleibt es dann Windows überlassen, welche Sprache es verwendet, der Nutzer kann es Zentral in der Systemsteuerung ändern.

urs.liska 7. Feb 2005 14:37

Re: Menüs zur Laufzeit
 
nur kurz zu den Tags (mehr schaue ich später an):
[ot] war nur als Hinweis für OffTopic gedacht
Quelltext umschließt man mit [ delphi ] und [ / delphi] (ohne die Leerzeichen)

Urs

DP-Maintenance 7. Feb 2005 14:40

DP-Maintenance
 
Dieses Thema wurde von "Sharky" von "Datenbanken" nach "VCL-Komponenten und Controls" verschoben.
Menüs - Datenbanksparte? Bitte etwas auf die Spartenbeschreibungen achten. Danke.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:54 Uhr.
Seite 1 von 2  1 2      

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