Array
(
)

Procedure comum em todos os forms

Lucianogar
   - 02 set 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
#Código


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


Lucas Silva
   - 02 set 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!


Vinicius2k
   - 02 set 2004

Colega,

Vc pode alterar sua procedure para que ela receba o form em que vc chamá-la como parametro... creio que ficaria assim:
#Código

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 :
#Código
AtivaAtalhos(Self);


Espero ter ajudado...
T+


Bruno Belchior
   - 02 set 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!


Lucianogar
   - 02 set 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


Ipc$
   - 02 set 2004


Citação:

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 :?:


Vinicius2k
   - 02 set 2004


Citação:

Citação:
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 :?:

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 ? :
#Código

for i:= 0 to (ComponentCount - 1) do begin

Vc não se esqueceu do -1 ? Lembre-se de que a contagem de índices de um Array (Components) começa de Zero, por isso é necessário o -1...

T+


Emerson
   - 02 set 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)


Ipc$
   - 02 set 2004


Citação:
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.


Emerson
   - 02 set 2004

[size=18:07c5b325e7]melhor:[/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.


Vinicius2k
   - 02 set 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 :
#Código

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+


Emerson
   - 02 set 2004


Citação:

Citação:
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.


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


Beppe
   - 02 set 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:

#Código

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.