[C++] System Tray messages

System Tray messages [C++] - C++ - Programmation

Marsh Posté le 20-04-2002 à 15:14:55    

Salut,
je crée une icone dans la system tray (Shell_NotifyIcon) mais comment faire pour intercepter les messages du genre WM_LBUTTONUP,... sur l'icone (et surtout quand l'application n'a pas le focus) ?
merci
   ANT

Reply

Marsh Posté le 20-04-2002 à 15:14:55   

Reply

Marsh Posté le 22-04-2002 à 00:32:45    

bein en passant un callback dans le membre uCallbackMessage de la struct NOTIFYICONDATA ( deuxieme paramettre de Shell_NotifyIcon). La ta fonction sera de type :
 
' en VB
Public Function TrayWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 
 select case msg
    case WM_WM_NCLBUTTONDOWN:  
        ' blah ...
 
' en C/C++
LRESULT CALLBACK SystrayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    switch (msg)
   {
         case WM_WM_NCLBUTTONDOWN :
            {
                // blah ..
                break;
            }
          }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

Reply

Marsh Posté le 22-04-2002 à 18:06:18    

merci !

Reply

Marsh Posté le 22-04-2002 à 18:46:05    

merci pour ton code, voici le mien qui ne fonctionne pas :
 
LRESULT CALLBACK SystrayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
 case WM_NCLBUTTONDOWN:
  MessageBeep(-1);
  break;
 }
 
 return DefWindowProc(hwnd,msg,wParam,lParam);
}
 
 
tnd.uCallbackMessage = (UINT)SystrayWndProc;
 
et bien ça compile mais ça beep pas quand je clique sur l'icone !

Reply

Marsh Posté le 22-04-2002 à 19:53:10    

Moi je fais comme ça, et ça marche très bien.
 
1 - Définir dans le source un message personnalisé :
 
#define WM_TRAYMESSAGE (WM_USER + 101)
 
2 - Rattacher ce message à la structure NOTIFYICONDATA de l'icone du SysTray (ni est une structure NOTIFYICONDATA):
 
ni.uCallbackMessage = WM_TRAYMESSAGE;
ni.uFlags = NIF_ICON | NIF_MESSAGE;
 
3 - Insérer ce message dans la MESSAGEMAP, en lui rattachant la fonction Callback OnTrayMessage() :
 
BEGIN_MESSAGE_MAP(CTaClasse, CParent)
  //{{AFX_MSG_MAP(CTaClasse)
  Messages de Windows, ne pas toucher à cette section
  //}}AFX_MSG_MAP
  ON_MESSAGE(WM_TRAYMESSAGE, OnTrayMessage)
END_MESSAGE_MAP()
 
4 - Implémenter la méthode OnTrayMessage() qui traitera le message :
 
LRESULT CTaClasse:: OnTrayMessage(WPARAM wParam, LPARAM lParam)
{
   if (lParam == WM_RBUTTONDOWN) { // bouton droit enfoncé
         //traitement si le bouton droit est enfoncé sur l'icone
   else if (lParam == WM_LBUTTONDBLCLK) { // double clic
         // traitement si dble clic sur l'icone
   }
   return 0;
}
 
Voila, c'est la manière propre de traiter les messages du SysTray.
 
A+  :hello:

 

[jfdsdjhfuetppo]--Message édité par Harkonnen le 22-04-2002 à 20:00:03--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 22-04-2002 à 20:26:44    

Tout d'abord un grand merci et je m'incline devant un tel professionalisme avec l'utilisation des MFC (ce que je fais à coté c'est vraiment de la bidouille !)  :jap:  
 
Mais une dernière erreur, j'ai mis ça dans la MessageMap
 
ON_MESSAGE(WM_TRAYMESSAGE, OnTrayMessage)
 
mais le compilo me sort une erreur comme quoi OnTrayMessage n'appartient pas à la classe de ma dialog (normal je l'ai défini nulle part). Alors où le définir ou comment faire autrement ?

Reply

Marsh Posté le 22-04-2002 à 20:41:46    

Oups, j'ai effectivement oublié d'insérer la déclaration de ce message. :ouch:  
 
Dans le fichier TaClasse.h, tu dois aller dans la section des déclaration des message map et déclarer ton message de la façon suivante :
 
// Generated message map functions
//{{AFX_MSG(CTaClasse)
// Messages traitant les évènements de ta classe, ne pas toucher
//}}AFX_MSG
afx_msg LRESULT OnTrayMessage(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
 
Désolé pour l'oubli, A+  :hello:

 

[jfdsdjhfuetppo]--Message édité par Harkonnen le 22-04-2002 à 20:42:28--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 23-04-2002 à 19:19:33    

Maintenant ça marche (y avait pas de raisons que ça plante !), alors je te dis un grand merci !
a+
  ANT

Reply

Marsh Posté le 23-04-2002 à 23:29:02    

apres on me demande pkoi j'aime pas utiliser les MFC :)

Reply

Marsh Posté le 24-04-2002 à 09:08:58    

C'est juste une question de rigueur, les MFC ne sont pas plus compliquées qu'autre chose une fois que le principe est compris.
 
Surtout n'hésitez pas à consulter le MSDN, c'est LA référence pour utiliser les MFC correctement.
 
 :hello:

Reply

Marsh Posté le 24-04-2002 à 09:08:58   

Reply

Marsh Posté le 24-04-2002 à 10:12:59    

Je sais bien que c'est pas trop compliqué, je les utilise quand j'ai pas le choix mais c'est le code qu'on a qui m'hérite. Parce que je suis du genre a suivre les normes en prog (ansi), ca fait un peu spaghetti quoi. Mais bon, les mfc sont quand meme puissants.
Pour la MSDN, c'est claire que si je l'avais pas, je ramerais encore :)

 

[jfdsdjhfuetppo]--Message édité par KarLKoX le 24-04-2002 à 10:13:32--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 24-04-2002 à 11:05:08    

Moi perso, depuis que j'ai découvert la plate-forme .NET et le C#, je me demande comment j'ai pu supporter les MFC aussi longtemps !
 
C'est vraiment un environnement génial pour développer, les classes fournies sont très fonctionnelles et explicites. Si tu n'as pas essayé, je te le recommande fortement.

Reply

Marsh Posté le 24-04-2002 à 13:26:04    

oui je l'ai essayée mais pour l'instant je ne sais pas si j'en ai réellement besoin, tout réapprendre (car c'est bien le cas) m'apportera t il un plus ? Je suis tjrs dans cette interogation, je test des trucs par ci, par la ... je verrais bien :)

Reply

Marsh Posté le 24-04-2002 à 13:37:44    

Harkonnen a écrit a écrit :

Moi perso, depuis que j'ai découvert la plate-forme .NET et le C#, je me demande comment j'ai pu supporter les MFC aussi longtemps !
 
C'est vraiment un environnement génial pour développer, les classes fournies sont très fonctionnelles et explicites. Si tu n'as pas essayé, je te le recommande fortement.  




ben tu voie moi le C# c le contraire...


---------------
What butter and whiskey won't cure, there is no cure for.
Reply

Marsh Posté le 24-04-2002 à 17:10:45    

Salut
J'ai un autre problème : maintenant que je sais comment intercepter les events je voudrais
1 - Afficher ma dialog (en arrière plan) quand je clique sur l'icone en systray, et ShowWindow ni SetWindowPos ni SetWindowPlacement ne marchent !
2 - Afficher un menu quand je clique droit dur la tray icon : le menu est affiché mais quand je clique ailleurs à l'écran le menu reste ! DestroyMenu / DeleteMenu ne marchent pas !
 
Voila de quoi faire tenir le topic encore un peu ;-)

Reply

Marsh Posté le 24-04-2002 à 21:20:35    

Et me revoici à la rescousse, prêt à venir en aide à ceux qui galèrent avec les MFC :)
 
1 - Pour afficher ta fenêtre au double-clic, il faut que la fonction OnTrayMessage réagisse à ce double clic, donc au message WM_LBUTTONDBLCLK, qui est contenu dans lParam :
 
