Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Minimizar al trayicon (https://www.clubdelphi.com/foros/showthread.php?t=86953)

aguml 27-10-2014 15:11:08

Minimizar al trayicon
 
Hola amigos, tengo esto:
Código PHP:

private:    // User declarations
   // Capturar mensajes al form
  
void __fastcall OnWMSysCommand(TWMSysCommand &Msg); //message WM_SYSCOMMAND;
  
TWndMethod OldWMSysCommand;
  
void __fastcall NewWMSysCommand(TMessageMessage);
protected:
   
BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER
(WM_SYSCOMMANDTWMSysCommandOnWMSysCommand)
   
END_MESSAGE_MAP(TForm

Código PHP:

void __fastcall TForm1::OnWMSysCommand(TWMSysCommand &Msg)
{
   
// Minimizando?
   
if (Msg.CmdType == SC_MINIMIZE){
      
// Accion de ocultar el form
      
SysTrayIcon1->Minimize();
   }else{
      
// comportamiento estandard
      
DefaultHandler(Msg);
   }


y no me compila dando el error:
Cita:

[C++ Error] Main.cpp(412): E2316 '_fastcall TForm1::OnWMSysCommand(TMessage &)' is not a member of 'TForm1'
¿Me podeis ayudar?

aguml 27-10-2014 19:29:04

al final lo he podido solucionar. Solo tuve que cambiar el DefaultHandle por DispathMessage.

escafandra 27-10-2014 21:07:11

No comprendo porqué quieres manejar el mensaje SC_MINIMIZE para forzar a SysTrayIcon a ejecutar Minimize() cuando eso ya lo detecta por si solo el componente. Fíjate en este fragmento de código de SysTrayIcon:

Código PHP:

bool __fastcall TSysTrayIcon::ApplicationHookProc(TMessage &Message)
{
   if (
Message.Msg == WM_SYSCOMMAND)
   {
      if (
Message.WParam == SC_MINIMIZE)
         
Minimize();
      if (
Message.WParam == SC_RESTORE)
         
Restore();
   }

   return 
false;


Tiene capturado ("hookeado") el mensaje WM_SYSCOMMAND de la aplicación para detectar SC_MINIMIZE y SC_RESTORE. No tiene sentido rehacerlo, ¿qué necesidad has encontrado para hacerlo?

Saludos.

aguml 27-10-2014 22:38:53

Cita:

Empezado por escafandra (Mensaje 483897)
No comprendo porqué quieres manejar el mensaje SC_MINIMIZE para forzar a SysTrayIcon a ejecutar Minimize() cuando eso ya lo detecta por si solo el componente. Fíjate en este fragmento de código de SysTrayIcon:

Código PHP:

bool __fastcall TSysTrayIcon::ApplicationHookProc(TMessage &Message)
{
   if (
Message.Msg == WM_SYSCOMMAND)
   {
      if (
Message.WParam == SC_MINIMIZE)
         
Minimize();
      if (
Message.WParam == SC_RESTORE)
         
Restore();
   }

   return 
false;


Tiene capturado ("hookeado") el mensaje WM_SYSCOMMAND de la aplicación para detectar SC_MINIMIZE y SC_RESTORE. No tiene sentido rehacerlo, ¿qué necesidad has encontrado para hacerlo?

Saludos.

Pues amigo, algo raro pasaba porque al yo minimizar el form no se minimizaba al tray icon.
Te pongo el link para que lo puedas mirar: https://mega.co.nz/#!xpNmESJI!6GSaf6...nPmleTPSDZtoNg

Está en Main.h y Main.cpp

ecfisa 28-10-2014 00:06:44

Hola aguml.
Cita:

Empezado por aguml (Mensaje 483873)
Hola amigos, tengo esto:
Código PHP:

private:    // User declarations
   // Capturar mensajes al form
  
void __fastcall OnWMSysCommand(TWMSysCommand &Msg); //message WM_SYSCOMMAND;
  
TWndMethod OldWMSysCommand;
  
void __fastcall NewWMSysCommand(TMessageMessage);
protected:
   
BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER
(WM_SYSCOMMANDTWMSysCommandOnWMSysCommand)
   
END_MESSAGE_MAP(TForm

...

y no me compila dando el error:

¿Me podeis ayudar?

Fuera de tópico, mas allá de la explicación sobre el componente que te ha dado escafandra, para cualquier otro caso ese código no va a funcionar.

Debería bastar con:
Código PHP:

...
class 
TForm1 : public TForm
{
private:
  
void __fastcall WMSysCommand(TWMSysCommand &Msg);

protected:
  
BEGIN_MESSAGE_MAP
  VCL_MESSAGE_HANDLER
(WM_SYSCOMMANDTWMSysCommandWMSysCommand)
  
END_MESSAGE_MAP(TForm)

__published:

public:
  
__fastcall TForm1(TComponentOwner);
};
extern PACKAGE TForm1 *Form1;
... 

Código PHP:

...
void __fastcall TForm1::WMSysCommand(TWMSysCommand &Msg)
{
  switch (
Msg.CmdType) {
    case 
SC_MINIMIZEShowMessage("Minimize");break;
    case 
SC_RESTORE ShowMessage("Restore"); break;
    case 
SC_MAXIMIZEShowMessage("Maximize");break;
  }
  
DefaultHandler(&Msg);
}
... 

Saludos :)

escafandra 28-10-2014 02:07:35

Ya se a que te refieres, aguml. El componente no está diseñado para cambiar la visibilidad del formulario en el evento OnMinimize pero es fácil de solucionar.

Hoy es tarde para mi. Mañana te subo un cambio en el componente que permitirá hacerlo.


Saludos.

aguml 28-10-2014 07:27:55

ok, mil gracias amigo.
Supongo que tendras que añadir alguna propiedad para indicar si queremos que lo haga o no ¿verdad? Ya puestos estaria bien que podamos elegir que debe hacer al pulsar el boton de cerrar ya que hay muchas aplicaciones que al darle al boton cerrar de la barra del form te colocan la aplicacion en el systrayicon.
De momento he aprendido mucho intentando solucionarlo.
Por cierto ecfisa, lo que me indicas no está del todo bien ya que si o si ejecutas la accion por defecto y si yo lo oculto a la icontray y luego ejecuto la accion por defecto es como si no hubiera hecho nada ya que me aparece minimizado y no es lo que deseo. Asi si va:
Código PHP:

void __fastcall TForm1::OnWMSysCommand(TWMSysCommand &Msg)
{
   
// Minimizando?
   
switch(Msg.CmdType)
   {
      case 
SC_MINIMIZE:
         
// Accion de ocultar el form
         
SysTrayIcon1->Minimize();
         break;

      default:
         
// comportamiento estandard
         
DefaultHandler(&Msg);
   }


Aunque no se como solucionar este warning que me muestra:
Código:

[C++ Warning] Main.h(82): W8027 Functions containing switch are not expanded inline
Es por lo que hay colocado en el protected pero a mi eso que dice es como si me hablara en chino jejeje.

aguml 28-10-2014 08:50:39

otra cosa ¿Que diferencia hay entre usar DispathMessage y usar DefaultHandler? En ambos casos me funciona perfecto.

ecfisa 28-10-2014 14:56:54

Cita:

Empezado por aguml (Mensaje 483910)
Por cierto ecfisa, lo que me indicas no está del todo bien ya que si o si ejecutas la accion por defecto y si yo lo oculto a la icontray y luego ejecuto la accion por defecto es como si no hubiera hecho nada ya que me aparece minimizado y no es lo que deseo. Asi si va:

Es cierto, la verdad es que me interesaba destacar la forma correcta de la declaración y escribí el ejemplo sobre el mensaje sin haberlo probado. Se me escapó ese detalle...

Saludos:)

escafandra 28-10-2014 19:50:11

He hecho algún pequeño cambio en el componente y ya funciona como esperaba aguml, no hay nuevas propiedades.

Para evitar el cierre de la app y llevarla en segundo plano al Systray sólo tenemos que actuar en el formulario de la siguiente manera:

Código PHP:

void __fastcall TForm1::FormCloseQuery(TObject *Senderbool &CanClose)
{
  
SysTrayIcon1->Visible true;
  
SysTrayIcon1->Hide true;
  
SysTrayIcon1->Minimize();
  
CanClose false;


El enlace de la actualización de TSysTrayIcon lo tienes aquí.

PD/ Ya no es necesario el uso de OnWMSysCommand

Saludos.

aguml 28-10-2014 22:37:26

me pierdo un poco porque no se donde está formclosequery y que es eso de canclose. ¿Es un evento de TForm de los que vienen por defecto? Y si hago eso y luego coloco un boton para cerrar el form ¿Pongo close() y ya está? ¿O tengo que cambiar antes el valor de canclose? ¿Y si le doy a minimizar ¿En que evento coloco el codigo para que minimice a las systray? Una cosa, ¿No hubiese sido mas sencillo crear por ejemplo la propiedad buttonbarminimize que pueda valer por ejemplo buttonclose y buttonminimize y otra propiedad que por ejemplo llamemos sysminimize de tipo bool y que donde haces en tu componente el hook a esos mensajes de la sysbar, si tenemos a true esa propiedad, dependiendo del valor de la otra propiedad usemos un boton o el otro para minimizarlo a la systray? Es una sugerencia, el maestro eres tu :-P

escafandra 28-10-2014 22:55:18

OnCloseQuery es un evento del formulario que se activa justo antes que OnClose. Si CanClose toma el valor true el formulario se cierre, en caso contrario no.


Saludos.

escafandra 28-10-2014 23:02:12

Cita:

Empezado por aguml (Mensaje 483942)
¿No hubiese sido mas sencillo crear por ejemplo la propiedad buttonbarminimize que pueda valer por ejemplo buttonclose y buttonminimize y otra propiedad que por ejemplo llamemos sysminimize de tipo bool y que donde haces en tu componente el hook a esos mensajes de la sysbar, si tenemos a true esa propiedad, dependiendo del valor de la otra propiedad usemos un boton o el otro para minimizarlo a la systray?

Si se sobrecarga el componente de propiedades y eventos que puede manejar el Form, deja de ser intuitivo y liamos al personal. El evento OnCloseQuery está diseñado para el control de la salida o no del formulario y es común usarlo. Con las propiedades que tiene TSysTrayIcon se consigue hacer casi todo lo que un desarrollador pretende de él.

Prueba la nueva versión, ya no te hace falta el uso de OnWMSysCommand, lo hace el mismo componente. Pero tu programas lo que se hará en OnMinimize o en OnRestore, que para eso implementé esos eventos del componente.


Saludos.

aguml 29-10-2014 08:47:10

ok, lo pruebo y comento.

aguml 29-10-2014 12:44:15

Amigo, lo he probado y no funciona exactamente como esperaba.
Te explico, lo ideal es poder elegir entre si se debe ocultar al cerrar o solo cerrarse. Eso ya está solucionado en tu componente.
El otro punto es si se debe ocultar al minimizar, o simplemente minimizarse. Eso sin el hook no soy capaz de conseguirlo. Es mas, DefaultHandler no funciona como debiera ya que lo minimiza pero no a la barra de tareas sino que lo minimiza en el lado izquierdo de la pantalla y sigues viendo la barra superior del form con los tres botones mientras que con TForm::Dispatch(&Msg) se minimiza a la barra de tareas.

He modificado el proyecto que subí anteriormente para hacer pruebas y lo adjunto para que veas lo que digo. En este sigo teniendo la funcion que me dices que no hace falta para que veas que funciona e intentes hacerlo funcionar sin ella de igual manera.

Link: https://mega.co.nz/#!81cwEYrb!zkHzVP...GFkxV-DzgWuzT8

A ver si puedes verlo y me cuentas, que a lo mejor se puede sin esa funcion y soy yo el que no ve como jejeje. :p

escafandra 31-10-2014 00:15:56

He visto lo que dices y he dado unas vueltas al control TSysTrayIcon tenía un bug en la última actualización. Descarga la última versión.

Debes cambiar tu código de la siguiente forma:

En Main.h añade:
Código PHP:

private:
   
bool SyStrayCanClose

En el código Main.cpp eliminas OnWMSysCommand y su declaración, además modificas lo siguiente:
Código PHP:

void __fastcall TForm1::SysTrayIcon1Restore(TObject *Sender)
{
   
SysTrayIcon1->Visible false;
   
SysTrayIcon1->Hide false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SysTrayIcon1Minimize(TObject *Sender)
{
   
bool SysTray CheckBoxMinToSysTray->Checked && ComboBox1->ItemIndex >= 1;
   
SysTray |= !SyStrayCanClose;
   
SyStrayCanClose true;
   
SysTrayIcon1->Visible SysTray;
   
SysTrayIcon1->Hide SysTray;
   if(
SysTrayIcon1->Animate == true)
      
SysTrayIcon1->ShowBalloon("Buscando el serial","Estoy buscando el serial, por favor espere a que termine.");
   else
      
SysTrayIcon1->ShowBalloon("Sin actividad","Ahora mismo no estoy realizando ninguna busqueda.\nPermanezco aquí esperando a que me pongas a currar.");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCloseQuery(TObject *Senderbool &CanClose)
{
   if(
CloseApp){
      
CanClose CloseApp;
   }else{
      
CanClose = !(CheckBoxMinToSysTray->Checked && ComboBox1->ItemIndex != 1);
      
SyStrayCanClose CanClose;
      
SysTrayIcon1->Minimize();
   }


Saludos.


La franja horaria es GMT +2. Ahora son las 06:05:10.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi