Jump to content
Fórum Script Brasil
  • 0

MdiChild em DLL, tecla TAB não Funciona


Renatosky

Question

Ola amigos estou com um problema com minha aplicação...

tenho um software com forms em mdi ai meu executavel ficou muito grande ai quebrei os modulos em dll, mas agora to com um problema a tecla TAB não funciona nos forms mdi filhos na dll, quando estava mo executavel funcionava agora q estao na dll, não funciona. alguém tem uma luz??

Obrigado.

Edited by Renatosky
Link to comment
Share on other sites

19 answers to this question

Recommended Posts

  • 0

tecla TAB não funciona nos forms mdi filhos

Usando a tecla Tab, o cursor vai se alternando entre os campos, sempre seguindo a ordem em que os controles foram colocados no formulário.

Propriedade TabStop.

Essa propriedade impede o acesso ao controle pela tecla Tab se estiver desligada. Isso acontece porqueTabStop determina se o controle deve ou não atender à ordem de tabulação. Mas é importante ressaltar que TabStop não evita que o usuário acesse o controle usando o mouse. Os valores possíveis para TabStop sãoTrue (TabStop ligada) ou False (TabStop desligada).

Evento KeyPress.

Sempre que é pressionada uma tecla, estando o foco sobre um controle, ocorre o evento KeyPress. Associada a ele está a variável KeyAscii, que é carregada com o código ASCII da tecla pressionada. Dessa maneira podemos identificar quando o usuário usa uma tecla qualquer, e, se for o caso, escrever um código a ser executado quando essa tecla for utilizada.

experimente fazer um teste da tecla Tab no evento KeyPress no form filho, para ver se esta funcionando.

abraço

Link to comment
Share on other sites

  • 0
Fiz tudo isso q você me falou mas ainda não funcionou...

continua nulo a tecla TAB nas minhas dll..

acho que para tentar ajudá-lo vale o que o Jhonas sugeriu.

Mas ainda perguntaria:

- Por acaso no form principal, da sua aplicação, você habilitou a propriedade KeyPreview?

- como ficou estruturada sua aplicação em termos de tela. O que está no programa e o que está em DLL? (acho que é mais ou menos ao que o Jhonas se refere)

Abraços

Link to comment
Share on other sites

  • 0

Ola Micheus,

meu form esta o msmo de quando estava na executavel eu apenas desbembrei ele e coloquei em dll, desde então a tecla tab na funciona, a função key preveiw esta ativada, estou usando o segunte codigo no envendo onkeypress do form:

if key=#13 then

begin

key:=#0;

Perform(Wm_NextDlgCtl,0,0);

end;

é normal q eu sempre usei p/ a tecla enter fazer a mesma função da tecla tab mas so isso q funciona p/ ir mudando de edit já o tab fica nulo, já tentei de tudo...

v o q você pod fazer..

obrigado..

abração.

Link to comment
Share on other sites

  • 0

como ficou estruturada sua aplicação em termos de tela. O que está no programa e o que está em DLL? (acho que é mais ou menos ao que o Jhonas se refere)

eu apenas desbembrei ele e coloquei em dll

voce não resposdeu nem a minha pergunta e nem a do Micheus...

sem voce colocar o codigo que esta na dll fica dificil ajudar... de qualquer forma voce pode tentar outras maneiras

de controlar a tecla TAB:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then
if not (ActiveControl is TDBGrid) then
begin
Key := #0;
Perform(WM_NEXTDLGCTL, 0, 0);
end
else if (ActiveControl is TDBGrid) then
with TDBGrid(ActiveControl) do
if selectedindex < (fieldcount -1) then
selectedindex := selectedindex +1
else
selectedindex := 0;
end;
Ou então, pode-se tentar o seguinte método: Utilize o evento onkeydown do componente e insira o seguinte comando: if Key = VK_RETURN then Perform(Wm_NextDlgCtl,0,0); este comando testa a tecla pressionada, se ela for um enter, manda o foco para o componente posterior. if Key = VK_TAB then Perform(Wm_NextDlgCtl,0,0); este comando testa a tecla pressionada, se ela for um tab, manda o foco para o componente posterior. .................................................................................. Dica de Márcio Souza Enter funcionando como Tab em toda a aplicação
Uses
  Grids
procedure TfrmPri.MudarComEnter(var Msg: TMsg; var Handled: Boolean);
begin
  If not ((Screen.ActiveControl is TCustomMemo) or
  (Screen.ActiveControl is TCustomGrid) or
  (Screen.ActiveForm.ClassName = 'TMessageForm')) then
  begin
  If Msg.message = WM_KEYDOWN then
  begin
  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;
  end;
end;
no evento OnCreate o Form Principal digite a seguinte linha Application.OnMessage := MudarComEnter; .......................................................... Eu uso desta maneira:
if Key = #9 then
            if not (ActiveControl is TDBGrid) then
               begin
                  Key := #0;
                  Perform(WM_NEXTDLGCTL, 0, 0);
               end
            else if (ActiveControl is TDBGrid) then
               with TDBGrid(ActiveControl) do
               if selectedindex <= (fieldcount -1 ) then
                  begin
                     if selectedindex = 2 then
                         begin
                              showmessage('Coluna 3 do DbGrid selecionada');                              
                         end;

                  end
                else
                  selectedindex := 0;

abraço

Link to comment
Share on other sites

  • 0
a função key preveiw esta ativada, estou usando o segunte codigo no envendo onkeypress do form:

if key=#13 then
   begin
    key:=#0;
    Perform(Wm_NextDlgCtl,0,0);
  end;
é normal q eu sempre usei p/ a tecla enter fazer a mesma função da tecla tab mas so isso q funciona p/ ir mudando de edit já o tab fica nulo
você pode tentar as opções que o Jhonas postou, mas antes, só para teste, experimente uma alteração bem simples no seu código atual, já que está funcionando com o ENTER - inclusa o TAB no seu teste:
if key in [#9, #13] then
   begin
    key:=#0;
    Perform(Wm_NextDlgCtl,0,0);
  end;

Veja se isto irá funcionar.

Abraços

Link to comment
Share on other sites

  • 0

Ola amigos,

fiz uns testes e verifiquei ond esta o problema mas ainda não consegui resolver, eu fui na propriedade FormStyle e mudei ela p/: fsNormal, fsMDIForm e fsStayOnTop, nesses tres estilos a tecla tab funciona normalmente, mas quando eu mudo para o estilo fsMDIChild, q é o q eu preciso, a tecla tab praticamente para de funcionar, fica nula, usei todos os codigos q vocês me passaram anteriormente, mas não obtive sucesso. Se vocês tem uma ideia de q possa ser..

Obrigado.

Link to comment
Share on other sites

  • 0

Ola amigo tentei mais essa dica e não funcionou...

sera q é algum bug do delphi??

micheus você podia me passar o seu e-mail p/ eu te enviar o projeto

ai você vai avaliar melhor o q pode estar acontecendo..

obrigado..

Edited by Renatosky
Link to comment
Share on other sites

  • 0

O comando q eu usu p/ chamar a dll é o seguinte:

procedure TPrincipal.ChegadaMateriaPrima1Click(Sender: TObject);
var
  vProc : TOpenSRF002;
begin
  vDll := LoadLibrary('SRF002.dll');
  if vDLL <> 0 then begin
    @vProc := GetProcAddress(vDll, 'ShowSRF002');
    if @vProc <> nil then begin
      vProc( Pointer(Application));
    end;
  end;
end;

ai esta uma tela do sistema:

telamdichild.jpg

se alguém quiser ver o fonte do projeto me mande um e-mail: renatosky@gmail.com

obrigado

Edited by Micheus
Incluída tag's CODE para melhorar a visualização, bem como a tag IMG para mostrar a imagem. Utilize a identação também ;)
Link to comment
Share on other sites

  • 0

Ola amigos, estou aqui de novo com o mesmo problema mas agora vou mostrar detalhadamente como esta meu projeto e colocarei o link p/ quem quiser baixar e testar..

Na minha dll os codigos do meu form é o seguinte:

unit UTESTE;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TTESTE = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  procedure ShowSRF005( vApplicaton : Pointer);

var
  TESTE: TTESTE;
  vOldApplication : TApplication;
  OldScreen: TScreen;

implementation

{$R *.dfm}

procedure ShowSRF005( vApplicaton : Pointer);
begin
Application := TApplication(vApplicaton);
Application.CreateForm(TTESTE, TESTE);
TESTE.Show;
end;

procedure TTESTE.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
Self   := nil;
end;

Initialization
vOldApplication := Application;

Finalization
Application := vOldApplication;

end.
e
library SRF005;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Classes,
  UTESTE in 'UTESTE.pas' {TESTE};

{$R *.res}

Exports
  ShowSRF005;
end.
No meu projeto .exe eu chamo meu form dll com esse comando:
procedure TPrincipal.RMA1Click(Sender: TObject);
var
  vProc : TOpenSRF005;
begin
  vDll := LoadLibrary('SRF005.dll');
  if vDLL <> 0 then begin
    @vProc := GetProcAddress(vDll, 'ShowSRF005');
    if @vProc <> nil then begin
      vProc( Pointer(Application));
    end;
  end;
end;

Link do projeto: http://www.4shared.com/dir/5664434/b317bbc8/sharing.html

Se alguém quiser o projeto me passe o e-mail q eu envio os codigos para fazer testes e tentar-mos resolver esse grande problema..

Obrigado.

Edited by Renatosky
Incluída tag's CODE para melhorar a visualização. Utilize a identação também ;)
Link to comment
Share on other sites

  • 0
Por favor amigos e ajudem... precisando dessa solução...
Renatosky, este último post poderia ser considerado um UP - e eles são proibidos pelas regras do forum. ;)