if (lParam == WM_LBUTTONDBLCLK) { // double clic
   ShowWindow(SW_SHOWNORMAL);
   SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
   SetActiveWindow();
}
 
Ce code devrait te permettre d'afficher ta fenêtre, mais à condition que la classe qui contient OnTrayMessage dérive d'une classe de fenêtre (CDialog dans le cas d'une boite de dialogue)
 
2 - Pour afficher un menu quand on clique sur le bouton droit (WM_RBUTTONDOWN), toujours dans OnTrayMessage() :
 
if (lParam == WM_RBUTTONDOWN) { // bouton droit
   CMenu menu;
   CPoint pt;
 
   menu.LoadMenu(IDR_MENU1);
   CMenu *m = menu.GetSubMenu(0);
   GetCursorPos(&pt);
   m->SetDefaultItem(0, TRUE);
 
   ::SetForegroundWindow(m_hWnd); //nécessaire, cause bug windows
   m->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON,  
   pt.x,
   pt.y,
   this);
   :: PostMessage(m_hWnd, WM_NULL, 0, 0);
}
 
IDR_MENU1 est l'ID de ressource de ton menu. Tu récupères dans m un pointeur vers la classe CMenu correspondante, et tu met l'item 0 de ce menu par défaut (il sera affiché en gras).
GetCursorPos() te permet de récupérer dans une structure Point les coordonnées de la souris au moment du clic.
Le SetForegroundWindow(m_hWnd) est nécessaire, car il corrige un bug de Windows. Enfin, tu affiches ton menu aux coordonnées de la souris récupérées précedemment via TrackPopupMenu, puis tu postes un message vierge à ta fenêtre, à cause du même bug de l'explorer de Windows.
 
Rien ne t'empêche de mixer ces 2 conditions, via un if .... else if.
 
Voila, je pense avoir été complet cette fois ci.  :D  
 
A+ :hello:

 

[jfdsdjhfuetppo]--Message édité par Harkonnen le 24-04-2002 à 21:21:33--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 25-04-2002 à 13:04:42    

Salut,
je vais tester ça ce soir et encore une fois merci ! Y a pas de raisons que ça ne marche pas.
je pense que c'est ça qui me manquait :
SetActiveWindow();
SetForegroundWindow(m_hWnd);
et le PostMessage(WM_NULL)
a+  :hello:

Reply

Marsh Posté le 25-04-2002 à 15:25:18    

L'autre jour je cherchais une idée de site à faire, je me demande si je ne vais pas faire un site dédié aux MFC.... :crazy:

Reply

Marsh Posté le 25-04-2002 à 17:08:24    

Ben c'est pas une mauvaise idée. Un truc du genre CodeGuru / CodeProject en Fr ?

Reply

Marsh Posté le 25-04-2002 à 18:19:11    

Euh, guru et project sont assez énormes :) J'aurais pas trop le temps de faire ce genre de site :lol:  
 
Je pensais plus à un site traitant des MFC, mais pas dans l'esprit de lafaqmfc.com, qui est très bien mais qui est très incomplet et qui aurait bien besoin d'une mise à jour sur certains points.
 
A creuser... Au fait, ça marche le code que je t'ai donné ?

Reply

Marsh Posté le 25-04-2002 à 20:33:31    

Im-pe-cable ! Merci grand chef  ;)  
Mais je cherche toujours une solution pour enlever de la barre des taches mon appli. J'en ai une mais qui me parait compliquée : il faut crée une dialog parente invisible et lui enlever WS_EX_APPWINDOW et ensuite créé une dialog fille et normalement ça marche. Mais bon c'est un peu le brodel ! A ton avis il y a une autre solution ?

Reply

Marsh Posté le 27-04-2002 à 12:10:25    

:bounce:

Reply

Marsh Posté le 27-04-2002 à 14:13:03    

La solution que tu possèdes est effectivement la seule solution correcte pour masquer la fenêtre. C'est celle préconisée par Microsoft, et je te recommande de l'utiliser.
 
Moi il m'arrive de faire comme ceci : je réagis au message WM_SIZE et je cache la fenêtre. Ceci implique que ta fenêtre principale ne soit pas redimensionnable et qu'elle possède un bouton d'iconification :
 
void CTaClasse:: OnSize(UINT nType, int cx, int cy)  
{
 CDialog:: OnSize(nType, cx, cy);
 
 // TODO: Add your message handler code here
 
 // On cache la fenetre si elle est iconifiée
 // pour ne pas l'avoir dans la barre des taches.
 // Pas tres propre mais ça fonctionne !!
 
 if(nType == SIZE_MINIMIZED) {
   
  ShowWindow(SW_HIDE);
   
  // on affiche l'icone du SysTray
 
  AfficheIconeSysTray();
 }
}
 
Comme je te le dis, ce n'est pas très propre. Je t'encourage donc à utiliser ta solution.
 
A+ :hello:

 

[jfdsdjhfuetppo]--Message édité par Harkonnen le 27-04-2002 à 14:13:40--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 28-04-2002 à 16:32:26    

C'est noté,
 :hello:

Reply

Marsh Posté le 26-01-2005 à 21:04:06    

Harkonnen a écrit :

Moi je fais comme ça, et ça marche très bien.
 
1 - Définir dans le source un message personnalisé :
 
#define WM_TRAYMESSAGE (WM_USER + 101)
 
2 - Rattacher ce message à la structure NOTIFYICONDATA de l'icone du SysTray (ni est une structure NOTIFYICONDATA):
 
ni.uCallbackMessage = WM_TRAYMESSAGE;
ni.uFlags = NIF_ICON | NIF_MESSAGE;

 
3 - Insérer ce message dans la MESSAGEMAP, en lui rattachant la fonction Callback OnTrayMessage() :
 
BEGIN_MESSAGE_MAP(CTaClasse, CParent)
  //{{AFX_MSG_MAP(CTaClasse)
  Messages de Windows, ne pas toucher à cette section
  //}}AFX_MSG_MAP
  ON_MESSAGE(WM_TRAYMESSAGE, OnTrayMessage)
END_MESSAGE_MAP()
 
4 - Implémenter la méthode OnTrayMessage() qui traitera le message :
 
