Ir al contenido



Foto

Escribir una notificación en el SysTray


  • Por favor identifícate para responder
14 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 14 septiembre 2015 - 11:45

Es útil escribir notificaciones en el SysTray y resulta profesional hacerlo, para ello ya publiqué el componente SysTrayIcon. En esta ocasión muestro como hacerlo sin necesidad de dicho componente, para aplicaciones sencillas.
Utiliza sólo la API y sigue el estándar de Win10:
 

Definiciones:


delphi
  1. TNotifyIconData = record
  2. cbSize: DWORD;
  3. Wnd: HWND;
  4. uID: UINT;
  5. uFlags: UINT;
  6. uCallbackMessage: UINT;
  7. hIcon: HICON;
  8. szTip: array [0..127] of AnsiChar;
  9. dwState: DWORD;
  10. dwStateMask: DWORD;
  11. szInfo: array [0..255] of AnsiChar;
  12. uTimeout: UINT;
  13. szInfoTitle: array [0..63] of AnsiChar;
  14. dwInfoFlags: DWORD;
  15. end;
  16.  
  17. // Ampliaciones para Vista
  18. const NIIF_INFO = $00000001;
  19. const NIF_INFO = $00000010;
  20. const NIF_REALTIME = $00000040;
  21. const NIF_SHOWTIP = $00000080;
  22. const NIIF_USER = $00000004;

El procedimiento:


delphi
  1. procedure ShowBalloon(Handle: THANDLE; Titulo, Texto: String);
  2. var
  3.   Data: TNotifyIconData;
  4. begin
  5.   ZeroMemory(@Data, sizeof(TNotifyIconData));
  6.   Data.cbSize:= sizeof(TNotifyIconData);
  7.   Data.uFlags:= NIF_ICON or NIF_INFO or NIF_REALTIME;
  8.   Data.dwInfoFlags:= NIIF_INFO;
  9.   lstrcpyn(Data.szInfoTitle, PCHAR(Titulo), 64-1);
  10.   lstrcpyn(Data.szInfo, PCHAR(Texto), 256-1);
  11.   Data.uTimeOut:= 1000;
  12.   Data.Wnd:=  Handle;
  13.   Shell_NotifyIcon(NIM_ADD, @Data);
  14.   Shell_NotifyIcon(NIM_MODIFY, @Data);
  15. Shell_NotifyIcon(NIM_DELETE, @Data); // Para WinXP comentar esta línea. En el resto de S.O. funciona con esta línea comentada
  16. end;

Uso:


delphi
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. begin
  3. ShowBalloon(Handle, Edit1.Text, Edit2.Text);
  4. end;

Subo un proyecto de ejemplo.
Saludos.

Archivos adjuntos


  • 4

#2 ELKurgan

ELKurgan

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 518 mensajes
  • LocationEspaña

Escrito 14 septiembre 2015 - 11:35

Como siempre, muy bueno

 

:ap:


  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 15 septiembre 2015 - 05:09

Muy bueno, relamente.

Aunque si nos proponemos, todo se puede programar por medio de la API, incluso, los motores de bases de datos se pueden usar con lenguaje puro sin usar los componentes provistos por la VCL o FM, eso sí: hay que trabajar mucho.

Antes tenía esa visión de Escafandra y me proponía hacer las cosas yo mismo. Lamento haber dejado ese lado de la programación, supongo que lo hice cuando empecé a programar sistemas de tipo contable.

 

Saludos


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 15 septiembre 2015 - 08:52

Muy bueno, relamente.
Aunque si nos proponemos, todo se puede programar por medio de la API, incluso, los motores de bases de datos se pueden usar con lenguaje puro sin usar los componentes provistos por la VCL o FM, eso sí: hay que trabajar mucho.
Antes tenía esa visión de Escafandra y me proponía hacer las cosas yo mismo. Lamento haber dejado ese lado de la programación, supongo que lo hice cuando empecé a programar sistemas de tipo contable.

Saludos

Estas cosas y forma de programar viene bien para pequeños proyectos en los que el tamaño del ejecutable prima. Vas añadiendo funciones a tu librería y luego no cuesta nada ir añadiendo código reutilizado. Tengo mi PC lleno de estas pequeñas cosas que añado según necesidades.


Saludos.
  • 0

#5 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 15 septiembre 2015 - 09:18

Dada mi debilidad por el C/C++ voy a publicar el truco en ese lenguaje:
 


