[ ratko83 @ 28.12.2009. 20:49 ] @
Code:

unit Main;

interface

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

type
  TfrmMain = class(TForm)
    mnuMain: TMainMenu;
    tblMenu: TADOTable;
    procedure FormCreate(Sender: TObject);
    procedure MenuClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FormNames: TStringList;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

function FindMenuItem(Parent: TMenuItem; ACaption: String): TMenuItem;
var
  I: Integer;
begin
  I := 0;
  Result := Parent.Find(ACaption);
  while (Result = nil) and (I < Parent.Count) do
  begin
    Result := FindMenuItem(Parent.Items[I], ACaption);
    Inc(I);
  end;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
var
  M, P: TMenuItem;
  ParentName, MenuName, FormName: String;
begin
  FormNames := TStringList.Create;
  
  while not tblMenu.Eof do
  begin
    ParentName := tblMenu.FieldByName('Parent').AsString;
    MenuName := tblMenu.FieldByName('Name').AsString;
    FormName := tblMenu.FieldByName('Form').AsString;

    P := FindMenuItem(mnuMain.Items, ParentName);
    if P = nil then
    begin
      P := TMenuItem.Create(mnuMain);
      P.Name := ParentName;
      P.Caption := P.Name;
      mnuMain.Items.Add(P);
    end;

    M := TMenuItem.Create(mnuMain);
    M.Name := MenuName;
    M.Caption := M.Name;
    P.Add(M);
    if FormName <> '' then
    begin
      FormNames.Add(FormName);
      M.Tag := FormNames.Count - 1;
      M.OnClick := MenuClick;
    end;

    tblMenu.Next;
  end;
end;

procedure TfrmMain.MenuClick(Sender: TObject);
var
  F: TForm;
  C: TComponentClass;
begin
  F := nil;
  try
    C := TComponentClass(FindClass(FormNames[TMenuItem(Sender).Tag]));
    Application.CreateForm(C, F);
    F.ShowModal;
  finally
    if Assigned(F) then
      FreeAndNil(F);
  end;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  if Assigned(FormNames) then
    FreeAndNil(FormNames);
end;

end.


[Ovu poruku je menjao savkic dana 29.12.2009. u 01:24 GMT+1]
[ savkic @ 29.12.2009. 00:26 ] @
Nisam shvatio šta je tačno tvoje pitanje, možeš li to malo razjasniti?

BTW koristi code tagove prilikom pisanja koda, povećavaju preglednost.
[ ratko83 @ 29.12.2009. 16:02 ] @
Imam neki TMenu koji se sam dopunjuje iz tabele tblmenu, zanima me kako da proseldim tom meniu funkciju ili proceduru kada kliknem na neki item....

Treba mi primer recimo

Type
TGlobalMethod = procedure of object;
published
//PrikaziMe ze nalazi u tabeli tblmenu u polju funkcija
class procedure PrikaziMe;
end;

//edMethodName.Text
class procedure TForm.prikazime;
begin
ShowMessage('Primer treci');
end;

//Kako ovo dodeliti Tmeni-u tj. nekom itemu onclick da bi izvrsio ovaj metod
var
Metod: TGlobalMethod;
begin
//Pokusava da nadje metodu po nazivu
@Metod := FormC.MethodAddress(edMethodName.Text);
//Ako metoda pronadjena pozivamo odgovarajuci proceduralni tip
if Assigned(Metod) then
Metod;
end;



[ Daniel Mauric @ 30.12.2009. 12:20 ] @
(Ako sam dobro razumeo sta hoces...)

Da bi assign-ovao proceduru na OnClick event TMenuItem-a, prvo moras imati kompatibilnu proceduru, znaci signature TMenuItem.OnClick-a je standardni TNotifyEvent, odnosno

TNotifyEvent = procedure(Sender: TObject) of object;

Druga i mozda bolja varijanta je da koristis TAction, pa da samo dodelis akciju na menu item i to je to.

Edit:
Sad vidim da si uspesno vezao onClick, tako da ni meni nije jasno sta je pitanje
[ savkic @ 30.12.2009. 13:56 ] @
Želiš da dodeliš handler samo na osnovu naziva metode (proslediš string i dobiješ metodu)?

Otprilike ovako:

Code:

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private

  public

  published
    procedure Proba(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Typinfo;

procedure TForm1.Button2Click(Sender: TObject);
var
  Method: TMethod;
begin
  Method.Code :=  MethodAddress('Proba');
  Method.Data := Self;
  if Method.Code <> nil then
    SetMethodProp(Button1, 'OnClick', Method);
end;

procedure TForm1.Proba(Sender: TObject);
begin
  Caption := TimeToStr(Now);
end;
[ ratko83 @ 30.12.2009. 17:32 ] @
Ovo mi se svidelo ali je problem u tome koliko ja vidim da samo mogu da pozovem neku formu ali nemogu funkciju ili proceduru....


Link: https://static.elitesecurity.org/uploads/1/1/1101102/dynmenu.zip
[ savkic @ 30.12.2009. 19:23 ] @
> Ovo mi se svidelo ali je problem u tome koliko ja vidim da samo mogu da pozovem neku formu ali nemogu funkciju ili proceduru.

Možeš dodeliti event handler bilo kojoj postojećoj metodi iz published sekcije čiji argumenti se poklapaju. Ako želiš da bilo kakvu proceduru ili funkciju, onda nema načina da se na osnovu naziva dobije njihova adresa, ako ti to treba onda moraš sam izgraditi neku tabelu (može recimo i neki case ili više IFova).
[ tkaranovic @ 31.12.2009. 09:21 ] @
Ako se MenuClick (koji je za sve MenuIteme isti) iz primera izmeni ovako:

Code:

procedure TfrmMain.MenuClick(Sender: TObject);
 type
 TProc = Procedure of object;
var
  Method: TMethod;
  Proc: TProc;
begin
  Method.Code :=  MethodAddress(ProcNames[TMenuItem(Sender).Tag]);
  Method.Data := Self;
  if Method.Code <> nil then begin
   proc := TProc(Method);
   proc;//startovanje razlicitih procedura koje nemaju parametre
  end; 
end;


Umesto FormNames koji čuva imena klasa formi može da se koristi ProcNames sa imenima procedura.
Tako bi svaki MenuItem startovao svoju proceduru, kojima se handler dodeljuje kao na već opisan način.

Može i ovako za funkcije, ali moraju da vraćaju samo isti tip (primer je sa boolean) podataka:

Code:

procedure TfrmMain.MenuClick(Sender: TObject);
 type
 TFunc = Function: boolean of object;
var
  Method: TMethod;
  func: TFunc;
begin
  Method.Code :=  MethodAddress(FuncBNames[TMenuItem(Sender).Tag]);
  Method.Data := Self;
  if Method.Code <> nil then begin
   func := TFunc(Method);
   if func then begin
   
   end;
  end; 
end;