LRESULT CTaClasse:: OnTrayMessage(WPARAM wParam, LPARAM lParam)
{
   if (lParam == WM_RBUTTONDOWN) { // bouton droit enfoncé
         //traitement si le bouton droit est enfoncé sur l'icone
   else if (lParam == WM_LBUTTONDBLCLK) { // double clic
         // traitement si dble clic sur l'icone
   }
   return 0;
}
 
Voila, c'est la manière propre de traiter les messages du SysTray.
 
A+  :hello:  
 
[jfdsdjhfuetppo]--Message édité par Harkonnen le 22-04-2002 à 20:00:03--[/jfdsdjhfuetppo]


 :hello:  
J'aimerai essayer cela mais je ne vois pas où mettre cette partie de code.

Code :
  1. ni.uCallbackMessage = WM_TRAYMESSAGE;
  2. ni.uFlags = NIF_ICON | NIF_MESSAGE;


je l'ai d'abord mise dans une bete fonction exécutée lors d'un click sur un bouton mais rien ne se produit. Ais-je oublié quelque chose?
 
Merci.

Reply

Marsh Posté le 26-01-2005 à 22:08:16    

ni c'est la structure que tu passes à Shell_NotifyIcon.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 27-01-2005 à 00:24:56    

Harkonnen a écrit :

L'autre jour je cherchais une idée de site à faire, je me demande si je ne vais pas faire un site dédié aux MFC.... :crazy:


Nan mais vade retro, quoi !

Reply

Marsh Posté le 27-01-2005 à 20:16:19    

HelloWorld a écrit :

ni c'est la structure que tu passes à Shell_NotifyIcon.


Et comment faut-il faire pour la "passer"?
je connais pas tres bien la Shell_NotifyIcon
 
MErci

Reply

Marsh Posté le 27-01-2005 à 21:16:02    

c'est le 2eme argument de Shell_Notifyicon() :spamafote:
 
http://msdn.microsoft.com/library/ [...] fyicon.asp
http://msdn.microsoft.com/library/ [...] ondata.asp


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 27-01-2005 à 21:17:31    

el muchacho a écrit :

Nan mais vade retro, quoi !


le tomic a 3 ans hein :o
('tain, c'est maintenant que je me rends compte que je suis une bête en MFC [:wam])


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 28-01-2005 à 16:51:25    

Harkonnen a écrit :

L'autre jour je cherchais une idée de site à faire, je me demande si je ne vais pas faire un site dédié aux MFC.... :crazy:


 
Il y avait un trés bon site, http://www.lafaqmfc.com/ . Mais il n'est plus publié.
Par chance, je l'avais récupéré, si ca intéresse qqu'un, je peux le mettre sur un ftp. (si c'et légal aussi, de remettre en ligne des pages qui ne sont plus dispos et qui sont pas à soi).

Reply

Marsh Posté le 28-01-2005 à 23:26:28    

L'auteur avait signalé qu'il allait suspendre le site, et avait demandé si quelqu'un était intéressé à la reprendre. Comme un c** j'ai oublié de copier le contenu du site avant que ce ne soit trop tard. Donc moi je veux bien que tu partages...:)


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 28-01-2005 à 23:56:15    

Reply

Marsh Posté le 29-01-2005 à 01:14:00    

:jap:


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 29-01-2005 à 11:15:01    

Reply

Marsh Posté le 29-01-2005 à 22:25:02    


 

Citation :


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 
    // Open window when double click to the Systray Icon
    if(message == MYWM_NOTIFYICON){
 
        switch (lParam){
 
            case WM_LBUTTONDBLCLK:
 
                switch (wParam) {
 
                    case IDR_TRAYICON:
 
                        ShowWindow(SW_NORMAL);
                        SetForegroundWindow();
                        SetFocus();
                        return TRUE;
 
                    break;
 
                }
 
            break;
 
        }
 
    }
 
    return CFrameWnd::WindowProc(message, wParam, lParam);
 
}


c'est particulièrement dégueulasse et anti objet comme méthode.... déjà que les MFC c'est pas le summum de l'objet...
je préfère 1000 fois ma méthode consistant à implémenter une callback pour intercepter le message


Message édité par Harkonnen le 29-01-2005 à 22:25:24

---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 30-01-2005 à 01:01:16    

Ca c'est la méthode d'un gars qui a trop fait de C Win32. C'est vrai que c'est pas trés objet, mais bon, qd on sait que c'est comme ca derrière...

Reply

Marsh Posté le 30-01-2005 à 16:45:02    

Harkonnen a écrit :

[quote]
c'est particulièrement dégueulasse et anti objet comme méthode.... déjà que les MFC c'est pas le summum de l'objet...
je préfère 1000 fois ma méthode consistant à implémenter une callback pour intercepter le message


Je n'ai pas réussi à implémenter la méthode que tu recommandes, je me suis donc rabattu sur celle là [:sinclaire]
 
Est-ce que qqun sait comment on peut afficher un menu quand on clique droit sur l'icone par exemple?

Reply

Marsh Posté le 30-01-2005 à 16:49:06    

polo021 a écrit :

Je n'ai pas réussi à implémenter la méthode que tu recommandes, je me suis donc rabattu sur celle là [:sinclaire]


c'est quoi qui te bloque :??:
 

polo021 a écrit :


Est-ce que qqun sait comment on peut afficher un menu quand on clique droit sur l'icone par exemple?


ben je l'explique dans ce topic ;)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 30-01-2005 à 17:00:27    

Harkonnen a écrit :

c'est quoi qui te bloque :??:


J'ai essayé et je n'ai pas réussi, je pense qu'il me manquait quelques détails. Le lien que j'ai donné est plus simple à comprendre pour qqun qui n'y connait rien (dommage que ce ne soit pas la meillleure méthode).

Harkonnen a écrit :


ben je l'explique dans ce topic ;)


Je vais essayer de trouver ca.


Message édité par polo021 le 30-01-2005 à 17:01:01
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed