GARANTIR DESCONTO

Fórum Foco no edit #366073

11/11/2008

0

Boa tarde.

Estava procurando na internet como desenvolver um componente e acabei neste link:

[url]http://www.delphi.eti.br/ver_artigo.php?id=23[/url]

Bem interessante e explicativo. Consegui chegar ao propósito da materia.
Porém encontrei um pequeno problema.

Criei e instalei o componente. Adicionei 2 Edits na tela e no primeiro Edit no evento OnExit coloquei um simples:

   ShowMessage(´teste´);
 



o que acontece é que a mensagem é exibida e ao sair do campo a cor do edit não volta ao normal, ou seja, se executa a mensagem mata o onexit do componente.

alguem poderia me dar uma dica de como acertar isso?


Framosip

Framosip

Responder

Posts

12/11/2008

Framosip

Amigos,
Bom dia.

Utilizando o tutorial (
http://www.plugmasters.com.br/forum/lofiversion/index.php/t18177.html
) do amigo Márcio Theis, consegui implementar do modo que queria. A cor muda ao receber o foco volta ao normal ao perder o foco e o OnExit continua funcionando.

Porém estou com algumas dúvidas no código e gostaria da ajuda de vocês.

Vamos lá.

(var Msg: TMessage); message CM_ENTER;

O que seria TMessage? o que faz ´message CM_ENTER´ ?

inherited

Este comando faz com que herde as propriedados do componente que estou extendendo, é isso?

abraços


Responder

Gostei + 0

12/11/2008

Discorpio

Boa tarde Framosip.

Em primeiro lugar, TMessage é uma classe que controla as mensagens da API do Windows dentro da aplicação Delphi que você está desenvolvendo.

O sistema operacional Windows se comunica com qualquer aplicativo enviando e recebendo mensagens que são interpretadas como comandos de ação que o Sistema fará como o aplicativo se comportará

O Delphi e a sua linguagem object pascal possui algumas funções e classes que fazem parte de uma biblioteca que controla essa API (Application Program Interface).

Entretanto eu vejo uma outra solução para seu problema, visto que quando criamos um componente personalizado, devemos tomar alguns cuidados, pois ao criar esse componente personalizado, o modificamos de modo tal que o mesmo execute um efeito especial, e que foi o seu caso, modifica a cor do background do Edit quando este ganha e perde o Foco.

Ora se você desenvolveu esse componente com essa finalidade, então porque modificar novamente o comportamento do evento OnExit e OnEnter dentro da Aplicação :?:

A coisa boa disso tudo é que você pode personalizar o seu componente TEdit nos seus Eventos OnEnter e OnExit para executar esse efeito especial dentro do componente e ainda quando quiser, pode executar o seu código dentro da aplicação, ou seja, executar ambos os códigos, o código encapsulado dentro do componente e o código dentro da aplicação. Como faço isso :?:

Simples, todo evento nada mais é que um ponteiro de um método, ou seja, toda vez que voce direciona a sua execução para um procedure específica dentro da aplicação, aquela procedure será o ponteiro do seu evento, assim sendo, quando voce desviou a execução do evento OnExit dentro do código encapsulado, e o novamente desviou para outra procedure dentro da aplicação, o evento assumiu a nova posição do ponteiro que foi a nova procedure.

Só que ponteiros de métodos executa outros métodos dentro do código encapsulado do componente, ou seja, o OnExit nada mais é do que uma propriedade que ao receber o ponteiro de método selecionado dentro da aplicação este verificará se o ponteiro não está nulo, e dentro desse método ´DoExit´ que esta verificação é feita, se o ponteiro não estiver nulo, então DoExit executa o outro método o qual lhe foi apontado.

Então dentro do componente TEditPersonalizado, ao invés de direcionar o evento OnExit para uma procedure específica dentro dele mesmo, você apenas reescreva o método DoExit, da seguinte maneira:

  type
     TEditPersonalizado = class(TEdit)
      private
           OnEnterColor: TColor;
           OnExitColor: TColor;
      protected
           procedure DoEnter; dynamic; override;
           procedure DoExit; dynamic; override;
      public
           constructor Create(Aowner: TComponent); override;
      published
           property ColorOnEnter: TColor read OnEnterColor write OnEnterColor
           property ColorOnExit: TColor read OnExitColor write OnExitColor
      end;
procedure Register;

implementation

procedure Register;
begin
  RegisterComponents(´Standard´, [TEditPersonalizado]);
end;

