Dúvida sobre eventos em runtime
Bom dia, estou criando ToolButtons em runtime para organizar as janelas abertas no meu programa. Toda vez que eu clicar no ToolButton a janela que corresponder a ele terá de ser mostrada. O problema é que eu não consigo atribuir essa função ao OnClick do ToolButton no código que uso para cria-lo e o evento OnClick da ToolBar "pai" só é ativado quando você clica nela, não nos seus filhos. Gostaria de uma alternativa para isso.
Júnior Garcia
Curtidas 0
Respostas
Pjrm1470
19/12/2012
Se há um procedimento exato para cada tipo de "botão" (toolButton) que você cria em run-time... então não vejo problema.
transforme esses procedimentos no escopo do TNotifyEvent (TNotifyEvent = procedure(Sender: TObject) of object;), ou seja:
procedimento do Botao01:
com um case (ou if) indo para o botão desejado, basta atribuir o OnClick:
E quando clicar nele o codigo será executado.
Não sei como está seu codigo, então não posso dizer ao certo como fazer ou como instruílo das maneiras que pode-se fazer.
Espero que ajude.
transforme esses procedimentos no escopo do TNotifyEvent (TNotifyEvent = procedure(Sender: TObject) of object;), ou seja:
procedimento do Botao01:
procedure CodeToolButton01(Sender: TObject);
begin
{ seu codigo }
end;com um case (ou if) indo para o botão desejado, basta atribuir o OnClick:
SeuToolButton.OnClick := CodeToolButton01;
E quando clicar nele o codigo será executado.
Não sei como está seu codigo, então não posso dizer ao certo como fazer ou como instruílo das maneiras que pode-se fazer.
Espero que ajude.
GOSTEI 0
Júnior Garcia
19/12/2012
eae cara. Mais detalhes aí pra vc entender melhor: Tenho uma unit chamada NavigationUtils onde faço tarefas relacionadas a navegação, como por exemplo, a criação desse botão em Runtime, a procedure é a seguinte para criá-lo:
Eu até tentei fazer isso que você disse, porém me retornava o erro: Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'.
procedure addFormBtn(formReference: TForm; toolbar: TToolBar);
var
btnCaption: String;
toolBtn: TToolButton;
lastBtnIndex: Integer;
begin
//Guarda o mesmo caption do formulário de referência
btnCaption := formReference.Caption;
//Cria um novo TToolButton
toolBtn := TToolButton.Create(formReference);
toolBtn.Caption := btnCaption;
//Armazena o índice do último botão
lastBtnIndex := Pred(toolbar.ButtonCount);
{Verifica se o último índice é maior que -1 (significa que existem botões)}
if lastBtnIndex > -1 then
toolBtn.Left := toolbar.Buttons[lastBtnIndex].Left +
toolbar.Buttons[lastBtnIndex].Width
else
toolBtn.Left := 0;
toolBtn.Parent := toolbar;
end;
Eu até tentei fazer isso que você disse, porém me retornava o erro: Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'.
GOSTEI 0
Pjrm1470
19/12/2012
Se não for pedir muito... posta o codigo que você fez que deu o erro. junto a procedure do evento que ele deve executar quando fizer o click do botão.
Assim da pra te dizer no que errou ou o que pode ser feito para melhorar (se quiser, rs).
Abraço.
Assim da pra te dizer no que errou ou o que pode ser feito para melhorar (se quiser, rs).
Abraço.
GOSTEI 0
Júnior Garcia
19/12/2012
na hora cara, taí o código de toda a unit:
unit NavigationUtils;
interface
uses
ComCtrls,
Forms,
Classes,
Controls;
procedure addFormBtn(formReference: TForm; toolbar: TToolBar);
procedure openFormByToolButton(Sender: TObject);
implementation
procedure addFormBtn(formReference: TForm; toolbar: TToolBar);
var
btnCaption: String;
toolBtn: TToolButton;
lastBtnIndex: Integer;
begin
//Guarda o mesmo caption do formulário de referência
btnCaption := formReference.Caption;
//Cria um novo TToolButton
toolBtn := TToolButton.Create(formReference);
toolBtn.Caption := btnCaption;
//Atribuo o evento OnClick
toolBtn.OnClick := openFormByToolButton(formReference);
//Armazena o índice do último botão
lastBtnIndex := Pred(toolbar.ButtonCount);
{Verifica se o último índice é maior que -1 (significa que existem botões)}
if lastBtnIndex > -1 then
toolBtn.Left := toolbar.Buttons[lastBtnIndex].Left +
toolbar.Buttons[lastBtnIndex].Width
else
toolBtn.Left := 0;
toolBtn.Parent := toolbar;
end;
procedure openFormByToolButton(Sender: TObject);
begin
with Sender as TForm do
begin
Show;
BringToFront;
end;
end;
end.
GOSTEI 0
Pjrm1470
19/12/2012
ok... vejamos...
No caso:
Utilize o seu ToolBar como o owner do botão. Apenas objetos já na memoria devem ser usados no create. Caso contrario utilize "nil"
Não sei como é o create do TToolButton, pois não estou com o delphi aqui para averiguar, mas por via de dúvidas... devida o "Parent" do seu toolButton com o toolbar (o pai dele será o toolbar, assim ele será automaticamente posicionado no toolbar)
Em vez de:
use:
Obs.: Você está definindo o evento e não fazendo a chamada dele. O compilador precisa entender que a estrutura do evento tem de ser a mesma para ser aceita. Quando o botão é clicado, o Sender já terá o TToolButton como o sender, pois quem está chamando o evento é o botão.
E por último,
Não faça Cast diretamente. É perigoso e pode vir a causar access violation se o sender não for do tipo espero. Verifique com um IF antes. Sempre tenha esse costume, pois evita muito erros indesejáveis:
Utilize uma variavel no evento do botão para chamar a tela. não sei quantas telas tem, mas cada evento pode fazer uma chamada para a respectiva variável.
Espero que ajude.
qualquer coisa so perguntar.
No caso:
toolBtn := TToolButton.Create(formReference);
Utilize o seu ToolBar como o owner do botão. Apenas objetos já na memoria devem ser usados no create. Caso contrario utilize "nil"
if assigned(toolbar) then toolBtn := TToolButton.Create(toolbar) else toolBtn := TToolButton.Create(nil);
Não sei como é o create do TToolButton, pois não estou com o delphi aqui para averiguar, mas por via de dúvidas... devida o "Parent" do seu toolButton com o toolbar (o pai dele será o toolbar, assim ele será automaticamente posicionado no toolbar)
toolBtn.Parent := toolbar;
Em vez de:
toolBtn.OnClick := openFormByToolButton(formReference);
use:
toolBtn.OnClick := openFormByToolButton;
Obs.: Você está definindo o evento e não fazendo a chamada dele. O compilador precisa entender que a estrutura do evento tem de ser a mesma para ser aceita. Quando o botão é clicado, o Sender já terá o TToolButton como o sender, pois quem está chamando o evento é o botão.
E por último,
with Sender as TForm do
Não faça Cast diretamente. É perigoso e pode vir a causar access violation se o sender não for do tipo espero. Verifique com um IF antes. Sempre tenha esse costume, pois evita muito erros indesejáveis:
if (Sender is TForm) then
Utilize uma variavel no evento do botão para chamar a tela. não sei quantas telas tem, mas cada evento pode fazer uma chamada para a respectiva variável.
Espero que ajude.
qualquer coisa so perguntar.
GOSTEI 0
Júnior Garcia
19/12/2012
Já adaptei todo o código, mas na linha:
ele mostra o erro Incompatible types: 'method pointer and regular procedure'
toolBtn.OnClick := openFormByToolButton;
ele mostra o erro Incompatible types: 'method pointer and regular procedure'
GOSTEI 0
Pjrm1470
19/12/2012
Pelo fato do TNotifyEvent ser uma procedure of Object.
O proprio nome ja diz "of Object"
Seu evento precisa ser implementado em alguma classe.
Crie uma classe so de escopo para que funcione.
Faça o teste e me diga.
Não sei se dará certo... tudo requer tentativas e mudanças.
se não conseuir acessar o metodo do objeto use um "class" antes da palavra "procedure"
Tanto na interface do objeto quanto na implementação. Mas creio que apenas tento uma procedure do objeto ja resolve.
O proprio nome ja diz "of Object"
Seu evento precisa ser implementado em alguma classe.
Crie uma classe so de escopo para que funcione.
Faça o teste e me diga.
interface
{...}
TNaoSeiOQueClass = class
public
procedure OpenFormByToolButton(Sender: TObject);
end;
implementation
procedure TNaoSeiOQueClass.OpenFormByToolButton(Sender: TObject);
begin
{...}
end;Não sei se dará certo... tudo requer tentativas e mudanças.
se não conseuir acessar o metodo do objeto use um "class" antes da palavra "procedure"
class procedure .....
Tanto na interface do objeto quanto na implementação. Mas creio que apenas tento uma procedure do objeto ja resolve.
GOSTEI 0