cpp
  1. // Ampliaciones para Vista
  2. #define NIIF_INFO 0x00000001
  3. #define NIF_INFO 0x00000010
  4. #define NIF_REALTIME 0x00000040
  5. #define NIF_SHOWTIP 0x00000080
  6. #define NIIF_USER 0x00000004
  7.  
  8.  
  9. void ShowBalloon(HANDLE Handle, PCHAR Titulo, PCHAR Texto)
  10. {
  11. NOTIFYICONDATA Data;
  12. ZeroMemory(&Data, sizeof(NOTIFYICONDATA));
  13. Data.cbSize = sizeof(TNotifyIconData);
  14. Data.uFlags = NIF_ICON | NIF_INFO | NIF_REALTIME;
  15. Data.dwInfoFlags = NIIF_INFO;
  16. lstrcpyn(Data.szInfoTitle, Titulo, 64-1);
  17. lstrcpyn(Data.szInfo, Texto, 256-1);
  18. Data.uTimeout = 1000;
  19. Data.hWnd = Handle;
  20. Shell_NotifyIcon(NIM_ADD, &Data);
  21. Shell_NotifyIcon(NIM_MODIFY, &Data);
  22. }

 
 
Y la forma de uso:


cpp
  1. void __fastcall TForm1::Button1Click(TObject *Sender)
  2. {
  3. ShowBalloon(Handle, Edit1->Text.c_str(), Edit2->Text.c_str());
  4. }

Saludos


  • 1

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.066 mensajes
  • LocationArgentina

Escrito 16 septiembre 2015 - 12:19

Interesante.

Estoy estudiando para un proyecto que tengo en mano la posibilidad de implementar algo de notificaciones. Pensé en algo como lo que tiene Dropbox y Copy que muestra/notifica/alerta los cambios que se realizan. Y también he pensado en la notificación en la SysTray como en tu ejemplo.

 

Se que esto de la API es en Windows, y en vista a que tengo a un "cliente" que emplea Linux me limita. Espero que Lazarus tenga algo parecido multiplataforma, sino habrá que estudiarle la vuelta.

Lo deseable es que la aplicación esté en 2do plano, para no tener que tenerla minimizada. Y como se trata de una aplicación que estará monitoreando, pienso que una buena manera de reportar los cambios del monitoreo en forma de notificaciones.

 

Saludos,


  • 0

#7 Koalasoft

Koalasoft

    Advanced Member

  • Miembros
  • PipPipPip
  • 131 mensajes
  • LocationMéxico

Escrito 03 enero 2017 - 07:13

Es útil escribir notificaciones en el SysTray y resulta profesional hacerlo, para ello ya publiqué el componente SysTrayIcon. En esta ocasión muestro como hacerlo sin necesidad de dicho componente, para aplicaciones sencillas.
Utiliza sólo la API y sigue el estándar de Win10:
 

Definiciones:


delphi
  1. TNotifyIconData = record
  2. cbSize: DWORD;
  3. Wnd: HWND;
  4. uID: UINT;
  5. uFlags: UINT;
  6. uCallbackMessage: UINT;
  7. hIcon: HICON;
  8. szTip: array [0..127] of AnsiChar;
  9. dwState: DWORD;
  10. dwStateMask: DWORD;
  11. szInfo: array [0..255] of AnsiChar;
  12. uTimeout: UINT;
  13. szInfoTitle: array [0..63] of AnsiChar;
  14. dwInfoFlags: DWORD;
  15. end;
  16.  
  17. // Ampliaciones para Vista
  18. const NIIF_INFO = $00000001;
  19. const NIF_INFO = $00000010;
  20. const NIF_REALTIME = $00000040;
  21. const NIF_SHOWTIP = $00000080;
  22. const NIIF_USER = $00000004;

El procedimiento:


delphi
  1. procedure ShowBalloon(Handle: THANDLE; Titulo, Texto: String);
  2. var
  3.   Data: TNotifyIconData;
  4. begin
  5.   ZeroMemory(@Data, sizeof(TNotifyIconData));
  6.   Data.cbSize:= sizeof(TNotifyIconData);
  7.   Data.uFlags:= NIF_ICON or NIF_INFO or NIF_REALTIME;
  8.   Data.dwInfoFlags:= NIIF_INFO;
  9.   lstrcpyn(Data.szInfoTitle, PCHAR(Titulo), 64-1);
  10.   lstrcpyn(Data.szInfo, PCHAR(Texto), 256-1);
  11.   Data.uTimeOut:= 1000;
  12.   Data.Wnd:=  Handle;
  13.   Shell_NotifyIcon(NIM_ADD, @Data);
  14.   Shell_NotifyIcon(NIM_MODIFY, @Data);
  15. Shell_NotifyIcon(NIM_DELETE, @Data); // Para WinXP comentar esta línea. En el resto de S.O. funciona con esta línea comentada
  16. end;

Uso:


delphi
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. begin
  3. ShowBalloon(Handle, Edit1.Text, Edit2.Text);
  4. end;

