Newsgroup: it.comp.lang.c++
Titolo: Popup menu da una icona nella tray.

Ciao a tutti !
Sto scrivendo un piccolo programma che inserisce un'icona nella Tray e
visualizza un popmenu quando
si clicca su di essa.
Il mio problema è che il popup, una volta visualizzato,  non si chiude
semplicemente cliccando da qualche altra parte fuori dall'area menu, ma
scompare solo al successivo passaggio del mouse sull' area dello stesso
menu........ inoltre non sempre si attiva al primo click. ( Le stesse
funzioni usate per attivare un pop up menu cliccando sull'area della
finestra funzionano perfettamente........ )
Spero di essere stato comprensibile......... :-)
Grazie mille a chiunque volesse aiutarmi!
/***************************************************************************
*****************************
 Function prototypes
****************************************************************************
****************************/
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM );
BOOL ModifyTrayIcon( HWND, UINT, UINT, DWORD, int);
VOID TrayIconPopUpMenu (HWND hWnd, HINSTANCE hInst, POINT pt);
/***************************************************************************
*****************************
 Global variables
****************************************************************************
****************************/
HANDLE hInst;
........................
/***************************************************************************
*****************************
 WndProc
****************************************************************************
****************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam )
 POINT pt;
 switch (uMsg)
  case WM_CREATE:
   ModifyTrayIcon(hWnd,WM_COMMAND,TRAY_ICON,NIM_ADD, EAGLE_ICON);
   break;
   .............
  case WM_COMMAND:
   switch ( wParam ) {
    case TRAY_ICON:
     if( lParam == WM_RBUTTONDOWN ) {
      GetCursorPos(&pt);
      TrayIconPopUpMenu (hWnd, hInst,pt);
      }
     break;
    ...............
}
/***************************************************************************
*****************************
 ModifyTrayIcon
****************************************************************************
****************************/
BOOL ModifyTrayIcon( HWND hWnd, UINT msg, UINT uID, DWORD dwType, int
iIcon )
{
 NOTIFYICONDATA nid;
 memset( &nid, 0, sizeof(NOTIFYICONDATA) );
 nid.cbSize = sizeof(NOTIFYICONDATA);
 nid.hWnd = hWnd;
 nid.uID = uID;
 nid.uFlags = NIF_ICON | NIF_MESSAGE;
 nid.uCallbackMessage = msg;
 nid.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(1000));
 Shell_NotifyIcon( dwType, &nid );
 return TRUE;
}
/***************************************************************************
*****************************
 TrayIconPopUpMenu
****************************************************************************
****************************/
VOID TrayIconPopUpMenu (HWND hWnd, HINSTANCE hInst, POINT pt)
{
    HMENU hMenu;
    HMENU hMenuTrackPopup;
    hMenu = LoadMenu(hInst, "POPUPMENU");
    hMenuTrackPopup = GetSubMenu(hMenu, 0);
    TrackPopupMenu (hMenuTrackPopup, 0 ,pt.x,pt.y,0, hWnd,NULL);
    DestroyMenu(hMenu);
}
Pippo.

Anch'io ho avuto il problema della chiusura del menu, e non l'ho risolto.
Comunque anche alcuni programmi in commercio hanno questo problema; ad
esempio PC-Chillin ce l'ha, mentre altri come gli applicativi Matrox o
GetRight no. Non ho mai avuto comunque l'altro problema che descrivi. Ad
ogni modo mi sembra che tu faccia un passaggio di troppo nel tuo codice;
infatti non c'è bisogno di intercettare WM_COMMAND. Basta definire un
messaggio personalizzato, ad esempio con: #define WM_TRAY   WM_USER (gli id
da WM_USER fino a 0x7FFF sono liberamente utilizzabili), passarlo a
nid.uCallbackMessage e intercettarlo nella winproc; non so se sia questo a
determinare il problema, comunque, provare non ti costa niente. Anche il
caricamento al volo del menu potrebbe esserne la causa; potresti quindi
provare a caricarlo in WM_CREATE e distruggerlo in WM_DESTROY ricordandoti
di usare un HMENU globale o (se non globale) statico. Tutto questo per
ridurre al minimo l'elaborazione di WM_TRAY. In questo modo, io non ho
avuto problemi, se non quello della chiusura.
Esempio:
#define WM_TRAY      WM_USER
// WinProc
case WM_CREATE:
 .
 .
 // Carica menu
 // Ottieni submenu
 .
 .
return 0;
case WM_TRAY:
 switch(lParam)
 {
  case WM_RBUTTONDOWN:
   GetCursorPos(...);
   TrackPopupMenu(...);
  break;
 }
return 0;
case WM_DESTROY:
.
.
 // Distruggi menu
.
.
return 0;
Stefano.


Non so se e` il tuo caso (al momento non posso verificare
il tuo codice), ma so per certo che bisogna effettuare una chiamata
a SetForegroundWindow prima e dopo la chiamata a TrackPopupMenu
altrimenti il menu` rimane parzialmente visibile anche dopo un click.
Sembra trattasi di un bug di windows, la cosa e` comunque nota
almeno dall'inizio del 96.
Paolo

Se vi guardate l'esempio su CODE GURU vi viene facile e
perfettamente standard secondo Microsoft
L'ho provato e fatto anche se novellino.
                                   Valentino
----------------------------------------------------------
PS: se volete maggiori informazioni su  quale code
scrivetemi.
