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

Ativar Aplicação No Tray


fajo

Pergunta

16 respostass a esta questão

Posts Recomendados

  • 0
Oi pessoal,

Existe alguma forma de ativar uma aplicação que está no tray, eu só quero que ela receba o foco, ela inicia minizada no tray e eu quero que ela receba o foco, tipo setfocus que não serve pois o mainform está oculto;

Obrigado

como assim, colocar o foco na aplicação que está na tray e sem mostrar o form? Acho que não dá. O que você pretende fazer?

Link para o comentário
Compartilhar em outros sites

  • 0

Bom Micheus, como eu disse anteriormente, estou fazendo um programinha de mensagens pra rede local, a minha intenção é que ele inicie com o windows e vá direto para o Tray, até que alguém dê clique duplo, selecione um usuário pra enviar uma mensagem, o problema que eu detectei é que a rotina responsável por coletar as informações dos outros computadores da rede que tem o programa instalado para que sejam listados no listbox, só é executada quando o form é..., até meio complicado explicar, acho que quando ele é focado, tipo assim, quando eu disabilito a iniciação no tray, ou seja, quando ele é executado como outro programa a rotina é lida e a coleta das informações é feita, eu fiz um teste aqui colocando uma animação no form "AnimateWindow(Handle, 3000, AW_BLEND);", beleza, o form é aberto só que sem foco ai só é eu clicar e pronto as outras aplicações irmãs passam a vê-la, meu intuito é exatamente isso fazer com a aplicação receba o foco mesmo no tray pra ativar a rotina!!

Se quiser posso te mandar o código e o componente pra dar uma olhada

beleza

Link para o comentário
Compartilhar em outros sites

  • 0
o problema que eu detectei é que a rotina responsável por coletar as informações dos outros computadores da rede que tem o programa instalado para que sejam listados no listbox, só é executada quando o form é..., até meio complicado explicar, acho que quando ele é focado
Seria difícil colocar o código dessa rotina e de onde ela é chamada?

Nesse processo, as mensagens circulam pela rede utilizando algum componente específico tipo socket ou você implementou isto num banco de dados?

Se quiser posso te mandar o código e o componente pra dar uma olhada
Se quizer enviar, até pode, mas só vou ter um tempo livre para isto na terça a noite. Dê uma olhada na sua caixa de mensagens aqui do forum (meu e-mail)

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Não usei nenhum banco de dados e o código da rotina é esse:

procedure TfrmMain.ICQFmsgUserListChange(Sender: TObject; UserList: TStrings);

begin

lbxUser.Items := UserList; //captura todos os usuários onLine

end;

onde ICQFmsg é o nome dado ao componente TMessenger, cuja Unit é:

unit Messenger;

interface

{$LONGSTRINGS ON} // Equal {$H+}

uses

ExtCtrls, Windows, SysUtils, Classes,Dialogs;

type

TMainMessenger = Class;

TSignalThread = class(TThread)

private

FMailSlot : TMainMessenger;

protected

procedure Execute; override;

Public

Constructor Create(MailSlot : TMainMessenger);

end;

TTimerThread = class(TThread)

private

FMailSlot : TMainMessenger;

protected

procedure Execute; override;

Public

Constructor Create(MailSlot : TMainMessenger);

end;

TNELineArrival = Procedure (Sender : TObject;Origin,Time,Line : string) of Object;

TNEMemoArrival = Procedure (Sender : TObject;Origin,Time : string;MsgLines : TStrings) of Object;

TNEUserListChange = Procedure (Sender : TObject; UserList : TStrings) of Object;

TNEError = Procedure (Sender : TObject;ErrorMsg : string) of object;

TNETimer = Procedure (Sender : TObject) of object;

TMainMessenger = class(TComponent)

private

FWaitThread : TSignalThread;

FTimerThread : TTimerThread;

LocalHandle,RemoteHandle : THandle;

ActiveFlag : Boolean;

FComputer,FUser : string;

Server,FBoxName,LocalPath,RemotePath : string;

MaxMsgSize,MsgCount,NextMsgSize,MsgSize : DWORD;

MsgType,MsgTime,MsgSender,MsgText : string;

OutStrings,InStrings,UserList,MemoLines : TStringList;

NewLine : String;

FInterval : word;

FTimerActive : boolean;

FLineArrival : TNELineArrival;

FMemoArrival : TNEMemoArrival;

FUserListChange : TNEUserListChange;

FError : TNEError;

FTimer : TNETimer;

Procedure SendOutStrings(Recipient : string);

Procedure SendCommand(Recipient,Command : string);

Procedure AddUser(Name : string);

Procedure DeleteUser(Name : string);

protected

Procedure DoLineArrival(Const FMSender,FMTime,FMText : string); virtual;

Procedure DoMemoArrival(const FMSender,FMTime : string;MLines : Tstrings); virtual;

Procedure DoUserListChange(Const CompList : TStringList); virtual;

Procedure DoErrorReport(const Error : string); virtual;

public

Constructor Create(AOwner : TComponent); Override;

Destructor Destroy; override;

Procedure Activate;

Procedure DeActivate;

Procedure SetName(const NewName : TComponentName); override;

Procedure SetBoxName(NewName : string);

Procedure SetInterval(time : word);

Procedure ReadMessage;

Procedure ProcessCommand;

Procedure SendLine(Recipient,Text : string);

Procedure SendMemo(Recipient : string;Lines : TStrings);

Procedure Broadcast(text : string);

procedure DoTimer;

Property OnNewLine : TNELineArrival read FLineArrival write FLineArrival;

Property OnNewMemo : TNEMemoArrival read FMemoArrival write FMemoArrival;

Property OnUserListChange : TNEUserListChange Read FUserListChange Write FUserListChange;

Property OnError : TNEError read FError write FError;

Property OnTimer : TNETimer read FTimer write FTimer;

published

end;

TMessenger = class(TMainMessenger)

Published

Property Computer : string read FComputer;

Property User : string read FUser;

Property BoxName : string read FBoxName write SetBoxName;

Property Interval : word read FInterval write SetInterval;

Property OnNewLine;

Property OnNewMemo;

Property OnUserListChange;

Property OnError;

Property OnTimer;

end;

procedure Register;

implementation

//---------- Component Registration ------------------------------------------

procedure Register;

begin

RegisterComponents('3rdParty', [TMessenger]);

end;

//---------- Thread Procedures -----------------------------------------------

Constructor TSignalThread.Create(MailSlot : TMainMessenger);

Begin

Inherited Create(False);

Priority := tpNormal;

FMailSlot := MailSlot;

end;

Procedure TSignalThread.Execute;

Begin

While Not Terminated do

Begin

GetMailSlotInfo(FMailSlot.LocalHandle,NIL, FMailSlot.NextMsgSize,

@FMailSlot.MsgCount, NIL);

If FMailSLot.MsgCount > 0 Then

Synchronize(FMailSLot.ReadMessage);

Sleep(1);

end;

end;

Constructor TTimerThread.Create(MailSlot : TMainMessenger);

Begin

Inherited Create(False);

Priority := tpNormal;

FMailSlot := MailSlot;

end;

Procedure TTimerThread.Execute;

Begin

While Not Terminated do begin

Synchronize(FMailSLot.DoTimer);

Sleep(FMailslot.FInterval);

end;

end;

Procedure TMainMessenger.DoTimer;

begin

if assigned(FTimer) then FTimer(Self);

end;

//----------- Signaler StartUp/ShutDown -----------------------------------------

Constructor TMainMessenger.Create(AOwner : TComponent);

var

temp : array[0..255] of char;

len : DWord;//integer;

Begin

Inherited Create(AOwner);

FBoxName := 'SignalBox';

FInterval := 1000;

FWaitThread := NIL;

FTimerThread := NIL;

len := 255;

GetComputerName(temp,len);

FComputer := StrPas(temp);

len := 255;

GetUserName(temp,len);

FUser := StrPas(temp);

OutStrings := TStringList.Create;

InStrings := TStringList.Create;

UserList := TStringList.Create;

MemoLines := TStringList.Create;

end;

Destructor TMainMessenger.Destroy;

begin

if ActiveFlag = true then DeActivate;

UserList.Free;

OutStrings.Free;

InStrings.Free;

MemoLines.Free;

inherited Destroy;

end;

Procedure TMainMessenger.Activate;

var

i,j : integer;

begin

If ActiveFlag = true then begin

DoErrorReport('You tried to Activate an active TMessenger component');

exit;

end;

FWaitThread := TSignalThread.Create(Self);

if FWaitThread = nil then begin

DoErrorReport('Could not Start TMessenger Timer Thread');

exit;

end;

FTimerThread := TTimerThread.Create(Self);

Server := '.';

LocalPath := '\\' + Server + '\mailslot\' + FBoxName;

LocalHandle := CreateMailSlot(PChar(LocalPath),MaxMsgSize,0,nil);

if LocalHandle = INVALID_HANDLE_VALUE then begin

FWaitThread.Terminate;

FWaitThread := nil;

FTimerThread.Terminate;

FTimerThread := nil;

DoErrorReport('Could not Create Mail Slot');

exit;

end;

SendCommand('*','ONLINE_NOTIFY');

ActiveFlag := true;

end;

Procedure TMainMessenger.DeActivate;

begin

if ActiveFlag = false then begin

DoErrorReport('Cannot Deactivate an Inactive TMessenger Component');

exit;

end;

if FWaitThread <> nil then begin

FWaitThread.Terminate;

FWaitThread := nil;

end;

if FTimerThread <> nil then begin

FTimerThread.Terminate;

FTimerThread := nil;

end;

CloseHandle(LocalHandle);

SendCommand('*','OFFLINE_NOTIFY');

ActiveFlag := False;

end;

//-------------- Set Property Procedures --------------------------------------

Procedure TMainMessenger.SetName(const NewName: TComponentName);

Begin

Inherited SetName(NewName);

end;

Procedure TMainMessenger.SetBoxName(NewName : string);

begin

if FBoxName <> NewName then begin

FBoxName := NewName;

if ActiveFlag = true then begin

DeActivate;

Activate;

end;

end;

end;

Procedure TMainMessenger.SetInterval(Time : word);

begin

if FInterval <> Time then FInterval := Time;

end;

//------------- Message Retrieval Procedures ----------------------------------

Procedure TMainMessenger.ReadMessage;

var

i : integer;

begin

Instrings.Clear;

SetLength(NewLine,NextMsgSize);

ReadFile(LocalHandle,PChar(NewLine)^,NextMsgSize,MsgSize,nil);

Instrings.Text := NewLine;

FWaitThread.Suspend;

if Instrings.Count > 3 then begin

MsgType := Instrings[0];

MsgTime := Instrings[1];

MsgSender := Instrings[2];

MsgText := Instrings[3];

end;

if Instrings.Count > 5 then begin

MemoLines.Clear;

for i := 4 to Instrings.Count - 2 do begin

MemoLines.Add(Instrings);

end;

end;

if MsgType = 'COMMAND_MSG' then ProcessCommand;

if MsgType = 'LINE_MSG' then DoLineArrival(MsgSender,MsgTime,MsgText);

if MsgType = 'MEMO_MSG' then DoMemoArrival(MsgSender,MsgTime,MemoLines);

Instrings.Clear;

FWaitThread.Resume;

end;

Procedure TMainMessenger.ProcessCommand;

begin

if MsgSender = FComputer then exit;

if MsgText = 'ONLINE_NOTIFY' then begin

AddUser(MsgSender);

SendCommand(MsgSender,'ONLINE_RESPONSE');

end;

if MsgText = 'ONLINE_RESPONSE' then AddUser(MsgSender);

if MsgText = 'OFFLINE_NOTIFY' then DeleteUser(MsgSender);

end;

Procedure TMainMessenger.AddUser(Name : string);

var

i : Integer;

j : boolean;

begin

j := false;

if UserList.Count > 0 then begin

for i := 0 to UserList.Count - 1 do begin

if UserList = Name then j := true;

end;

end;

if j = true then exit;

UserList.Add(Name);

DoUserListChange(UserList);

end;