Este parece não será um "problema" muito fácil de resolver. Se você colocar um TEdit no seu form principal, observará ao abrir um de seus forms Child, que ao teclar TAB em um campo deste form, o foco será movido para o Edit colocado no form principal. E isto ocorre independente de questões como uso do KeyPreview.

Abraços

Link to comment
Share on other sites

  • 0

Oi Renato ... dei uma olhada no seu projeto, percebi que atraves da dll voce cria a chamada para o form filho... percebi tambem que voce consegue criar o form filho mas não consegue mover o foco de um campo para outro nem com o enter e nem com o tab.

voce precisaria usar a unit QForm para que isto pudesse ocorrer, entretando quando voce cria o ponteiro para a aplicação que cria o form filho, voce mata este processo, e o cursor só move se voce clicar com o mouse.

se voce mudar a propriedade formstyle para fsNormal no formulario TESTE voce vai perceber que o enter e o tab funcionam normalmente, no entanto, o form filho sobrepoe o form Principal.

Solução: não criar form filhos atraves de dll, ou procurar um maneira da unit Qform não entrar em conflito com a dll gerando exceção. (não pode criar objeto de aplicação em um objeto compartilhado ou biblioteca);

abraço

Link to comment
Share on other sites

  • 0
Axo q agora então o problema já não é mais nosso e sim da borland..

Renatosky, nestes dias acompanhando este tópico, havia lembrado de que o uso de BPL's poderia ser a possível solução, já que trata-se de um tipo especial de DLL criada pela Borland. Se você observar, as BPL's ao serem instaladas (no caso dos componentes visuais) interagem com a aplicação Delphi, sem qualquer efeito colateral.

Pensando nisto, estava a procura de um artigo na Developer Network (Code Gear). O link está neste post da sessão links é este:Dynamic packages in Delphi .

Então, tentei fazer uns testes antes de posta-lhe algo. O resultado foi positivo - tudo normal com os forms filhos. :D

Mas, não consegui implementar o código utilizando a função GetClass como é sugerido lá, pois por algum motivo ela retorna NIL indicando que a classe da janela não tenha sido registrada na inicialização da BPL. Entretanto, tentei utilizar a função FindClass e, com ela, obtive a classe registrada (as duas basicamente fazem a mesma coisa). :blink:

No meu exemplo, o form Child ficou com esta estrutura mínima:

unit uChild1;
...
var
  FrmChild1: TFrmChild1;

implementation
{$R *.dfm}

procedure TFrmChild1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

initialization
  RegisterClass(TFrmChild1);

finalization
  UnregisterClass(TFrmChild1);

end.
O form MDI principal, ficou assim:
unit uMainForm;
interface
uses
  Windows, Messages, SysUtils, Classes, ... StdCtrls;

type
  TMainForm = class(TForm)
    ...
  private
    PckChild1 :HModule;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation
{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  PckChild1 := 0;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  if PckChild1 > 0 then
    UnloadPackage(PckChild1);
end;

procedure TMainForm.MDIChild11Click(Sender: TObject);
var
  AClass: TPersistentClass;
begin
  if PckChild1 = 0 then
    PckChild1 := LoadPackage('MDIChild02.bpl');

  if PckChild1 > 0 then
  begin
    AClass := FindClass('TFrmChild1');
   // este teste a seguir, nem seria necessário porque a 
   // função FindClass gera uma exceção no caso de não 
   // encontrar a classe que estamos procurando.
   // Ele é válido no caso de uso do GetClass
    if AClass <> nil then
      TComponentClass(AClass).Create(Application)
    else
      ShowMessage('Classe não foi encontrada!');
  end else
    ShowMessage('Módulo não foi encontrado!');
end;

end.

Por fim, nas opções do projeto, como indica o artigo, deve-se habilitar na Packages, groupbox Runtime packages a opção Build with runtime packages e selecionar os pacotes a serem utilizados em run-time, no meu caso, foi apenas MDIChild02.

Como as janelas filhas não são mostradas "Modais", optei por carregar a BPL no momento de criá-la, mas a descarga da BPL só poderá ocorrer ao sair do program ou quando tiver certeza de que fechou a janela filha. No exemplo isto fica bem claro, porque a janela utilizada não é MDIChild e ela é apresentada com ShoModal, de modo que ao ser fechada a BPL pode ser descarregada.

Aparentement não houveram efeitos colaterais. É questão de implementar e testar mais.

Abraços

Edited by Micheus
Link to comment
Share on other sites

  • 0

Ressucitando o tópico... Tente fazer assim:

No evento onShow do Formulário da DLL, coloque = Componente.CreateParented(Self.Handle);

O único problema é que ele aparentemente cria o componente de volta. Se alguém souber resolver este outro problema, eu agradeço =)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Forum Statistics

    • Total Topics
      152k
    • Total Posts
      651.6k
×
×
  • Create New...