Subo un proyecto de ejemplo.
Saludos.

 

Muchas gracias por tu ejemplo, una pregunta .. 

Cómo sería para que en la notificación en lugar de poner el símbolo de información, esta vez fuera de error?


  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.066 mensajes
  • LocationArgentina

Escrito 03 enero 2017 - 08:30

Con NIF_WARNING. Más info en su página de MSDN.

Perdón, con NIIF_WARNING.

 

Saludos,


  • 0

#9 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 04 enero 2017 - 05:19

Muchas gracias por tu ejemplo, una pregunta .. 
Cómo sería para que en la notificación en lugar de poner el símbolo de información, esta vez fuera de error?

El código podría modificarse así:


delphi
  1.   TNotifyIconData = record
  2.     cbSize: DWORD;
  3.     Wnd: HWND;
  4.     uID: UINT;
  5.     uFlags: UINT;
  6.     uCallbackMessage: UINT;
  7.     hIcon: HICON;
  8.     szTip: array [0..127] of AnsiChar;
  9.     dwState: DWORD;
  10.     dwStateMask: DWORD;
  11.     szInfo: array [0..255] of AnsiChar;
  12.     uTimeout: UINT;
  13.     szInfoTitle: array [0..63] of AnsiChar;
  14.     dwInfoFlags: DWORD;
  15.   end;
  16.  
  17. // Ampliaciones para Vista
  18. const NIF_INFO     = $00000010;
  19. const NIF_REALTIME = $00000040;
  20. const NIF_SHOWTIP  = $00000080;
  21.  
  22. // InfoFlags
  23. const NIIF_NONE    = $00000000;
  24. const NIIF_INFO    = $00000001;
  25. const NIIF_WARNING = $00000002;
  26. const NIIF_ERROR   = $00000003;
  27. const NIIF_USER    = $00000004;


delphi
  1. procedure ShowBalloon(Handle: THANDLE; Titulo, Texto: String; InfoFlags: DWORD);
  2. var
  3. Data: TNotifyIconData;
  4. begin
  5. ZeroMemory(@Data, sizeof(TNotifyIconData));
  6. Data.cbSize:= sizeof(TNotifyIconData);
  7. Data.uFlags:= NIF_ICON or NIF_INFO or NIF_REALTIME;
  8. Data.dwInfoFlags:= InfoFlags;
  9. lstrcpyn(Data.szInfoTitle, PCHAR(Titulo), 64-1);
  10. lstrcpyn(Data.szInfo, PCHAR(Texto), 256-1);
  11. Data.uTimeOut:= 1000;
  12. Data.Wnd:= Handle;
  13. Shell_NotifyIcon(NIM_ADD, @Data);
  14. Shell_NotifyIcon(NIM_MODIFY, @Data);
  15. Shell_NotifyIcon(NIM_DELETE, @Data);
  16. end;

Las InfoFlags de iconos de notificación no son sumables.

 

Subo un proyecto de ejemplo delphi7

Archivos adjuntos


  • 0

#10 Koalasoft

Koalasoft

    Advanced Member

  • Miembros
  • PipPipPip
  • 131 mensajes
  • LocationMéxico

Escrito 04 enero 2017 - 10:03

El código podría modificarse así:


delphi
  1.   TNotifyIconData = record
  2.     cbSize: DWORD;
  3.     Wnd: HWND;
  4.     uID: UINT;
  5.     uFlags: UINT;
  6.     uCallbackMessage: UINT;
  7.     hIcon: HICON;
  8.     szTip: array [0..127] of AnsiChar;
  9.     dwState: DWORD;
  10.     dwStateMask: DWORD;
  11.     szInfo: array [0..255] of AnsiChar;
  12.     uTimeout: UINT;
  13.     szInfoTitle: array [0..63] of AnsiChar;
  14.     dwInfoFlags: DWORD;
  15.   end;
  16.  
  17. // Ampliaciones para Vista
  18. const NIF_INFO     = $00000010;
  19. const NIF_REALTIME = $00000040;
  20. const NIF_SHOWTIP  = $00000080;
  21.  
  22. // InfoFlags
  23. const NIIF_NONE    = $00000000;
  24. const NIIF_INFO    = $00000001;
  25. const NIIF_WARNING = $00000002;
  26. const NIIF_ERROR   = $00000003;
  27. const NIIF_USER    = $00000004;