Procedure TMainMessenger.DeleteUser(Name : string);

var

i,Num : Integer;

j : boolean;

begin

j := false;

Num := 0;

if UserList.Count > 0 then begin

for i := 0 to UserList.Count - 1 do begin

if UserList = Name then begin

j := true;

Num := i;

end;

end;

end;

if j = false then exit;

UserList.Delete(Num);

DoUserListChange(UserList);

end;

//------------- Message Sending Procedures ------------------------------------

Procedure TMainMessenger.SendOutStrings(Recipient : string);

var

len : DWORD;

begin

if OutStrings.Count > 0 then begin

RemotePath := '\\' + Recipient + '\mailslot\' + FBoxName;

RemoteHandle := CreateFile(PChar(RemotePath),GENERIC_WRITE,FILE_SHARE_READ,

nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);

if RemoteHandle = INVALID_HANDLE_VALUE then begin

DoErrorReport('Could not Open a Remote Mail Slot');

exit;

end;

WriteFile(RemoteHandle,Pointer(Outstrings.text)^,Length(OutStrings.text),len,nil);

OutStrings.Clear;

end;

end;

Procedure TMainMessenger.SendLine(Recipient,Text : string);

begin

if Recipient = '*' then exit;

Outstrings.Add('LINE_MSG');

Outstrings.Add(TimeToStr(Time));

OutStrings.Add(FComputer);

OutStrings.Add(text);

OutStrings.Add('END_MESSAGE');

SendOutStrings(Recipient);

end;

Procedure TMainMessenger.Broadcast(text : string);

begin

Outstrings.Add('LINE_MSG');

Outstrings.Add(TimeToStr(Time));

OutStrings.Add(FComputer);

OutStrings.Add(text);

OutStrings.Add('END_MESSAGE');

SendOutStrings('*');

end;

Procedure TMainMessenger.SendMemo(Recipient : string;Lines : TStrings);

var

i : integer;

begin

if Recipient = '*' then exit;

Outstrings.Add('MEMO_MSG');

Outstrings.Add(TimeToStr(Time));

OutStrings.Add(FComputer);

OutStrings.Add('BEGIN_MEMO');

if Lines.Count > 0 then begin

for i := 0 to Lines.Count -1 do begin

OutStrings.Add(Lines);

end;

end;

OutStrings.Add('END_MESSAGE');

SendOutStrings(Recipient);

end;

Procedure TMainMessenger.SendCommand(Recipient,Command : string);

begin

Outstrings.Add('COMMAND_MSG');

Outstrings.Add(TimeToStr(Time));

OutStrings.Add(FComputer);

OutStrings.Add(Command);

OutStrings.Add('END_MESSAGE');

SendOutStrings(Recipient);

end;

//----------- Event Handler Procedures ---------------------------------------

Procedure TMainMessenger.DoLineArrival(const FMSender,FMTime,FMText : string);

begin

if Assigned(FLineArrival) then FLineArrival(Self,MsgSender,MsgTime,MsgText);

end;

Procedure TMainMessenger.DoMemoArrival(const FMSender,FMTime : string;MLines : Tstrings);

begin

if Assigned(FMemoArrival) then FMemoArrival(Self,MsgSender,MsgTime,MemoLines);

end;

Procedure TMainMessenger.DoUserListChange(Const CompList : TStringList);

begin

If Assigned(FUserListChange) Then FUserListChange(Self,CompList);

end;

Procedure TMainMessenger.DoErrorReport(const Error : string);

begin

If Assigned(FError) Then FError(Self,Error);

end;

end.

Link para o comentário
Compartilhar em outros sites

  • 0

Tem sim Micheus, as duas, tá ai:

procedure TfrmMain.ICQFmsgNewLine(Sender: TObject; Origin, Time,

Line: String);

begin

frmReceive := TfrmReceive.Create(Application);

frmReceive.Caption := Origin;

frmReceive.mmoReceive.Text := Line;

frmReceive.ShowModal;

frmReceive.Free;

end;

procedure TfrmMain.ICQFmsgNewMemo(Sender: TObject; Origin, Time: String;

MsgLines: TStrings);

