Ir para conteúdo
Fórum Script Brasil
  • 0

Form Sempre Visível


Paulo Nobre

Pergunta

Existiria algum motivo para que a propriedade formstyle de um form não funcionasse em tempo de execução para fsStayOnTop.

Digo isso pois estou tendo problema com ela.

Clicando num botão chamo esta propriedade, mas nada acontece.

Tentei o código abaixo que achei na internet, mas também não adiantou.

with Form1 do

SetWindowPos(Handle,

HWND_TOPMOST,

Left,

Top,

Width,

Height,

SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);

O que poderia estar acontecendo?

Link para o comentário
Compartilhar em outros sites

21 respostass a esta questão

Posts Recomendados

  • 0

Também funcionou aqui com outros programas e forms.

Só neste caso que por um acaso é o do post-it está dando problema.

Será que pode ter alguma coisa a ver com o fato de ele estar vinculado a um trayicon, ou seja,

ele é um form criado depois do principal. No oncreat é lida uma chave do registro que estando escrita como sempre visível = sim, então aciona Form1.FormStyle:=FsStayOnTop;

Acho que vou ter que dar uma fuçada profunda.

Valeu, Thales.

Link para o comentário
Compartilhar em outros sites

  • 0

Então é esse form sem caption que não quer ficar em cima? Nesse caso eu não sei oque pode estar acontecendo. Eu teria que ver o projeto para pesquisar. Talvez algum outro colega possa ajudar.

Link para o comentário
Compartilhar em outros sites

  • 0

Com certeza. Eu estava achando que ele não estava ficando em cima de um form do mesmo programa, aí seria errado. Mas você ainda pode fazer uma gambiarra: Coloque um timer com intervalo 10 no form ->

procedure Form1.Timer1Timer(sender : TObject);
begin
  if (getforegroundwindow <> Form1.handle) then setforegroundwindow(form1.handle);
end;
-- O que eu observei aqui é que quando é o form principal da aplicação e está fsStayOnTop ele fica em cima de qualquer janela de qualquer aplicação, mas quando não é o form principal ele só fica em cima das janelas da mesma aplicação. Bom, eu não sei se funcionaria mas tente transformar esse form no principal ->
Application.mainform:=Form2;

Desculpe é ReadOnly property, esqueça. :D

Então você deve tentar colocar a criação desse form primeiro doque os outros no Project->View Source, oque o tornará o form principal, então você vai ter que controlar a abertura do form que deveria ser principal e ocultar o primeiro.

Link para o comentário
Compartilhar em outros sites

  • 0

Paulo acho que achei a solução para o seu problema no site Experts.

você coloca o FormStyle do form desejado para fsStayOnTop.

Tire esse form da lista de forms auto criáveis do projeto. Vamos cria-lo na mão.

no evento OnShow do form desejado coloque->

procedure TForm4.FormShow(Sender: TObject);
begin
 SetWindowPos(self.Handle,
               HWND_TOPMOST,
               0, 0, 0, 0,
               SWP_NOACTIVATE+SWP_NOMOVE+SWP_NOSIZE);

end;
E no OnClose ->
procedure TForm4.FormClose(Sender : TObject; var Action : TCloseAction);
begin
  Action:=caFree;  
end;
e para chamar o form tem que se usar ShowModal ->
procedure TForm3.Button1Click(Sender: TObject);
begin
  form4:=TForm4.create(nil); // o form não pode ter pai, então o parametro tem que ser nil
  form4.showmodal;
end;

isso faz com que o form principal se comporte normalmente mas o form desejado fique em cima de qualquer janela de qualquer aplicação.

Link para o comentário
Compartilhar em outros sites

  • 0

Valeu, Thales.

Vou testar hoje à noite.

Terei que adaptar, pois ficar sempre visível é uma opção do usuário.

Ou seja, o form deve iniciar sem a propriedade fsStayOnTop.

O usuário abre o form e aí tem a opção através de um mnuFicanoTopo e mnhNFicaNoTopo

de controlar isto.

Você acha que dará para fazer?

Outra coisa é o seguinte: o usuário tem opção de retirar o form da memória.

Neste caso basta fazer form4.free?

Link para o comentário
Compartilhar em outros sites

  • 0

Não vejo problemas em criar o Form com Owner sendo que o pai não é o Owner e sim o Parent.

Provavelmente ele não fica na frente de todos os Forms por causa do SWP_NOACTIVATE.

Tente fazer:

SetWindowPos(Form1.Handle, Hwnd_TopMost, 0, 0, 0, 0, Swp_NoSize + Swp_NoMove);
E para deixá-lo normal:
SetWindowPos(Form1.Handle, Hwnd_NoTopMost, 0, 0, 0, 0, Swp_NoSize + Swp_NoMove);

Link para o comentário
Compartilhar em outros sites

  • 0

Daquela maneira ele já está ficando em cima de todas as janelas. Nesse caso o SWP_NOACTIVATE não influeciou em nada. Em ambos os casos tem que usar ShowModal senão não funciona.

Respondendo a pergunta do Paulo, é possível colocar um menu para controlar se o form fica em cima ou não, deve-se deixar a propriedade FormStyle sempre fsStayOnTop e usar os 2 comando citados pelo sc3.

só que esse menu deverá estar no mesmo form já que tem que se usar ShowModal. Talvez um PopUpMenu.

Link para o comentário
Compartilhar em outros sites

  • 0

Infelizmente nenhuma das dicas funcionou comigo.

Estou fazendo

frmLembrete:=TfrmLembrete.create(nil);

frmLembrete.showmodal;

Dá acesso de violação como erro.

O form está sendo chamado a partir de um mnu que está no form principal, via tray.

