none
balloon tips on tray icon on windows 7

    Question

  • hi all.
    i'm trying to do a simple method that show balloon tips on tray icon of my program.
    this seems to work on win xp, but nothing happen on windows 7.

    BOOL ShowBalloon(NOTIFYICONDATAA *pnidIconInfo, char *szBalloonTitle, char *szBalloonMsg, DWORD dwIcon, UINT nTimeOut){
      
        BOOL bBalloonShown = FALSE;
       
        if (pnidIconInfo != NULL){
            pnidIconInfo->dwInfoFlags = dwIcon;
        }
        else{
            return bBalloonShown; // We could not get the NOTIFYICONDATA
        }
       
        // Set the flags for showing balloon, espcially NIF_INFO
        pnidIconInfo->uFlags |= NIF_INFO;
       
        // Set the time out for the balloon
        pnidIconInfo->uTimeout = nTimeOut;

        // Set the balloon title
        strcpy(pnidIconInfo->szInfoTitle, szBalloonTitle);

        // Set balloon message
        strcpy(pnidIconInfo->szInfo, szBalloonMsg);

        // Show balloon....
        bBalloonShown = ::Shell_NotifyIconA(NIM_MODIFY, pnidIconInfo);
        bBalloonShown = Shell_NotifyIconA(NIN_BALLOONSHOW, pnidIconInfo);
           
        return bBalloonShown; 
    }

    any help would be appreciated.
    Saturday, December 05, 2009 3:31 PM

Answers

  • hi all.
    i'm trying to do a simple method that show balloon tips on tray icon of my program.
    this seems to work on win xp, but nothing happen on windows 7.

    BOOL ShowBalloon(NOTIFYICONDATAA *pnidIconInfo, char *szBalloonTitle, char *szBalloonMsg, DWORD dwIcon, UINT nTimeOut){
      
        BOOL bBalloonShown = FALSE;
       
        if (pnidIconInfo != NULL){
            pnidIconInfo->dwInfoFlags = dwIcon;
        }
        else{
            return bBalloonShown; // We could not get the NOTIFYICONDATA
        }
       
        // Set the flags for showing balloon, espcially NIF_INFO
        pnidIconInfo->uFlags |= NIF_INFO;
       
        // Set the time out for the balloon
        pnidIconInfo->uTimeout = nTimeOut;

        // Set the balloon title
        strcpy(pnidIconInfo->szInfoTitle, szBalloonTitle);

        // Set balloon message
        strcpy(pnidIconInfo->szInfo, szBalloonMsg);

        // Show balloon....
        bBalloonShown = ::Shell_NotifyIconA(NIM_MODIFY, pnidIconInfo);
        bBalloonShown = Shell_NotifyIconA(NIN_BALLOONSHOW, pnidIconInfo);
           
        return bBalloonShown; 
    }

    any help would be appreciated.

    There are several things I would change in the above code:

    1. There is a problem of const-correctness in your input string parameters szBalloonTitle and szBalloonMsg. You declared them as char*, but, considering that they are input strings, I would declare them as const char*.

    2. I would switch from ANSI/MBCS to Unicode (unless you have to target Windows 95/98...). So, I would use WCHAR* instead of char*.
    If you would like to make your code ANSI/MBCS-aware, you may use TCHAR (which exapnds to WCHAR in Unicode builds, and to char in ANSI/MBCS builds).

    So, combining 1. and 2. (considering that LPCTSTR == const TCHAR *), you could write:

    BOOL ShowBalloon(
       NOTIFYICONDATA *pnidIconInfo, 
       LPCTSTR *pszBalloonTitle, 
       LPCTSTR *pszBalloonMsg, 
       DWORD dwIcon, 
       UINT nTimeOut)
    

    3. You are using unsafe string functions like strcpy. You should instead use safe string functions, like StringCchCopy.
    Unsafe string functions open the code to security vulnerabilities.
    So, you could use code like this:

    // Set the balloon title
    StringCchCopy(nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle), pszBalloonTitle);
    
    // Set balloon message
    StringCchCopy(nid.szInfo, ARRAYSIZE(nid.szInfo), pszBalloonMsg);
    

    4. Considering 2., you should use SHELLNOTIFYICONDATA and Shell_NotifyIcon, instead of ANSI-only SHELLNOTIFYICONDATAA and Shell_NotifyIconA.


    There is a Win32/C++ sample project named NotificationIcon available both on Windows 7 SDK and online on CodeGallery, that shows how to use balloons.

    With VS2008 SP1 and Windows 7, I verified that this code works fine:

    BOOL ShowBalloon(LPCWSTR pszTitle, LPCWSTR pszText, DWORD dwIcon)
    {
        NOTIFYICONDATA nid = {sizeof(nid)};
        nid.uFlags = NIF_INFO | NIF_GUID;
        nid.guidItem = __uuidof(PrinterIcon);
        nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
        StringCchCopy(nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle), pszTitle);
        StringCchCopy(nid.szInfo, ARRAYSIZE(nid.szInfo), pszText);
        LoadIconMetric(g_hInst, MAKEINTRESOURCE(dwIcon), LIM_LARGE, &nid.hBalloonIcon);
        return Shell_NotifyIcon(NIM_MODIFY, &nid);
    }
    
    BOOL ShowPrintJobBalloon()
    {
        return ShowBalloon( L"Some title", L"Some text...", IDI_NOTIFICATIONICON );
    }
    


    Giovanni

    • Marked as answer by Wesley Yao Friday, December 11, 2009 4:04 AM
    Monday, December 07, 2009 12:07 PM