delphi
  1. procedure ShowBalloon(Handle: THANDLE; Titulo, Texto: String; InfoFlags: DWORD);
  2. var
  3. Data: TNotifyIconData;
  4. begin
  5. ZeroMemory(@Data, sizeof(TNotifyIconData));
  6. Data.cbSize:= sizeof(TNotifyIconData);
  7. Data.uFlags:= NIF_ICON or NIF_INFO or NIF_REALTIME;
  8. Data.dwInfoFlags:= InfoFlags;
  9. lstrcpyn(Data.szInfoTitle, PCHAR(Titulo), 64-1);
  10. lstrcpyn(Data.szInfo, PCHAR(Texto), 256-1);
  11. Data.uTimeOut:= 1000;
  12. Data.Wnd:= Handle;
  13. Shell_NotifyIcon(NIM_ADD, @Data);
  14. Shell_NotifyIcon(NIM_MODIFY, @Data);
  15. Shell_NotifyIcon(NIM_DELETE, @Data);
  16. end;

Las InfoFlags de iconos de notificación no son sumables.

 

Subo un proyecto de ejemplo delphi7

 

Acabo de checar tu programa, tengo Windows 10 con Delphi 7, al ejecutarlo todo muy bien, gracias por el ejemplo, pero .. un detalle curioso, al dar click y mostrarme la notificación .. manda el mensaje dos veces seguidas, una después del otro .. es normal eso?


  • 0

#11 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 04 enero 2017 - 10:50

Acabo de checar tu programa, tengo Windows 10 con Delphi 7, al ejecutarlo todo muy bien, gracias por el ejemplo, pero .. un detalle curioso, al dar click y mostrarme la notificación .. manda el mensaje dos veces seguidas, una después del otro .. es normal eso?

Si estas usando Windows >= Vista, Data.uTimeOut se refiere a la versión de Shell notification (en XP es un TimeOut). Sustituye el valor por  1:


delphi
  1. Data.uTimeOut:= 1;

795db52491f0213506d35105eb58137do.gif


 

Saludos.


  • 1

#12 Koalasoft

Koalasoft

    Advanced Member

  • Miembros
  • PipPipPip
  • 131 mensajes
  • LocationMéxico

Escrito 13 diciembre 2017 - 11:35

Si estas usando Windows >= Vista, Data.uTimeOut se refiere a la versión de Shell notification (en XP es un TimeOut). Sustituye el valor por  1:


delphi
  1. Data.uTimeOut:= 1;

795db52491f0213506d35105eb58137do.gif


 

Saludos.

 

Estimado, después de que W10 hizo una actualización, este tipo de mensajes ya no funciona, sabes a que se deberá esto? les ha pasado?


  • 0

#13 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 19 diciembre 2017 - 01:01

Estimado, después de que W10 hizo una actualización, este tipo de mensajes ya no funciona, sabes a que se deberá esto? les ha pasado?

 

Parece que a M$ le gusta cambiar cosas

 

Comenta esta línea y me cuentas:


delphi
  1. Shell_NotifyIcon(NIM_DELETE, @Data);

Debería quedarte como sigue:


delphi
  1. procedure ShowBalloon(Handle: THANDLE; Titulo, Texto: String; InfoFlags: DWORD);
  2. var
  3. Data: TNotifyIconData;
  4. begin
  5. ZeroMemory(@Data, sizeof(TNotifyIconData));
  6. Data.cbSize:= sizeof(TNotifyIconData);
  7. Data.uFlags:= NIF_ICON or NIF_INFO or NIF_REALTIME;
  8. Data.dwInfoFlags:= InfoFlags;
  9. lstrcpyn(Data.szInfoTitle, PCHAR(Titulo), 64-1);
  10. lstrcpyn(Data.szInfo, PCHAR(Texto), 256-1);
  11. Data.uTimeOut:= 1;
  12. Data.Wnd:= Handle;
  13. Shell_NotifyIcon(NIM_ADD, @Data);
  14. Shell_NotifyIcon(NIM_MODIFY, @Data);
  15. //Shell_NotifyIcon(NIM_DELETE, @Data);
  16. end;

Saludos.


  • 1

#14 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.744 mensajes
  • LocationMéxico

Escrito 19 diciembre 2017 - 09:53

Parece que a M$ le gusta cambiar cosas

 

Si que le gusta cambiarlas :D

 

Acaba de instalarse la ultima version de Win10 en mi máquina y si que veo algunas diferencias aunque muy sutiles.

 

Saludos


  • 0

#15 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.733 mensajes
  • LocationMadrid - España

Escrito 19 diciembre 2017 - 02:53

Si que le gusta cambiarlas :D

 

Acaba de instalarse la ultima version de Win10 en mi máquina y si que veo algunas diferencias aunque muy sutiles.

 

Saludos

He probado en Win8 actualizado y el código precisa comentar Shell_NotifyIcon(NIM_DELETE, @Data), tambien en WinXP, sin embargo no en Win10 actualizado. Por lo tanto lo mejor es comentarlo siempre como expongo aquí.

 

Saludos.


  • 0