constructor TEditPersonalizado.Create(Aowner: TComponent);
begin
  inherited Create(Aowner);
  OnEnterColor := clYellow;
  OnExitColor := clWhite;
end;

procedure TEditPersonalizado.DoEnter;
begin
  Color := OnEnterColor;
  inherited DoEnter;
end;

procedure TEditPersonalizado.DoExit;
  Color := OnExitColor;
  inherited DoExit;
end;

end;



Como voce pode perceber, todo o código de seu componente personalizado ficou mais enxuto e lhe permitirá assim executar o código encapsulado dentro do componente, mesmo que este não seja configurado lá na aplicação, teste e veja se não dá certo.


Responder

Gostei + 0

12/11/2008

Framosip

Discorpio,
Boa noite.

Realmente achei a solução que você postou mais clara.
Porém resultou alguns erro.

vamos lá:

  [Warning] EditFcdEnt.pas(14): Method ´DoEnter´ hides virtual method of base type ´TWinControl´
  [Error] EditFcdEnt.pas(14): Field definition not allowed after methods or properties
  [Error] EditFcdEnt.pas(15): Unknown directive: ´DoExit´
  [Error] EditFcdEnt.pas(15): ´,´ or ´:´ expected but ´;´ found
  [Error] EditFcdEnt.pas(17): ´,´ or ´:´ expected but ´CONSTRUCTOR´ found
  [Error] EditFcdEnt.pas(20): ´;´ expected but ´PROPERTY´ found
  [Error] EditFcdEnt.pas(20): Published field ´ColorOnExit´ not a class nor interface type
  [Error] EditFcdEnt.pas(20): ´,´ or ´:´ expected but identifier ´write´ found
  [Error] EditFcdEnt.pas(21): ´,´ or ´:´ expected but ´END´ found
  [Error] EditFcdEnt.pas(44): Undeclared identifier: ´DoExit´
  [Error] EditFcdEnt.pas(45): Unknown directive: ´Color´
  [Error] EditFcdEnt.pas(49): ´.´ expected but ´;´ found
  [Hint] EditFcdEnt.pas(12): Private symbol ´OnExitColor´ declared but never used
  [Fatal Error] FRamos.dpk(35): Could not compile used unit ´c:\arquivos de programas\borland\delphi7\Lib\EditFcdEnt.pas´


se você pudesse me ajudar a resolve-los! Agradeceria...

abraços e obrigado pela atenção!


Responder

Gostei + 0

12/11/2008

Discorpio

Boa noite Framosip.

Realmente cometi um erro na declaração dos métodos DoEnter e DoExit

  Errado
  ....
  protected
           procedure DoEnter; dynamic; override;
           procedure DoExit; dynamic; override;
  public
  .....

  Certo
  ....
  protected
           procedure DoEnter; override;
           procedure DoExit; override;
  public
  .....


Eles são métodos Virtuais e não dinâmicos, basta então somente sobrescrevê-los com a cláusula override.

Outra coisa, vamos mudar o nome das variáveis de OnEnterColor para EnterColor e OnExitColor para ExitColor, o seu código ficaria assim:

  
  type
     TEditPersonalizado = class(TEdit)
      private
           EnterColor: TColor;
           ExitColor: TColor;
      protected
           procedure DoEnter; override;
           procedure DoExit; override;
      public
           constructor Create(Aowner: TComponent); override;
      published
           property ColorOnEnter: TColor read EnterColor write EnterColor
           property ColorOnExit: TColor read ExitColor write ExitColor
      end;

  procedure Register;

  implementation

  procedure Register;
  begin
    RegisterComponents(´Standard´, [TEditPersonalizado]);
  end;

  constructor TEditPersonalizado.Create(Aowner: TComponent);
  begin
    inherited Create(Aowner);
    EnterColor := clYellow;
    ExitColor := clWhite;
  end;

  procedure TEditPersonalizado.DoEnter;
  begin
    Color := OnEnterColor;
    inherited DoEnter;
  end;

  procedure TEditPersonalizado.DoExit;
    Color := OnExitColor;
    inherited DoExit;
  end;

  end;



Responder

Gostei + 0

13/11/2008

Framosip

Discorpio,
Bom dia.

Alguns pequenos acertos provavelmente por erro de digitação e funcionou legal.

Porém eu tenho uma dúvida.

Se eu quisesse fazer algo para o evento onKeyPress deste edit? Seria a mesma coisa? A idéia é fazer com que este edit além de mudar a cor , ao pressionar Enter passe para o próximo campo.

Tentei algo como:

procedure DoKeypress; override;


Mas retornou o erro:
[Error] EditFcdEnt.pas(16): Cannot override a static method


Então tentei sem o override;
procedure DoKeypress;


Ai retornou de erro:
[Error] EditFcdEnt.pas(54): Not enough actual parameters


è possivel fazer isso que estou pretendendo?

abraços!


Responder

Gostei + 0

13/11/2008

Framosip

Bom....

rs..vamos lá!

Pesquisando na internet mudei algumas coisas no onKeyPress e funcionou.

Fiz assim

procedure Keypress(var Key: Char); override;


Mas fiquei com uma dúvida enorme. Por que nos eventos Enter e Exit usamos na frente o ´Do´ e no Kreypress se colocar o ´Do´ da erro?

abraços!


Responder

Gostei + 0

13/11/2008

Discorpio

Boa tarde Framosip.

Quando queremos descobrir quais os métodos que estão declarados na classe ancestral de um componente que queremos personalizar, basta digitar dentro de um método qualquer já definido, uma letra e depois pressionar Ctrl + barra de espaço, que aparecerá todos os métodos que comecem com a letra digitado, ou digitar o nome da classe que no caso é TEditPersonalizado seguido de um ponto e aparecerá todos os métodos declarados em Protected, Public e Published, somente em Private é que não aparecerá.

Ao fazer isto, descobri que existe o método procedure KeyPress(var Key: Char) que é uma procedure virtual, portanto você deve reescrevê-lo com Override, e também tem o método function DoKeyPress(var Message: TWMKey): boolean, que é uma função que retorna valor booleano. Esta função deve capturar justamente a tecla que foi digitada através da API, verificando automaticamente se foi digitado alguma tecla, e passa para o método KeyPress a tecla digitado.

Outra coisa, a cláusula Override (Sobrescrita) só é utilizada para reescrever métodos (Procedure e Function) que sejam declarados na classe ancestral como virtuais ou dinâmicos. Métodos estáticos não precisam ser reescritos com Override.

Eu recomendo que voce reescreva apenas o método KeyPress, que vai atender o que você pretende fazer, assim:

   ...
   ...
   procedure KeyPress(var Key: Char); Override;
   ...
   ...



Responder

Gostei + 0

13/11/2008

Framosip

Blz...foi o que realmente fiz e funcionou legal.

Agora me tira uma duvida.

Neste ´Componente´ que vc me ajudou a criar nós extendemos o TEdit certo?

É possivel eu criar um componente que eu arraste para o meu form e ai sim os edits que estejam no form passem a funcionar como eu defini no componente(mudar cor focado e mudar de campo com enter)?


Responder

Gostei + 0

13/11/2008

Discorpio

Boa noite Fernando.

É possivel sim, e inclusive é possível até colocar esse TEdit que voce acabou de configurar instalado na palheta de componentes, de onde voce arrasta e coloca no seu form.

Como faço isso :?:

Simples, voce deve adicionar essa Unit a um pacote, lá no site do Planeta Delphi, que será o pacote de instalação do Delphi, se não me falhe a memória, o Eder explicou como se faz issosiga as instruções.

1º) Logo após ter salvo esta Unit, vá no menu File -> Close All para fechar todos os projetos abertos.

2º) No mesmo menu File -> New -> Other, selecione na palheta New e role a página até encontrar o ícone Package, selecione-o e click em OK.

3º) Vai abrir uma caixa de diálogo nominada Package - Pagage1.dpk, dentro dessa caixa vá no ícone Add e na próxima caixa de diálogo, na caixa de text Unit Filename, digite o nome da Unit do TEdit salvo, se prefirir, click no botão Browse para localizar a Unit, depois click em OK.

4º) A sua Unit vá aparecer na árvore da pasta Contains, click com o botão direito do mouse em Contains -> Options -> Aba Directories/Conditional e em todas as combos contidas dentro do groupbox Directories, digite ´C:\Arquivos de Programas\Borland\Delphi7\Lib´ e click OK.

5º) Click no ícone Compile.

6º) Click no ícone Install.

Se deu tudo certo, você verá o seu componente instalado na Aba Standard, mas como eu defini esta aba para o meu componente :?:

Simples, lá dentro da Unit na procedure register, eu posso designar a aba que quero instalar meu componente, com esse código:

procedure Register; implementation procedure Register; begin RegisterComponents([color=darkblue:1d2e63443a]´Standard´[/color:1d2e63443a], [TMeuEdit]); end;


Detalhe é que você pode escolher um nome inexistente na Aba que ele cria automaticamente uma nova aba com o nome escolhido.


Responder

Gostei + 0

14/11/2008

Framosip

Discorpio,
Bom dia.

Até ai eu consegui fazer. Rs...rs....

Eu gostaria de fazer algo diferente. Tipo um componente que eu coloca-se no meu form e fizesse com que todos os edits que estão na tela ganhassem estas funções que definimos anteriormente.

Entendeu? Na verdade não criaremos um TEditPersonalizado, criariamos um TComponent da vida que ao ser adicionado na tela daria funções personalizadas aos TEdits que lá ja existem!

abraços!


Responder

Gostei + 0

14/11/2008

Discorpio

Bom dia Fernando.

Agora entendi, e realmente existe não só uma, mais duas outras opções em que você não precise nem construir o componente. Vamos a elas.

1º) Toda aplicação contém um objeto oculto que controla toda ela, chamado Application. Este objeto também contém os seus eventos e um deles controla as mensagens da API recebidas do Windows e enviadas ao Windows, que é o evento OnMessage, e você pode criar uma procedure e apontar esta procedure para o OnMessage do Application com a seguinte estrutura:

  ....
  ....
  public
     procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  end;

  var
     Form1 = TForm1;
  
  implementation

  uses DM, Login;

  {$R *.dfm}

   procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
   var Control: TWinControl;
   begin
        Control := Screen.ActiveForm.ActiveControl;
        if Msg.wParam in [0,1,9] then begin
        if ((Msg.message = 256) or (Msg.message = 513)) or (Msg.message = 517) then begin
        if Control is TEdit then TEdit(Control).Color := clWhite;
        if Control is TDBEdit then TDBEdit(Control).Color := clWhite;
        if Control is TMaskEdit then TMaskEdit(Control).Color := clWhite;
        if Control is TComboBox then TComboBox(Control).Color := clWhite;
        if Control is TDBComboBox then TDBComboBox(Control).Color := clWhite;
        if Control is TDBMemo then TDBMemo(Control).Color := clWhite;
        if Control is TDBLookupComboBox then TDBLookupComboBox(Control).Color := clWhite;
     end;
     if ((Msg.message = 257) or (Msg.message = 514)) or (Msg.message = 15) then begin
        if Control is TEdit then TEdit(Control).Color := clYellow;
        if Control is TDBEdit then TDBEdit(Control).Color := clYellow;
        if Control is TMaskEdit then TMaskEdit(Control).Color := clYellow;
        if Control is TComboBox then TComboBox(Control).Color := clYellow;
        if Control is TDBComboBox then TDBComboBox(Control).Color := clYellow;
        if Control is TDBMemo then TDBMemo(Control).Color := clYellow;
        if Control is TDBLookupComboBox then TDBLookupComboBox(Control).Color := clYellow;
     end;
  end;
  if Msg.message = Wm_Keydown then
     case Msg.wParam of
           Vk_Return,Vk_Down:
                Screen.ActiveForm.Perform(WM_NextDlgCtl,0,0);
          Vk_Up: 
                Screen.ActiveForm.Perform(WM_NextDlgCtl,1,0);
     end;
end;


Agora dentro do evento OnShow ou OnCreate do Form Principal onde se encontra o código acima, voce coloca esse código:

  procedure TForm1.FormShow(Sender: TObject);
  begin
      Application.OnMessage := AppMessage;
  end;


2º) A segunda opção é idêntica a primeira, só que a única diferença é que vamos utilizar um componente chamado de ApplicationEvents que se encontra na palheta Additional. Este componente controla todos os Eventos do objeto Application e consequentemente de toda a aplicação. Nesta opção, voce não precisará criar procedure, pois dentro do ApplicationEvents já possui um evento OnMessage, e dentro desse evento, voce colocará o código descrito acima em AppMessage e quanto ao código do Application.OnMessage := AppMessage você pode até descartá-lo.


Responder

Gostei + 0

14/11/2008

Framosip

Hummmm
Muito bom.

Mas me tire uma duvida, podemos criar um componente para isso? Só a base de estudos mesmo!

abraços!


Responder

Gostei + 0

15/11/2008

Discorpio

Bom dia Fernando.

Meu amigo, o componente já existe, que é justamente o ApplicationEvents, ele foi criado justamente para controlar os eventos do Objeto Application e um desses eventos é justamente o OnMessage onde voce pode configurar nele todas as mensagens oriundas do Windows, detalhe é que não só existe as mensagens de controle de Foco, mas também, as que capturam teclas, click do mouse e por ai vai. Se voce reparar, na aba de eventos do ApplicationEvents, você vai encontrar além de outros eventos, o OnException, onde nele você pode fazer o tratamento de erros que porventura ocorrer em toda a aplicação.

A primeira dica na criação do componente TEdit que te dei, realmente foi só com o escopo de aprendizagem, para que você conhecesse como funciona a execução interna de um evento de componente.

Agora realmente ficar criando cada componente só para controlar o foco de cada um, chega a ser desperdício de tempo e de recursos, eis que temos esta última opção de controlar o foco de todos os componentes da aplicação, deixando o código mais enxuto e o desempenho de sua aplicação mais dinâmica.


Responder

Gostei + 0

16/11/2008

Framosip

Sim concordo plenamente com você.

Na verdade eu queria me aprofundar um pouco mais sobre componentes por isso a ideia de criar um componente de estudo, mas não para o Edit em si que controlaria o focus e o enter. Isso com a sua ajuda consegui criar e esta funcionando perfeitamente. Eu adiciono um TEditPersonalizado que criamos e ele muda de cor quando recebe o foco e muda de campo com ao pressionar ENTER.
Eu gostaria de dar mais um passo; criar uma coisa diferente. Por exemplo:
´Criar um componente que eu arraste esse componente para a tela e o caption do meu form mude para [TESTE DE COMPONENTE]´. Mas não um TFormPersonalizado(Nem sei se existe rs...), e sim um componente. É uma coisa boba e simples mas servirá de base para que eu possa criar outras funcionalidades mais importantes.

abraços!


Responder

Gostei + 0

18/11/2008

Discorpio

Bom dia Fernando.

Bom, já que você quer se aprofundar nesse estudo, então vou te passar aqui primeiramente algumas regras sobre a criação de componentes, depois postarei como criar um componte composto, ou seja, até agora voce aprendeu criar um componente simples, oriundo de uma única classe, com os componentes compostos, você pode embutir um componente dentro de outro componente. Primeiro vamos as regras.

1º) Estude a linguagem Object Pascal do Delphi com cuidado. Os conceitos particularmente importantes são:

1.1) Herança.
1.2) Sobrescrita (sobreposição) e sobregarga de métodos
1.3) A diferença entre as seções Public e Published de uma classe.
1.4) A definição da Propriedades e Eventos.

2º) Estude a definição da VCL (Visual Component Library ou Biblioteca de Componentes Visuais) isto para Windows, para Multiplataforma, a Biblioteca é CLX (Cross Prataform ou MultiPlataforma) do Kylix para Linux e outros sistemas.

3º) Estude a hierarquia de Classes da VCL e ou da CLX e mantenha um organograma dessa hierarquia sempre a mão, para voce saber quem herda de quem, e quais são os componentes visuais e os não visuais.

4º) Siga as convenções de atribuição de nomes padrão do Delphi. Existem várias delas para componentes, essas regras torna mais fácil para outros programadores interagirem com seus componentes e estendê-los ainda mais.

5º) Matenha componentes simples, imite outros componentes e evite dependências. Essas três regras significam basicamenbte que um programador que esteja usando seus componentes deve conseguir usá-los com a mesma facilidade que os componentes previamente instalados do Delphi. Use nomes de propriedades, métodos e eventos similares, quando possível. Se os usuários não precisarem aprender regras complexas sobre o uso de seu componente, (isto é, se as dependências entre os métodos ou propriedades forem limitadas) e puderem simplesmente acessar propriedades com nomes significativos, eles ficarão contentes.

6º) Use exceções. Quando algo der errado (Lei de Murphy), o componente deve lançar uma exceção. Quando estiver alocando recursos de qualquer tipo, você deverá protegê-los com blocos try/finally e chamdas a destrutor apropriados, por esta razão, sempre é bom sobrescrever os métodos construtor e também o destrutor de um componente.

7º) Esteja pronto para escrever código real e esqueça-se dos aspectos visuais do Delphi por enquanto. Escrever componentes geralmente significa escrever código sem suporte visual (embora o complemento de classes possa acelerar muito a codificação de classes simples). A exceção a esse regra é que você pode usar quadros (frames) para escrever componentes visualmente.

Bom, por enquanto é só nessa postagem.

Vou deixar você copiar isso ai, e depois vou postar aqui como construir um componente composto, ou seja, um componente TLabel com um componente TTimer embutido.


Responder

Gostei + 0

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

Aceitar