All replies

  • Have you set cbSize member of NOTIFYICONDATA to sizeof(NOTIFYICONDATA)? or you are using NOTIFYICONDATA_V3_SIZE.
    Saturday, December 05, 2009 3:41 PM
  • the first one...

    void InitNotifyIconData(HWND hDlg, NOTIFYICONDATAA *g_notifyIconData){

        g_notifyIconData->cbSize = sizeof(NOTIFYICONDATA);
        g_notifyIconData->hWnd = hDlg;
        g_notifyIconData->uID = IDI_TRAY_ICON;
        g_notifyIconData->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
        g_notifyIconData->uCallbackMessage = WM_TRAYICON;

        g_notifyIconData->hIcon = (HICON)LoadIcon(hInst, (LPCTSTR)IDI_SERVER);
        //g_notifyIconData.hIcon = (HICON)LoadImageA( NULL, "small.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE  ) ;
        strcpy(g_notifyIconData->szTip,"Server che non Server!");

    }
    Saturday, December 05, 2009 3:42 PM
  • none can help me? any link (except of msdn or codeguru)??? anything???
    Saturday, December 05, 2009 5:48 PM
  • I saw the same problem when was creating app under Vista in VS2008. Balloon doesn't appear, but simple tooltip was ok.
    After compiling under XP in VS2008, balloon appeard both under Vista and XP.
    I tried many ways, but nothing helped =)

    I used code like this:

    NOTIFYICONDATA nid = {0};
    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.hWnd = hWnd;
    nid.uFlags = NIF_ICON | NIF_INFO;
    wcscpy_s(nid.szInfo, 256, L"Info");
    wcscpy_s(nid.szInfoTitle, 64, L"Title");
    nid.dwInfoFlags = NIIF_INFO;
    nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    Shell_NotifyIcon(NIM_ADD, &nid);

    Maybe we need to perform some trick. Very interesting.
    Saturday, December 05, 2009 5:53 PM
  • i think the shelObj version is the issue.pls refer Stdafx.h for shell version linking. Windows version for Vista is 
    _WIN32_WINNT is 0x0600
    Monday, December 07, 2009 10:00 AM
  • the first one...

    void InitNotifyIconData(HWND hDlg, NOTIFYICONDATAA *g_notifyIconData){

        g_notifyIconData->cbSize = sizeof(NOTIFYICONDATA);
        g_notifyIconData->hWnd = hDlg;
        g_notifyIconData->uID = IDI_TRAY_ICON;
        g_notifyIconData->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
        g_notifyIconData->uCallbackMessage = WM_TRAYICON;

        g_notifyIconData->hIcon = (HICON)LoadIcon(hInst, (LPCTSTR)IDI_SERVER);
        //g_notifyIconData.hIcon = (HICON)LoadImageA( NULL, "small.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE  ) ;
        strcpy(g_notifyIconData->szTip,"Server che non Server!");

    }

    I think that you may have a problem in setting structure size.

    In fact, you passed a pointer to NOTIFYICONDATAA, but you set the pointed structure size to sizeof(NOTIFYICONDATA), not NOTIFYICONDATAA.
    This would work fine only for (obsolete and deprecated, IMHO), ANSI/MBCS builds.
    In fact, in Unicode builds (which are the default in modern versions of Visual Studio, like VS2005 and VS2008), NOTIFYICONDATA would be interpreted as NOTIFYICONDATAW, whose size is different from NOTIFYICONDATAA.

    Giovanni


    Monday, December 07, 2009 11:47 AM
  • the first one...

    void InitNotifyIconData(HWND hDlg, NOTIFYICONDATAA *g_notifyIconData){

        g_notifyIconData->cbSize = sizeof(NOTIFYICONDATA);
        g_notifyIconData->hWnd = hDlg;
        g_notifyIconData->uID = IDI_TRAY_ICON;
        g_notifyIconData->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
        g_notifyIconData->uCallbackMessage = WM_TRAYICON;

        g_notifyIconData->hIcon = (HICON)LoadIcon(hInst, (LPCTSTR)IDI_SERVER);
        //g_notifyIconData.hIcon = (HICON)LoadImageA( NULL, "small.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE  ) ;
        strcpy(g_notifyIconData->szTip,"Server che non Server!");

    }

    BTW: In addition to what I wrote previously, I'd like to add that your use of Hungarian Notation is not quite standard...
    I mean, usually, the g_ prefix identifies a global variable. If you pass a pointer as function parameter, I would name it something like pNotifyIconData, instead of g_notifyIconData.

    Giovanni

    Monday, December 07, 2009 11:50 AM
  • hi all.
    i'm trying to do a simple method that show balloon tips on tray icon of my program.
    this seems to work on win xp, but nothing happen on windows 7.

    BOOL ShowBalloon(NOTIFYICONDATAA *pnidIconInfo, char *szBalloonTitle, char *szBalloonMsg, DWORD dwIcon, UINT nTimeOut){
      
        BOOL bBalloonShown = FALSE;
       
        if (pnidIconInfo != NULL){
            pnidIconInfo->dwInfoFlags = dwIcon;
        }
        else{
            return bBalloonShown; // We could not get the NOTIFYICONDATA
        }
       
        // Set the flags for showing balloon, espcially NIF_INFO
        pnidIconInfo->uFlags |= NIF_INFO;
       
        // Set the time out for the balloon
        pnidIconInfo->uTimeout = nTimeOut;

        // Set the balloon title
        strcpy(pnidIconInfo->szInfoTitle, szBalloonTitle);

        // Set balloon message
        strcpy(pnidIconInfo->szInfo, szBalloonMsg);

        // Show balloon....
        bBalloonShown = ::Shell_NotifyIconA(NIM_MODIFY, pnidIconInfo);
        bBalloonShown = Shell_NotifyIconA(NIN_BALLOONSHOW, pnidIconInfo);
           
        return bBalloonShown; 
    }

    any help would be appreciated.

    There are several things I would change in the above code:

    1. There is a problem of const-correctness in your input string parameters szBalloonTitle and szBalloonMsg. You declared them as char*, but, considering that they are input strings, I would declare them as const char*.

    2. I would switch from ANSI/MBCS to Unicode (unless you have to target Windows 95/98...). So, I would use WCHAR* instead of char*.
    If you would like to make your code ANSI/MBCS-aware, you may use TCHAR (which exapnds to WCHAR in Unicode builds, and to char in ANSI/MBCS builds).

    So, combining 1. and 2. (considering that LPCTSTR == const TCHAR *), you could write:

    BOOL ShowBalloon(
       NOTIFYICONDATA *pnidIconInfo, 
       LPCTSTR *pszBalloonTitle, 
       LPCTSTR *pszBalloonMsg, 
       DWORD dwIcon, 
       UINT nTimeOut)
    

    3. You are using unsafe string functions like strcpy. You should instead use safe string functions, like StringCchCopy.
    Unsafe string functions open the code to security vulnerabilities.
    So, you could use code like this:

    // Set the balloon title
    StringCchCopy(nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle), pszBalloonTitle);
    
    // Set balloon message
    StringCchCopy(nid.szInfo, ARRAYSIZE(nid.szInfo), pszBalloonMsg);
    

    4. Considering 2., you should use SHELLNOTIFYICONDATA and Shell_NotifyIcon, instead of ANSI-only SHELLNOTIFYICONDATAA and Shell_NotifyIconA.


    There is a Win32/C++ sample project named NotificationIcon available both on Windows 7 SDK and online on CodeGallery, that shows how to use balloons.

    With VS2008 SP1 and Windows 7, I verified that this code works fine:

    BOOL ShowBalloon(LPCWSTR pszTitle, LPCWSTR pszText, DWORD dwIcon)
    {
        NOTIFYICONDATA nid = {sizeof(nid)};
        nid.uFlags = NIF_INFO | NIF_GUID;
        nid.guidItem = __uuidof(PrinterIcon);
        nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
        StringCchCopy(nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle), pszTitle);
        StringCchCopy(nid.szInfo, ARRAYSIZE(nid.szInfo), pszText);
        LoadIconMetric(g_hInst, MAKEINTRESOURCE(dwIcon), LIM_LARGE, &nid.hBalloonIcon);
        return Shell_NotifyIcon(NIM_MODIFY, &nid);
    }
    
    BOOL ShowPrintJobBalloon()
    {
        return ShowBalloon( L"Some title", L"Some text...", IDI_NOTIFICATIONICON );
    }
    


    Giovanni

    • Marked as answer by Wesley Yao Friday, December 11, 2009 4:04 AM
    Monday, December 07, 2009 12:07 PM
  • Giovanni, thanks for the WinAPI sample. Will check it. Interesting problem =)
    Monday, December 07, 2009 1:05 PM
  • Nikita: you are welcome.

    I think that the Windows team did a great job in offering quality C++/Win32 sample code in the Windows 7 SDK.
    (I consider these sample codes a fundamental integration of the MSDN documentation.)

    Giovanni

    Monday, December 07, 2009 3:26 PM
  • Checked. This sample also doesn't work when compiled under Vista.
    Very strange.
    Monday, December 07, 2009 8:28 PM
  • Checked. This sample also doesn't work when compiled under Vista.
    Very strange.

    Probably because the sample uses Windows 7-only features, like guidItem field of NOTIFYICONDATA.

    Giovanni

    Monday, December 07, 2009 11:08 PM