Display a System Tray Icon in VC++

Discussion in 'MFC' started by shabbir, Jun 3, 2005.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Create a Dialog based application and add a menu.

    First you need to declare some variables in the the header file of your Dialog.
    Code:
      #define MYWM_NOTIFYICON (WM_USER+1)
      //User defined messages. 
      
      CMenu m_TrayMenu;
      //Displaying menu when right clicked on the system tray. Should be inside the class definition
      
      NOTIFYICONDATA tnd;
      //Icon Data
      
      afx_msg LRESULT onTrayNotify(WPARAM, LPARAM);
      //Function to handle the user messages
      
    Now put the following code in the OnInitDialog function
    Code:
      CString sTip(_T("Hello System Tray")); 
      
      tnd.cbSize = sizeof(NOTIFYICONDATA);
      tnd.hWnd = this->GetSafeHwnd();;
      tnd.uID = IDR_MAINFRAME;
      //ICON RESOURCE ID
      tnd.uFlags = NIF_MESSAGE|NIF_ICON;
      tnd.uCallbackMessage = MYWM_NOTIFYICON;
      tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; 
      tnd.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDR_MAINFRAME));
      //ICON RESOURCE ID
      lstrcpyn(tnd.szTip, (LPCTSTR)sTip, sizeof(tnd.szTip));
      
      DWORD dwMessage = NIM_ADD;
      Shell_NotifyIcon(dwMessage, &tnd);	
      
      m_TrayMenu.LoadMenu(IDR_MENU);
      //MENU RESOURCE ID.
      
    Add user-defined message handler
    Code:
      ON_MESSAGE(MYWM_NOTIFYICON,onTrayNotify)
      
    Now define the body of onTrayNotify as follows
    Code:
      LRESULT CWallpaperDlg::onTrayNotify(WPARAM wParam,LPARAM lParam)
      {
        UINT uMsg = (UINT) lParam; 
        switch (uMsg ) 
        { 
        case WM_LBUTTONDBLCLK:
      	this->ShowWindow(SW_SHOW);
      	break;
        case WM_RBUTTONUP:
      	CPoint pt;	
      	GetCursorPos(&pt);
     	m_TrayMenu.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);
      	break;
        } 
        return TRUE;
      }
      
    Now if you want to add the functionality that whenever someone hits the cross it should be minimized to the system tray then add the WM_CLOSE event handler and remove the call to the CDialog::OnClose(); and add the following code.
    Code:
      ShowWindow(SW_HIDE);
      
    Now in the WM_DESTROY message of the dialog add the following lines to delete the icon from the system tray and clean up the tray.
    Code:
      Shell_NotifyIcon(NIM_DELETE,&tnd);
      
    The sample application has been done in VC++ 7.1 compiler and if you wish to transfer that and view them in older version 7.0 then you need to do the following
     

    Attached Files:

  2. AhmedHan

    AhmedHan New Member

    Joined:
    Oct 11, 2005
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    Home Page:
    http://www.stirve.com
    One more thing...

    Don't forget to define
    #define _WIN32_WINNT 0x0501
    before including "windows.h" file.
     
  3. sanjoy.saha@hcl.in

    sanjoy.saha@hcl.in New Member

    Joined:
    Feb 18, 2007
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    can u tell me why is this done as i am new to VC++
     
  4. AhmedHan

    AhmedHan New Member

    Joined:
    Oct 11, 2005
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    Home Page:
    http://www.stirve.com
    Because some of the features of API functions and structures are defined for specific Windows versions or highers.

    For example :
    Code:
    	//shellapi.h
        	typedef struct _NOTIFYICONDATAA {
        	DWORD cbSize;
        	HWND hWnd;
        	UINT uID;
        	UINT uFlags;
        	UINT uCallbackMessage;
        	HICON hIcon;
        #if _WIN32_IE >= 0x0500
        	CHAR szTip[128];
        	DWORD dwState;
        	DWORD dwStateMask;
        	CHAR szInfo[256];
        	_ANONYMOUS_UNION union {
        		UINT uTimeout;
        		UINT uVersion;
        	} DUMMYUNIONNAME;
        	CHAR szInfoTitle[64];
        	DWORD dwInfoFlags;
        #else
        	CHAR szTip[64];
        #endif
        #if _WIN32_IE >= 0x600
        	GUID guidItem;
        #endif
        } NOTIFYICONDATAA,*PNOTIFYICONDATAA;
    As you see, as the constant _WIN32_IE has higher values, higher features are enabled.
    [​IMG] [​IMG] [​IMG]

    From MSDN :
    Code:
    Windows Server 2003 family            _WIN32_WINNT>=0x0502
      Windows XP                            _WIN32_WINNT>=0x0501
      Windows 2000                        _WIN32_WINNT>=0x0500
      Windows NT 4.0                        _WIN32_WINNT>=0x0400
      Windows Me                            _WIN32_WINDOWS=0x0490
      Windows 98                            _WIN32_WINDOWS>=0x0410
      Internet Explorer 6.0                _WIN32_IE>=0x0600
      Internet Explorer 5.01, 5.5            _WIN32_IE>=0x0501
      Internet Explorer 5.0, 5.0a, 5.0b    _WIN32_IE>=0x0500
      Internet Explorer 4.01                _WIN32_IE>=0x0401
      Internet Explorer 4.0                _WIN32_IE>=0x0400
      Internet Explorer 3.0, 3.01, 3.02    _WIN32_IE>=0x0300
     
  5. Gopinath

    Gopinath New Member

    Joined:
    Jun 24, 2006
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Hi,

    i did this application in VC++6.0, but i want to display the balloon tool tips for my system tray icon, i know how to do this. when i'm working in version 6.0 its giving errors as

    error C2039: 'uTimeout' : is not a member of '_NOTIFYICONDATAA'
    error C2039: 'dwInfoFlags' : is not a member of '_NOTIFYICONDATAA'
    erro C2039: 'szInfo' : is not a member of '_NOTIFYICONDATAA'
    .....
    ....


    but when i did the another application application for system tray icon in VC++.Net then it runs perfectly and the system tray icons shows the balloon tips.

    i know its due to the shellapi.h version with respective to the os.
    now my question is how can i made VC++6.0 use the latest version of shellapi.h and able to display the balloon tool tips in my application.

    please help me to solve this.
    Thanks in advance.

    -Gopinath
     
  6. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Change the header file path in the project settings.
     
  7. 2MuchRiceMakesMeSick

    2MuchRiceMakesMeSick New Member

    Joined:
    Aug 5, 2007
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Can someone walk me though the part Add user-defined message handler
    I am still learning VC and im familiar with the MFC ClassWizard but where do I go from there?
     
  8. 2MuchRiceMakesMeSick

    2MuchRiceMakesMeSick New Member

    Joined:
    Aug 5, 2007
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    im using VC++ 6.0 also
     
  9. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    You need to add the code in the Message Map. In Dialog based application you will find that in the Dialog cpp file. Find the MESSAGE_MAP there.
     
  10. 2MuchRiceMakesMeSick

    2MuchRiceMakesMeSick New Member

    Joined:
    Aug 5, 2007
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Thanks. Now its saying that it cant find m_TrayMenu
    I havent defined a Member Variable called m_TrayMenu is obviously why
    But I cant because there is no Menu Control IDs in the wizard.
    I did add a IDR_MENU1 by right clicking NEW MENU. Why is it not showing up under the MFC Class Wizard? Or am I doing it wrong?

    Thanks for the help...
     
  11. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Why don't you download the code and try running it. I see you should have the IDR_MENU and not IDR_MENU1 but I could not get what you meant by
     
  12. parvez.yu

    parvez.yu New Member

    Joined:
    Feb 14, 2008
    Messages:
    100
    Likes Received:
    0
    Trophy Points:
    0
    what is system tray icon
     
  13. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    The Icon you see in the bottom right corner
     
  14. parvez.yu

    parvez.yu New Member

    Joined:
    Feb 14, 2008
    Messages:
    100
    Likes Received:
    0
    Trophy Points:
    0
    oh ok thanks shabbir
     
  15. torussxl

    torussxl New Member

    Joined:
    Mar 30, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    I followed the instructions for the system icon, and my app is able to get one to show up...however the icon disappears as soon as the mouse hovers over it. So obviously the tooltip and the right-click menu cannot be activated.

    What am I possibly doing wrong? I followed the instructions almost verbatim. I'm using Windows XP pro and Visual Studio 2005 version 8.

    Thanks for any help.
     
  16. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Your Exe is dying and so the Icon is disappearing.
     
  17. funativi

    funativi New Member

    Joined:
    Apr 8, 2009
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    I want to enable / disable menu items insystem trya. How cam I do it?
     
  18. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Disabling the menu item would be same for Normal Menu or for Any Windows control. There is an API EnableWindow and I think that should do it for you
     
  19. funativi

    funativi New Member

    Joined:
    Apr 8, 2009
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    I have tried it, but it does not work, I debugged the code and I found that update handler is called before oncommand.
     
  20. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    It does work for me ?
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice