GARANTIR DESCONTO

Fórum Procedure recursivo fecha-me o dataset #290010

29/07/2005

0

Olá a todos,

Estou a usar +- o seguinte código abaixo para me montar o menu,

procedure fazmenu;
ibquery.open
while not ibquery.eof
if tipo = ´M´ then
montamenu(codigo,nil);
next
end.
end


procedure montamenu(codigo : int; menu : titemmenu
Qrmenu.sql.clear;
Qrmenu.sql.add(´Select menu where codigo = codigo´ break by ordem´);
query.open;
while not Qrmenu.eof do begin
if qrmenu.tipo = ´P´ then //programa
begin
NovoItem := TMenuItem.Create(MainMenu1);
NovoItem.Caption := MenuCaption;
MainMenu1.items.Add(novoitem);
end;
else begin
if qrmenu.tipo = ´S´ then //submenu
montamenu(codigo,novoitem);
end;

end;
end;


O programa funciona bem, mas quando tinho o submenu ele monta-me correctamente so que depois desligar o Dataset ibquery do primeiro procedure fazmenu.

Alguem sabe como resolver este problema.

Cumprimentos
portelinha@clix.pt


Porty

Porty

Responder

Posts

29/07/2005

Kotho

Para funcionar corretamente, você terá que criar o componente em tempo de execução:

procedure montamenu(codigo : int; menu : titemmenu
var
vQrmenu: <Classe do componente, por exemplo TSQLQuery>;
begin
vQrmenu := <Classe>.Create(Self);
...
//defina as propriedades de conexão, e outras necessárias
...

...
//no final tem que destruir o objeto
...

FreeAndNil(vQrmenu);
end;


Responder

Gostei + 0

29/07/2005

Rjun

Se você colocasse o código correto da sua aplicação ficaria mais fácil para te ajudar. Baseado no que você postou, fiz umas alterações.


procedure fazmenu; 
begin
  ibquery.open; 
  try
    while not ibquery.eof do
    begin
      if tipo = ´M´ then 
        montamenu(codigo,nil); 
      ibquery.next ;
    end;
  finally
    ibquery.Close;
  end;
end; 

procedure montamenu(codigo : int; menu : titemmenu);
begin 
  Qrmenu.sql.clear;   
  Qrmenu.sql.add(´Select menu where codigo = codigo´ break by ordem´);   // <== não conheço essa cláusula break 
  QrMenu.open; 
  try
    while not Qrmenu.eof do 
    begin 
      if (qrmenu.FieldByName(´tipo´).Value = ´P´) then //programa 
      begin 
        NovoItem := TMenuItem.Create(MainMenu1); 
        NovoItem.Caption := MenuCaption; 
        MainMenu1.items.Add(novoitem); 
      end; 
     else if qrmenu.FieldByName(´tipo´) = ´S´ then //submenu 
       montamenu(codigo,novoitem); 
    end; 
  finally
    Qrmenu.Close;
  end; 
end; 



Responder

Gostei + 0

29/07/2005

Porty

Esta aqui o código todo chamo o botão Button1Click em primeiro,
por favor vê se consegues fazer algo.

procedure TForm1.MontaMenu(Grupo: String; Menu: TMenuItem);
var
Item: TMenuItem;
begin
qry.Close;
qry.SQL.Clear;
Qry.SQL.Add(´SELECT * FROM menu´);
Qry.SQL.Add(´WHERE GRUPO = ´ + Grupo );
Qry.SQL.Add(´ORDER BY ORDEM´);
Qry.Open;
while not Qry.Eof do begin
Item := TMenuItem.Create(nil);
Item.Caption := Qry.FieldByName(´TEXTO´).AsString;
Item.Tag := Qry.FieldByName(´CODIGO´).AsInteger;
if Qry.FieldByName(´TIPO´).AsString = ´M´ then
begin
try Menu1.items.Add(item);
if x2ficheiro1 <> nil then x2ficheiro1.Free;
menu := menu1.Items[qrymenu.FieldByName(´NIVEL´).asinteger];
except showmessage(´Erro ao criar ponto de menu´ + #13 + ´ID: ´ + qrymenu.FieldByName(´CODIGO´).asstring ); end;
end
else
if Qry.FieldByName(´TIPO´).AsString = ´S´ then
begin
Menu.Add(Item); MontaMenu(Qry.FieldByName(´link´).AsString, Item)
end
else
if Length(Trim(Qry.FieldByName(´LINK´).AsString)) > 0 then
begin
try Menu.Add(Item); Item.OnClick := MenuClick;
except showmessage(´Erro ao criar ponto de menu´ + #13 + ´ID: ´ + Qry.FieldByName(´CODIGO´).AsString );
end;
end;
Qry.Next;
end; // while not
item := nil;
Qry.Close;
end;

procedure TForm1.MenuClick(Sender: TObject);
var
Menu: TMenuItem;
Txt: String;
Qry: TQuery;
Frm: TForm;
Frc: TformClass;
begin

end;

procedure TForm1.Button1Click(Sender: TObject);
var menu: TMenuItem; i : integer;
begin
I := 0;
qrymenu.Close;
qrymenu.SQL.Clear;
qrymenu.SQL.Add(´SELECT * FROM menu´);
qrymenu.SQL.Add(´WHERE TIPO = ´ + #39 + ´M´ + 39 );
qrymenu.SQL.Add(´ ORDER BY NIVEL´);
qrymenu.Open;
qrymenu.First;
while not qrymenu.Eof do
begin
try
menu := menu1.Items[0];
except
showmessage(´Erro ao cirar menu´);
end;
MontaMenu(qrymenu.FieldByName(´GRUPO´).AsString, menu);
i := i + 1;
qrymenu.Next;
end;
end;


Responder

Gostei + 0

29/07/2005

Rjun

Aparentemente não ná nada de errado. Fiz algumas alterações. Ve se resolver.

procedure TForm1.MontaMenu(Grupo: String; Menu: TMenuItem);
var
  Item: TMenuItem;
begin
  qry.SQL.Clear;
  Qry.SQL.Add(´SELECT * FROM menu WHERE GRUPO = ´ + Grupo + ´ORDER BY ORDEM´);

  Qry.Open;
  try
    while not Qry.Eof do
    begin
      Item := TMenuItem.Create(nil);
      Item.Caption := Qry.FieldByName(´TEXTO´).AsString;
      Item.Tag := Qry.FieldByName(´CODIGO´).AsInteger;

      try
        if Qry.FieldByName(´TIPO´).AsString = ´M´ then
        begin
          Menu1.items.Add(item);

          if x2ficheiro1 <> nil then
            x2ficheiro1.Free;

          menu := menu1.Items[qrymenu.FieldByName(´NIVEL´).asinteger];
        end
        else if Qry.FieldByName(´TIPO´).AsString = ´S´ then
        begin
          Menu.Add(Item);
          MontaMenu(Qry.FieldByName(´link´).AsString, Item);
        end
        else if Length(Trim(Qry.FieldByName(´LINK´).AsString)) > 0 then
        begin
          Menu.Add(Item);
          Item.OnClick := MenuClick;
        end;
      except
        showmessage(´Erro ao criar ponto de menu´ + #13 + ´ID: ´ + Qry.FieldByName(´CODIGO´).AsString );
      end;

      Qry.Next;
    end; // while not
    item := nil;
  finally
    Qry.Close;
  end;
end;

procedure TForm1.MenuClick(Sender: TObject);
var
  Menu: TMenuItem;
  Txt: String;
  Qry: TQuery;
  Frm: TForm;
  Frc: TformClass;
begin

end;

procedure TForm1.Button1Click(Sender: TObject);
var
  menu: TMenuItem;
  i : integer;
begin
  i := 0; //<== Variável sem utilidade nenhuma.

  qryMenu.Close;
  qrymenu.SQL.Clear;
  qrymenu.SQL.Add(´SELECT * FROM menu WHERE tipo = ´´M´´ ORDER BY nivel´);
  qrymenu.Open;

  while not qrymenu.Eof do
  begin
    try
      menu := menu1.Items[0];
      MontaMenu(qrymenu.FieldByName(´GRUPO´).AsString, menu);
      i := i + 1;
    except
      showmessage(´Erro ao criar menu´);
    end;
    qrymenu.Next;
  end;
end;



Responder

Gostei + 0

29/07/2005

Jairroberto

Olá, pessoal!

Não entendi porque vocês desconsideraram a resposta correta do Kotho!

Quando você chama recursivamente o procedimento ´MontaMenu´ de dentro do loop pelos dados do componente denominado ´Qry´, logo na primeira linha do ´MontaMenu´ a chamada recursiva fecha automaticamente o ´Qry´ por limpar o conteúdo da sua propriedade ´SQL´ (Qry.SQL.Clear;). Para conseguir fazer essa chamada recursiva é preciso ter uma variável local no procedimento ´MontaMenu´ do tipo ´TQuery´ (ou outro que seja utilizado). Veja uma parte do código modificado:

procedure TForm1.MontaMenu(Grupo: String; Menu: TMenuItem);
var
  Item: TMenuItem;
  Qry: TQuery;
begin
  Qry := TQuery.Create(Self);
  try
    // Ajuste a linha abaixo com o DatabaseName correto
    Qry.DatabaseName := ´NomeDoDatabase´;
    Qry.SQL.Add(´SELECT * FROM menu WHERE GRUPO = ´ + Grupo + ´ORDER BY ORDEM´);

    Qry.Open;
    try
      while not Qry.Eof do
      begin
        ...
          { Esta chamada recursiva cria outro componente Qry,
             mantendo aberto o que foi criado no escopo atual }
          MontaMenu(Qry.FieldByName(´link´).AsString, Item);
        ...
        Qry.Next;
      end;
    finally
      Qry.Close;
    end;
  finally
    Qry.Free;
  end;
end;


Um abraço,
Jair


Responder

Gostei + 0

29/07/2005

Porty

Olá, pessoal!

Não entendi porque vocês desconsideraram a resposta correta do Kotho!

Quando você chama recursivamente o procedimento "MontaMenu" de dentro do loop pelos dados do componente denominado "Qry", logo na primeira linha do "MontaMenu" a chamada recursiva fecha automaticamente o "Qry" por limpar o conteúdo da sua propriedade "SQL" (Qry.SQL.Clear;). Para conseguir fazer essa chamada recursiva é preciso ter uma variável local no procedimento "MontaMenu" do tipo "TQuery" (ou outro que seja utilizado). Veja uma parte do código modificado:


Atenção pessoal a Query que é fechada é a QryMenu e não da qry do procedimento montamenu.
Um abraço,


Responder

Gostei + 0

29/07/2005

Porty

Olá pessoal.

Já Funcionou com a dica do JairRoberto. Mas tenho agora uma pequena dúvida quando ele diz para

qry.DatabaseName := //coloca o nome da bd

tive que criar no BDE o alias para o caminho da base dados firebird.

Se no meu projecto já tenho uma ligação directa com o TIBdatabase não posso associar a query? E que assim tenho que definir sempre o alias no BDE.

Obrigada


Responder

Gostei + 0

29/07/2005

Jairroberto

Olá, porty!

Atenção pessoal a Query que é fechada é a QryMenu e não da qry do procedimento montamenu.


A ´QryMenu´ você fecha explicitamente, já a ´Qry´ do ´MontaMenu´ é fechada automaticamente quando você atribui um novo valor para a propriedade ´SQL´. Leia novamente a minha resposta com atenção para entendê-la melhor.

Sobre o ´DatabaseName´, ajustei o exemplo de acordo com os elementos que você passou na pergunta, por isso supus que você estivesse usando TQuery (BDE). Mas se você está usando IBX, é só adaptar os componentes e suas propriedades:

var
  Qry: TIBQuery;
begin
  Qry := TIBQuery.Create(Self);
  try
    Qry.Database := IBDatabase1;
    Qry.Transaction := IBTransaction1;
    Qry.SQL.Add(´SELECT * FROM menu WHERE GRUPO = ´ + Grupo + ´ORDER BY ORDEM´);
    ...


Um abraço,
Jair


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar