Procedure comum em todos os forms

Delphi

02/09/2004

Boa dia, gostaria de saber como faço para ter uma procedure comum para todos o forms de um programa.

Exemplo:
Tenho uma unit de funções chamada u_Funcoes, em um forma tenho vários botões onde mudarei suas propriedades a medida que é executado algum outro comando. como todos os forms terão esses mesmos botões com as mesmas propriedade, gostaria de saber como faço para utilizar as mesmas funções para todos os forms.

Ps. Tentei criar a procedure deste jeito, mas não deu certo - não consegui compilar o programa
Procedure AtivaAtalhos();
Begin
  OB_Anterior.Enabled:=True;
  OB_Proximo.Enabled:=True;
  OB_Ultimo.Enabled:=True;
  OB_Novo.Enabled:=True;
  OB_Alterar.Enabled:=True;
  OB_Excluir.Enabled:=True;
  OB_Fechar.Enabled:=True;
  OB_Primeiro.Enabled:=True;
  OB_Confirma.Visible:=False;
End;


Obrigado


Lucianogar

Lucianogar

Curtidas 0

Respostas

Lucas Silva

Lucas Silva

02/09/2004

Se você trabalhar com herança de formulários, você pode fazer assim:

No form principal vc declara ela na seção public
Procedure AtivaAtalhos(); virtual; // virtual é pq ela poderá ser implementada nas classes Filhas.



Nas filhas se vc quiser implementar é só colocar:
Procedure AtivaAtalhos(); override;


até mais,
Lucas!


GOSTEI 0
Vinicius2k

Vinicius2k

02/09/2004

Colega,

Vc pode alterar sua procedure para que ela receba o form em que vc chamá-la como parametro... creio que ficaria assim:
procedure AtivaAtalhos(frm: TForm);
var i: Integer;
begin
  with frm do begin
    for i:= 0 to (ComponentCount - 1) do begin
      with Components[i] do begin
        { **** }
        if (Name = ´OB_Anterior´) or (Name = ´OB_Proximo´ ) or
           (Name = ´OB_Ultimo´  ) or (Name = ´OB_Novo´    ) or
           (Name = ´OB_Excluir´ ) or (Name = ´OB_Fechar´  ) or
           (Name = ´OB_Primeiro´) or (Name = ´OB_Anterior´) then
          (Components[i] as TButton).Enabled:= True;
        { **** }
        if (Name = ´OB_Confirma´) then
          (Components[i] as TButton).Enabled:= False;
      end;
    end;
  end;
end;


Para chamar, em qualquer form, basta :
AtivaAtalhos(Self);


Espero ter ajudado...
T+


GOSTEI 0
Bruno Belchior

Bruno Belchior

02/09/2004

sobre a procedure enviada pelo colega utilizae-a assim:

procedure AtivaAtalhos(frm: TForm);
var i: Integer;
begin
with frm do begin
for i:= 0 to (ComponentCount - 1) do begin
with Components[i] do begin
{ **** }
if (Name in [´´OB_Anterior´´,´OB_Proximo´ ,´OB_Ultimo´,´OB_Novo´,
´OB_Excluir´ ,´OB_Fechar´,´OB_Primeiro´,´OB_Anterior´]) then
(Components[i] as TButton).Enabled:= True;
{ **** }
if (Name = ´OB_Confirma´) then
(Components[i] as TButton).Enabled:= False;
end;
end;
end;
end;

porque evitar o ´or´ melhora o desempenho de se código!


GOSTEI 0
Lucianogar

Lucianogar

02/09/2004

Primeiro obrigado pela ajuda, mas infelizmente não esta dando certo
fiz esse segunda opção (vinicius2K) e esta ocorrendo o seguinte erro:

´List index out of bounds (50)´

se alguem puder me ajudar, obrigado


GOSTEI 0
Ipc$

Ipc$

02/09/2004

if (Name in [´´OB_Anterior´´,´OB_Proximo´ ,´OB_Ultimo´,´OB_Novo´, ´OB_Excluir´ ,´OB_Fechar´,´OB_Primeiro´,´OB_Anterior´]) then

Em qual Delphi vc consegue compilar esse código :?:


GOSTEI 0
Vinicius2k

Vinicius2k

02/09/2004

[quote:a0e56962cf=´IPC$´]
if (Name in [´´OB_Anterior´´,´OB_Proximo´ ,´OB_Ultimo´,´OB_Novo´, ´OB_Excluir´ ,´OB_Fechar´,´OB_Primeiro´,´OB_Anterior´]) then
Em qual Delphi vc consegue compilar esse código :?:[/quote:a0e56962cf]
Isso eu tbm queria saber... :?
Estamos tratando de Strings (nome do componente) e não tipos ordinais...


Colega lucianogar, tem certeza de que este trecho estah correto ? :
for i:= 0 to (ComponentCount - 1) do begin 

Vc não se esqueceu do [b:a0e56962cf][color=red:a0e56962cf]-1[/color:a0e56962cf][/b:a0e56962cf] ? Lembre-se de que a contagem de índices de um Array (Components) começa de Zero, por isso é necessário o -1...

T+


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

02/09/2004

gostaria de questionar uma coisa: visto que os botões são conhecidos, porque o laço com a pesquisa de componentes?
não bastaria mencioná-los? com certeza a execução se tornaria muito mais rápida, visto que, com o laço (for..next) a função ficará mais demorada quando o form tiver muitos componentes.

creio que o ideal seria:

procedure AtivaAtalhos(Form: TForm; Ativar: boolean = True);
const Botoes: array[0..8] of string =
    (´OB_Anterior´,´OB_Proximo´,´OB_Ultimo´,´OB_Novo´,´OB_Alterar´,
    ´OB_Excluir´,´OB_Fechar´,´OB_Primeiro´,´OB_Confirma´);
var
    i: byte;
begin
    with Form do
        for i := 0 to High(Botoes) do
            try
                if Botoes[i] = ´OB_Confirma´ then
                    TButton(FindComponent(Botoes[i])).Enabled := not Ativar
                else
                    TButton(FindComponent(Botoes[i])).Enabled := Ativar;
            except
            end;
end;

a sintaxe seria:
AtivarAtalhos(Self) ou, para inverter os botões,
AtivarAtalhos(Self,False)


GOSTEI 0
Ipc$

Ipc$

02/09/2004

gostaria de questionar uma coisa: visto que os botões são conhecidos, porque o laço com a pesquisa de componentes? não bastaria mencioná-los? com certeza a execução se tornaria muito mais rápida, visto que, com o laço (for..next) a função ficará mais demorada quando o form tiver muitos componentes.

Caro colega, se vc verificar a função FindComponent em Classes.pas, notará que ela faz um laço de 0 a Count-1.
Então vc estará fazendo o laço da função 9 vezes.
Se eles estiverem no início, pode ser que seja até mais rápido, pq o laço se encerra quando o componente é encontrado; contudo serão sempre 9 laços.


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

02/09/2004

[size=18:07c5b325e7][b:07c5b325e7]melhor:[/b:07c5b325e7][/size:07c5b325e7]

procedure AtivaAtalhos(Form: TForm; Ativar: boolean = True);
const Botoes: array[0..8] of string =
    (´OB_Anterior´,´OB_Proximo´,´OB_Ultimo´,´OB_Novo´,´OB_Alterar´,
    ´OB_Excluir´,´OB_Fechar´,´OB_Primeiro´,´OB_Confirma´);
var
    i: byte;
    Componente: TComponent;
begin
    with Form do
        for i := 0 to High(Botoes) do
        begin
            Componente := FindComponent(Botoes[i]);
            if Componente <> nil then
            begin
                if Botoes[i] = ´OB_Confirma´ then
                    TButton(Componente).Enabled := not Ativar
                else
                    TButton(Componente).Enabled := Ativar;
            end;
end;

onde se lê TButton, coloque a classe correta.


GOSTEI 0
Vinicius2k

Vinicius2k

02/09/2004

Emerson,

Sua solução estah mais completa e enxuta que a minha, mas discordo de vc quanto à velocidade do laço... o método FindComponent utiliza sobre o container o mesmo laço que eu re-escrevi...
Veja :
function TComponent.FindComponent(const AName: string): TComponent;
var
  I: Integer;
begin
  if (AName <> ´´) and (FComponents <> nil) then
    for I := 0 to FComponents.Count - 1 do
    begin
      Result := FComponents[I];
      if SameText(Result.FName, AName) then Exit;
    end;
  Result := nil;
end;


E se medirmos, talvez nem chegasse a ficar na casa dos milisegundos, mas creio que a sua seria ligeiramente mais lenta que a minha pq vc está fazendo dois laços... um visível e outro embutido na FindComponent...

T+


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

02/09/2004

[quote:275dcdbfc2=´IPC$´]
gostaria de questionar uma coisa: visto que os botões são conhecidos, porque o laço com a pesquisa de componentes? não bastaria mencioná-los? com certeza a execução se tornaria muito mais rápida, visto que, com o laço (for..next) a função ficará mais demorada quando o form tiver muitos componentes.

Caro colega, se vc verificar a função FindComponent em Classes.pas, notará que ela faz um laço de 0 a Count-1.
Então vc estará fazendo o laço da função 9 vezes.
Se eles estiverem no início, pode ser que seja até mais rápido, pq o laço se encerra quando o componente é encontrado; contudo serão sempre 9 laços.[/quote:275dcdbfc2]

[b:275dcdbfc2][size=18:275dcdbfc2]está correto[/size:275dcdbfc2][/b:275dcdbfc2]


GOSTEI 0
Beppe

Beppe

02/09/2004

O mais eficiente seria criar um array de componentes, não dos nomes deles. Como os componentes não são os mesmos, apenas os nomes, deve ser usado herança nos formulários(se possível), ou então cada formulário implementa uma interface que provê como propriedades os componentes.

Uma solução mais fácil de fazer, conforme o método de procurar nomes, seria formar uma string com os nomes de todos os componentes, usando uma delimitador como ´;´ ou #0. Ex:

const
  Botoes = ´OB_Anterior;OB_Proximo;OB_Ultimo;OB_Novo;OB_Alterar;OB_Excluir;OB_Fechar;OB_Primeiro;OB_Confirma´;
var
  I: Integer;
begin
  with Frm do
    for I := 0 to ComponentCount - 1 do
      if Components[i] is TButton then
        TButton(Components[i]).Enabled := Pos(Botoes, Components[i].Name) > 0; 
end;

Isto funciona, salvo erros de digitação. Como ´;´ não pode pertencer a um nome de componente, a função Pos pode ser usada.

Outra maneira seria usar a Tag dos controles.

Mas acho que o método utilizado nem importa, pq é um procedimento raro de ser executado. Como o vinicius2k disse, tvznem chegue aos milissegundos. Neste caso o que deve contar mais é a facilidade de escrever/manter do que a eficiência.


GOSTEI 0
POSTAR