begin

frmReceive := TfrmReceive.Create(Application);

frmReceive.Caption := Origin;

frmReceive.mmoReceive.Lines := MsgLines;

Beep;

frmReceive.ShowModal;

frmReceive.Free;

end;

Link para o comentário
Compartilhar em outros sites

  • 0

fajo, já que sim, coloque um brack-point nas linhas "frmReceive := TfrmReceive.Create(Application);" dos procedimentos e execute o programa de dentro da IDE do delphi (F9), só para ter certeza de que eles não estão sendo chamados mesmo (só para desencargo de consciência).

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Guest Visitante

São executadas sim Micheus, só não no caso que eu disse, que é quando a aplicação inicia no tray, consequentente não é focada e dessa forma as outras aplicações na rede não reconhecem-na, sendo dessa forma enviar mensagem!

Obrigado

Link para o comentário
Compartilhar em outros sites

  • 0
São executadas sim Micheus, só não no caso que eu disse, que é quando a aplicação inicia no tray, consequentente não é focada e dessa forma as outras aplicações na rede não reconhecem-na, sendo dessa forma enviar mensagem!
Acho que agora entendi, veja se é isso: Chegando as mensagens, pelos eventos OnNewLine e OnNewMemo, a janela do seu programa (frmReceive) é apresentada sem problemas - certo?

..., o problema que eu detectei é que a rotina responsável por coletar as informações dos outros computadores da rede que tem o programa instalado para que sejam listados no listbox, só é executada quando o form é..., até meio complicado explicar, acho que quando ele é focado, tipo assim, quando eu disabilito a iniciação no tray, ou seja, quando ele é executado como outro programa a rotina é lida e a coleta das informações é feita, ...
e olhando novamente seu 2º post, acho que a questão é o fato de quando o programa está minimizado (na tray) a atualização da lista de usuários com o programa rodando não é atualizada. Seria isto?

Se for, repetindo a sugestão anterior, você tem algum processamento para o evento OnUserListChange? Já confirmou que ele não ocorre?

É que não tem como você manter o foco na sua aplicação minimizada. Ela está lá digamos que "em stand-by" esperando algum evento para executar alguma função. Se o evento não ocorre, ela não vai executar nada. E então talvez tenhamos que verificar em quem é responsável pela geração deste evento para, quem sabe, resolver o problema.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

é exatamente como você disse, quando está minimizada no tray a rotina OnUserListChange não é executada, acho que vou desistir disso, como você mesmo disse não tem como manter o foco em uma aplicação minimizada, se você puder me fazer mais um favor, analisar o código mais acima e me dizer onde é que ele pega os computadores da rede, porque a unica coisa que eu vi foi GetComputerName e até onde sei isso pega o nome do computador local e a rotina que faz isso é:

Procedure TMainMessenger.SendCommand(Recipient,Command : string);

begin

Outstrings.Add('COMMAND_MSG');

Outstrings.Add(TimeToStr(Time));

OutStrings.Add(FComputer);

OutStrings.Add(Command);

OutStrings.Add('END_MESSAGE');

SendOutStrings(Recipient);

end;

tem essa variável FComputer; e apesar de ter também uma FUser que teoricamente serviria pra pegar os usuários em vez dos nomes dos computadores, quando eu substituo ela retorna é o nome do usuário local!!!

Por favor, preciso muito disso!!

Obrigado

Link para o comentário
Compartilhar em outros sites

  • 0

fajo, faz um teste com este demo que fiz hoje. Aparentemente, não há qualquer problema relacionado ao fato de o programa não estar com o foco. Quando minimizado:

- toca o Notify.wav ao entrar um usuário na rede;

- abre a tela de mensagem, para resposta, ao receber uma mensagem de outro usuário;

Para colocar o programa na Tray eu utilizei o componente SysTray.

Fiz uma alteração no código do TMessenger 2.0, de modo a receber na lista, além do computador (necessário para a comunicação), o nome do usuário que encontra-se logado nesta máquina.

Se o demo estiver fazendo o que você estava precisando, provavelmente você não terá que esquentar a cabeça com aquele outro post sobre usuários logados na rede. Então, teste ele e, se estiver Ok, manda seu mail por PM que lhe envio os fontes.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Micheus, tá muito muito legal mesmo, mesmo estando no tray ele está relacionando os usuários,

- toca o Notify.wav ao entrar um usuário na rede;

- abre a tela de mensagem, para resposta, ao receber uma mensagem de outro usuário;

tudo tranquilo, exceto, que quando se recebe uma mensagem de um usuário aparece é o nome do PC, pelo menos foi o que deu aqui, se você puder revisar..., mas se não tiver tempo pode me mandar o código que eu tento aqui, você já fez muito, pra não dizer quase tudo!!

"Fiz uma alteração no código do TMessenger 2.0, de modo a receber na lista, além do computador (necessário para a comunicação), o nome do usuário que encontra-se logado nesta máquina."

só aparece o nome do usuário!!

Link para o comentário
Compartilhar em outros sites

  • 0
Micheus, tá muito muito legal mesmo, mesmo estando no tray ele está relacionando os usuários,

- toca o Notify.wav ao entrar um usuário na rede;

- abre a tela de mensagem, para resposta, ao receber uma mensagem de outro usuário;

tudo tranquilo, exceto, que quando se recebe uma mensagem de um usuário aparece é o nome do PC, pelo menos foi o que deu aqui, se você puder revisar...,

É que não acabei o demo e faltou alterar isso. :D

mas se não tiver tempo pode me mandar o código que eu tento aqui, você já fez muito, pra não dizer quase tudo!!
estou passando amanhã demanhã, o código tá lá no meu trabalho. beleza.

"Fiz uma alteração no código do TMessenger 2.0, de modo a receber na lista, além do computador (necessário para a comunicação), o nome do usuário que encontra-se logado nesta máquina."

só aparece o nome do usuário!!

você quer que apareça mais alguma coisa?

Eu chequei a pensar em por o nome da máquina entre parenteses. Como me empouguei com o negócio, estou pensando em mais um monte de coisa. :D

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
você quer que apareça mais alguma coisa?

acho que se aparecer o nome do pc na listagem também, é interessante!

Como me empouguei com o negócio, estou pensando em mais um monte de coisa.

Eu também estou pensando em outras implementações, como:

quando chegar uma mensagem, deve ser pedida uma senha, para que só a pessoa para quem a mensagem foi enviada possa abri-la,nesse caso devemos fazer um armazenamento com usuario e senha, mas acho que não seja preciso um bd, acho que se trabalharmos com ClientDataSet e arquivos texto criptografados deve dar criados na propria máquina, onde quando o programa abrir deverá verificar se a atual pessoa logada tem um cadastro e se tem uma senha, senão, deverá abrir um pequeno cadastro e ai vai...

outra coisa bem interessante é o envio de anexos à mensagem, pense nisso!!!

estou esperando o email

Té +

Link para o comentário
Compartilhar em outros sites

  • 0
Eu também estou pensando em outras implementações, como:

quando chegar uma mensagem, deve ser pedida uma senha, para que só a pessoa para quem a mensagem foi enviada possa abri-la,nesse caso devemos fazer um armazenamento com usuario e senha, mas acho que não seja preciso um bd, acho que se trabalharmos com ClientDataSet e arquivos texto criptografados deve dar criados na propria máquina, onde quando o programa abrir deverá verificar se a atual pessoa logada tem um cadastro e se tem uma senha, senão, deverá abrir um pequeno cadastro e ai vai...

Acho que poderia ser assim mesmo.

outra coisa bem interessante é o envio de anexos à mensagem, pense nisso!!!
Isso implica em mudanças mais "drástricas". O componente TMessenger faz uso de MailSlot (msdn). Para implementar isto, teríamos que partir para outras abordagens, devido a restrição no tamanho da mensagem que pode ser trocada entre os computadores:

"To send messages that are larger than 424 bytes between computers, use named pipes or Windows Sockets instead." (veja no link do msdn acima)

estou esperando o email
Enviei para o do GMail

Abraços

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,3k
    • Posts
      652,4k
×
×
  • Criar Novo...