Link para o comentário
Compartilhar em outros sites

  • 0

que isso mano? tem alguma coisa errada aí. você lembrou de tirar o form da lista de forms auto-criáveis?(project->View Source) você lembrou de destruir o form quando é fechado? Dá uma conferida geral aí, isso não pode acontecer.

Tente então colocar um owner para o form->

FrmLembrete:=TFrmLembrete.create(Application);

Desiste não.

Link para o comentário
Compartilhar em outros sites

  • 0

É Thales, parece até que você está adivinhando,com sua última frase.

estou quase desistindo de implementar esta possibilidade do usuário.

Esta confusão toda esta acontecendo porque este programa é um subprograma.

Se você um programa independente, não estaria acontecendo isto.

Estou tirando ele da lista de forms auto-criáveis, sim?

Se destruir é colocar no evento OnDestroy....frmLembrete.Free, estou sim.

Hoje a noite vou dar uma olhada com mais cuidado.

Link para o comentário
Compartilhar em outros sites

  • 0

opa, destruir não é isso que você falou não, nunca se deve colocar free no OnDestroy. Destruir é colocar Action:=caFree; no evento OnClose e nunca fechar o form com hide, sempre usar close.

Link para o comentário
Compartilhar em outros sites

  • 0

Thales e s3c, obrigado pela atenção, mas vou deixar de lado esta implementação.

Como disse anteriormente está muito confuso pois este form é um dos 20 e poucos que o programa tem.

É chamado a partir de um principal, tem opções nele que são verificadas no registro a partir do oncreate do prinicipal e do oncreate dele próprio. Quando crio ele em tempo de execução acabo tendo problemas.

Depois vou fazer o programa separado e é provávê que não apresente problema.

Aprendi muito com este tópico e muitas coisas me servirão para outros programas.

Com certeza se vocês estivessem vendo o programa resolveriam isto bem rápido pela experiência que vocês tem, porém apenas imaginado o que existe nele e com poucas informações é quase impossível.

Gostaria de aproveitar o tópico para explorar uma observação feita pelo Thales anteriormente de que nunca se usa free no OnDestroy.

Havia aprendido por aí que por exemplo, ao usar reg:TRegistry, para destruí-lo o local adequado seria no OnDestroy colocando reg.free. Segundo o que o Thales mencionou ,está errado. Ou eu entendi errado e seria apenas para forms

Por que?

Nunca tive nenhum problema de erro ou violação.

Alguém poderia comentar isto , escrevendo algo se possível, como um resumo ou coisa e tal.

Valeu por mais este aprendizado.

Link para o comentário
Compartilhar em outros sites

  • 0

Ok Paulo, com certeza esse access violation deve-se a grande confusão de forms, objetos e recursos utilizados pelo seu programa. É preciso dar uma conferida geral e começar a organizar o programa seguindo a lógica convencionada.

Paulo Nobre, 29 de agosto de 2006, 10:07 PM

Gostaria de aproveitar o tópico para explorar uma observação feita pelo Thales anteriormente de que nunca se usa free no OnDestroy.

Havia aprendido por aí que por exemplo, ao usar reg:TRegistry, para destruí-lo o local adequado seria no OnDestroy colocando reg.free. Segundo o que o Thales mencionou ,está errado. Ou eu entendi errado e seria apenas para forms

Por que?

Nunca tive nenhum problema de erro ou violação.

Alguém poderia comentar isto , escrevendo algo se possível, como um resumo ou coisa e tal.

quando você disse Se destruir é colocar no evento OnDestroy....frmLembrete.Free, estou sim. não sei se entendí da maneira correta, mas eu entendí que você estava colocando frmLembrete.Free no OnDestroy do próprio form que se está destruindo, isso é errado.

No seu caso, colocar frmLembrete.Free no OnDestroy do form principal também não é o certo. Seria o certo se ele estivesse na lista de forms auto criáveis, aí ele seria criado na abertura da aplicação e destruído no fechamento da aplicação(OnDestroy do form principal). Se você criá-lo no OnClick de um botão, terá que destruí-lo quando for fechado, para que quando for aberto novamente, tenha-se que criá-lo denovo. Ou criá-lo no OnClick de um botão e não adicionar Action:=cafree; no OnClose, aí quando ele for fechado, não é liberado da memória, e quando você clicar naquele botão denovo, não poderá criá-lo novamente, somente mostrá-lo com ShowModal. Porque se voce criar outro sem liberar o anterior da memória o mesmo perderá a referencia e ficará ocupando memória atoa. Nesse caso seria melhor criá-lo no início da aplicação e usar ShowModal; e Close; para abrí-lo e fechá-lo. Lembrando que usar o método Hide num form Modal não permite que a aplicação continue, tem que ser Close.

No exemplo que sugerí, o form teria que ser criado apenas quando fosse necessário na aplicação(Ex: evento OnClick de um botão), e destruído assim que não fosse mais necessário(Aplicação continuaria rodando). Para isso o correto é colocar no evento OnClose do próprio form Action:=caFree;, e sempre usar Close; para fechá-lo. Isso garantiría que o form fosse liberado da memória.

Agora, se você colocar frmLembrete.Free no OnDestroy do próprio form, se foi isso que você quis dizer, estaria errado porque o evento OnDestroy ocorre quando é chamado o método Destroy ou Free do form, que são os métodos que liberam o form da memória. Na verdade o método Free chama o método Destroy. Portanto se for colocado frmLembrete.Free no OnDestroy do próprio form ocorrerá uma recursividade infinita podendo ocorrer um Stack Overflow ou a'te um access violation.

Não há nada de errado em colocar Reg.Free no OnDestroy de um form.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,1k
    • Posts
      651,8k
×
×
  • Criar Novo...