Przestudiowałem Twój kod i napisałem sobie prostą aplikację realizującą pewne rzeczy; Utworzyłem także przykładowy plik bazując na nazwach zaczerpniętych z Twojego kodu, jego zawartość:
[Ogolne]
IloscProgramow=4
IloscPrzekaznikow=2
[Program 0]
NazwaProgramu=Moj program 0
[Program 1]
NazwaProgramu=Moj program 1
[Program 2]
NazwaProgramu=Moj program 2
[Program 3]
NazwaProgramu=Moj program 3
[NazwyPrzekaznikow]
Przekaznik0=Moj przekaznik 0
Przekaznik1=Moj przekaznik 1
Sprawdziłem to, co napisałeś i u mnie działa (po niewielkich modyfikacjach); Analizując Twój kod zdziwiło mnie to, że piszesz:
Problem polega na tym ze chciałbym odwoływać się do tych dynamicznych itemow przez np standardowy button z formy, odwołanie nie możne byc po name bo go będę modyfikował w ini.
ale patrząc na zawartość pliku oraz Twój kod można śmiało napisać, że nie możesz się odwoływać do nazwy kontrolek bo w ogóle ich nie nadajesz - stąd wartość np. MainMenu1.Items[0][0].Name
(jeśli taki istnieje) będzie równoważna z pustym łańcuchem (sprawdzałem); Jeżeli nie nadasz każdej z dynamicznie tworzonych pozycji jakiejkolwiek nazwy to nie ma siły żebyś w ogóle mógł używać takich funkcji jak chociażby FindComponent
, bo ona potrzebuje jako jedyny argument właśnie nazwy szukanej kontrolki; Jak można wywnioskować z Twojego kodu - nowym kontrokom nadajesz jedynie wyświetlaną nazwę (MenuItem.Caption
); Tak więc w swoim teście nadałem nazwy dynamicznie tworzonym kontrolkom i mogę śmiało wykorzystywać funkcje podaną przez @olesio;
IDE programu testującego:
Kod tworzący kontrolki bazując na zawartości pliku INI
:
type
TMainForm = class(TForm)
{...}
private
iProgramsCount,
iRepeatersCount: Word;
{...}
end;
{...}
procedure TMainForm.MenuRunRepeater(Sender: TObject);
begin
Application.MessageBox(PChar('"' + TMenuItem(Sender).Name + '" was clicked!'), 'MenuRunRepeater Proc', MB_ICONINFORMATION);
end;
procedure TMainForm.MenuChooseProgram(Sender: TObject);
begin
Application.MessageBox(PChar('"' + TMenuItem(Sender).Name + '" was clicked!'), 'MenuChooseProgram Proc', MB_ICONINFORMATION);
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
iniPrograms: TINIFile;
miItem: TMenuItem;
I: Word;
begin
iniPrograms := TINIFile.Create(ExtractFilePath(Application.ExeName) + 'Programy.ini');
try
{ PROGRAMS }
iProgramsCount := iniPrograms.ReadInteger('Ogolne', 'IloscProgramow', 0);
for I := 0 to iProgramsCount - 1 do
begin
miItem := TMenuItem.Create(mmMain);
miItem.Name := 'Program' + IntToStr(I);
miItem.Caption := iniPrograms.ReadString('Program ' + IntToStr(I), 'NazwaProgramu', 'Bez nazwy');
miItem.OnClick := MenuChooseProgram;
mmMain.Items[0].Add(miItem);
end;
{ REPEATERS }
iRepeatersCount := iniPrograms.ReadInteger('Ogolne', 'IloscPrzekaznikow', 0);
for I := 0 to iRepeatersCount - 1 do
begin
miItem := TMenuItem.Create(mmMain);
miItem.Name := 'Repeater' + IntToStr(I);
miItem.Caption := iniPrograms.ReadString('NazwyPrzekaznikow', 'Przekaznik_' + IntToStr(I) + '_Nazwa', 'Przekaznik ' + IntToStr(I));
miItem.OnClick := MenuRunRepeater;
mmMain.Items[1].Add(miItem);
end;
finally
iniPrograms.Free();
end;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
var
I: Word;
begin
{ PROGRAMS LIST }
for I := 0 to iProgramsCount - 1 do
mmMain.Items[0].Clear();
{ REPEATERS LIST }
for I := 0 to iRepeatersCount - 1 do
mmMain.Items[1].Clear();
end;
Identyfikatory się różnią od Twoich - napisałem takie bo wolę angielskie, nie problem je oczywiście zmienić by były takie jak masz w swoim programie; Tutaj masz kod wykonywany podczas tworzenia formularza i zwalniania go z pamięci (nie wiem czy mmMain.Items[0].Clear()
faktycznie usunie z pamięci itemy, ale myślę że tak, że nie spowoduje to memlaka); Procedura MenuChooseProgram
wykonywana jest po kliknięciu w dowolny dynamicznie stworzony item w sekcji Programs List
(patrz w projekcie), a procedura MenuRunRepeater
jak można się domyślić wykonywana jest podczas kliknięcia w dowolny item w sekcji Repeaters List
(także patrz w projekcie w załączniku);
Teraz zostaje wywołanie metody Click
dynamicznie stworzonego itema; Nie bardzo rozumiem te słowa:
Elementy menu pobierane sa z ini. chciałbym np. z pozycji buttona wybrać dany item z menu bez względu na caption.
Problem polega na tym ze chciałbym odwoływać się do tych dynamicznych itemow przez np standardowy button z formy
Odwołanie ma być z innej procedury np. onclick buttona.
A teraz to co chce osiągnąć, che odwoływać sie do tych dynamicznych itemow poprzez np button na formie.
Już tego próbowałem z poziomu button.onclick i nie przyniosło rezultatów.
w kółko powtarzasz, że chcesz się z poziomu buttona odwołać do tych itemów, ale co to znaczy odwołać sie do buttona? Chcesz wywołać metodę Click
dynamicznie stworzonego itema czy co? To jest proste, można na sztywno lub dzięki funkcji FindComponent
(ale musisz tym kontrolkom nadać nazwy!); Ja oprogramowałem sobie dwa dodatkowe przyciski by sprawdzić to w jaki sposób da się wywołać je - z pola klasy TSpinEdit
wybierasz indeks pozycji w menu i po kliknięciu w przycisk wywoływana jest przypisana podczas tworzenia metoda; Metody OnClick
obu przycisków wyglądają tak:
procedure TMainForm.btnProgramExecuteClick(Sender: TObject);
begin
{ PROGRAM EXECUTING }
if mmMain.Items[0].Count = 0 then
Application.MessageBox('List of programs is empty!', 'Program executing', MB_ICONSTOP)
else
if seProgramIndex.Value > mmMain.Items[0].Count - 1 then
Application.MessageBox('Current program index is invalid!', 'Program executing', MB_ICONSTOP)
else
mmMain.Items[0][seProgramIndex.Value].Click();
end;
procedure TMainForm.btnRepeaterExecuteClick(Sender: TObject);
begin
{ REPEATER EXECUTING }
if mmMain.Items[1].Count = 0 then
Application.MessageBox('List of repeaters is empty!', 'Repeater executing', MB_ICONSTOP)
else
if seRepeaterIndex.Value > mmMain.Items[1].Count - 1 then
Application.MessageBox('Current repeater index is invalid!', 'Repeater executing', MB_ICONSTOP)
else
mmMain.Items[1][seRepeaterIndex.Value].Click();
end;
Nic nadzwyczajnego - wyświetlają krótki tekst zawierający m.in. nazwę kontrolki, która jest przekazana w argumencie procedury; Jeżeli dany item nie istnieje lub lista jest pusta wyświetlony zostaje odpowiedni komunikat;
Wszystko działa jak należy - odpal mój projekt i przestudiuj, może załapiesz o co chodzi; Kod przeglądaj raczej w kompilatorze IDE, bo tutaj pole jest dość wązkie i zawija linie kodu przez co trudniej się je analizuje; Program testujący napisany w Delphi 7 (Lazarus pewnie by go przełknął ;]);