Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. BIG trouble with 64-bit Shell_NotifyIcon() - can anyone help?

BIG trouble with 64-bit Shell_NotifyIcon() - can anyone help?

Scheduled Pinned Locked Moved C / C++ / MFC
c++helpwpfcomlinux
10 Posts 2 Posters 4 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    Tacitonitus
    wrote on last edited by
    #1

    Hi Everyone.. I very rarely ask programming-specific questions in public forums, but this one has me completely stumped. I just can't seem to get the Windows Native API function, "Shell_NotifyIcon" to work, no matter what I try. This is the Windows API function that enables an application to add its "Icon" to the Windows System Tray, aka: the "System Notification Area", and then enables it to pop up "notifications", etc.. At least, in theory.. No matter what I try however, this function always fails in my app. And when I call the GetLastError() function to try to determine what was allegedly wrong with the call, sometimes I'll get a "timeout" error (whatever that means), sometimes I'll get an "invalid window handle" (but the handle's perfectly valid), and other times the call will actually succeed, but the very next call will fail with the same variable results.. I'm compiling in Windows 64-bit using Visual C++ Express, BTW.. I've tried calling both the ANSI and Unicode versions of this function and get the same results. I've tried specifying different "versions" to this function (it's a parameter), and I get the same results. I've tried compiling both with and without "enabling Visual Styles", but, you guessed it, same results.. And I've looked at all the sample code on the Internet that uses this function, including most of the code on this site, and without exception, none of the code I've looked at is doing anything more than my own code is doing.. Which is all, needless to say, exceedingly frustrating.. My app also changes its own execution priority, so I took that out to see if it would make a difference - it didn't.. I also came across an excellent article on Shell_NotifyIcon on the Internet: "The trouble with Shell_NotifyIcon()"] So I implemented a retry count, as he suggested. Unfortunately, the only difference that made was that I had to wait four seconds before I could see it fail (yet again).. The methodology involved is this: my Main Dialog Box's WM_INITDIALOG message handler calls this:

    #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
    #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

    #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

    static NOTIFYICONDATA *NID;

    static void Init_NID( HWND hDlg )
    {
    if ( NID = new NOTIFYICONDATA )
    {
    memset( NID, 0, sizeof( NOTIFYICONDATA ) );

         if ( LoadIconMetric(
    
    F 1 Reply Last reply
    0
    • T Tacitonitus

      Hi Everyone.. I very rarely ask programming-specific questions in public forums, but this one has me completely stumped. I just can't seem to get the Windows Native API function, "Shell_NotifyIcon" to work, no matter what I try. This is the Windows API function that enables an application to add its "Icon" to the Windows System Tray, aka: the "System Notification Area", and then enables it to pop up "notifications", etc.. At least, in theory.. No matter what I try however, this function always fails in my app. And when I call the GetLastError() function to try to determine what was allegedly wrong with the call, sometimes I'll get a "timeout" error (whatever that means), sometimes I'll get an "invalid window handle" (but the handle's perfectly valid), and other times the call will actually succeed, but the very next call will fail with the same variable results.. I'm compiling in Windows 64-bit using Visual C++ Express, BTW.. I've tried calling both the ANSI and Unicode versions of this function and get the same results. I've tried specifying different "versions" to this function (it's a parameter), and I get the same results. I've tried compiling both with and without "enabling Visual Styles", but, you guessed it, same results.. And I've looked at all the sample code on the Internet that uses this function, including most of the code on this site, and without exception, none of the code I've looked at is doing anything more than my own code is doing.. Which is all, needless to say, exceedingly frustrating.. My app also changes its own execution priority, so I took that out to see if it would make a difference - it didn't.. I also came across an excellent article on Shell_NotifyIcon on the Internet: "The trouble with Shell_NotifyIcon()"] So I implemented a retry count, as he suggested. Unfortunately, the only difference that made was that I had to wait four seconds before I could see it fail (yet again).. The methodology involved is this: my Main Dialog Box's WM_INITDIALOG message handler calls this:

      #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
      #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

      #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

      static NOTIFYICONDATA *NID;

      static void Init_NID( HWND hDlg )
      {
      if ( NID = new NOTIFYICONDATA )
      {
      memset( NID, 0, sizeof( NOTIFYICONDATA ) );

           if ( LoadIconMetric(
      
      F Offline
      F Offline
      Frankie C
      wrote on last edited by
      #2

      From code you posted it seems very improbable to me that it can work with memory dynamically allocated (new) for NOTIFYICONDAT. This memory is released when sub exits, while it is not reused may happen that it works, as soon it is reused and filled with data making nosense for IconNotify it will not work anymore. The problem you mentioned is related only to services and program that starts before desktop (iexplorer) is started (that is the case of utilities wrote by the author of article you mentioned). In that case the solution is to wait for initialization to complete. You will find all info, if you need, here[^]. Making it static and changing the access to its members it works for me. This is the amended code:

      #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

      static BOOL Opning = TRUE;

      static NOTIFYICONDATA NID;

      static void Init_NID( HWND hDlg )
      {
      //if ( NID = new NOTIFYICONDATA )
      //{
      memset( &NID, 0, sizeof( NOTIFYICONDATA ) );

           if ( LoadIconMetric( AppInst,
                                (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                LIM\_SMALL, &NID.hIcon ) == S\_OK )
           {
                if ( LoadIconMetric( AppInst,
                                     (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                     LIM\_SMALL, &NID.hBalloonIcon ) == S\_OK )
                {
                     strcpy( NID.szTip, "My App Name" );
                     strcpy( NID.szInfoTitle, "Hi There" );
                     strcpy( NID.szInfo, "My notification message.." );
      
                     if ( Opning )
                     {
                          NID.uTimeout = 5000;
                          NID.uID = TRAY\_ICON\_ID;
                          NID.dwInfoFlags = NIIF\_USER;
                          NID.uCallbackMessage = MSG\_FROM\_TRAY;
                          NID.cbSize = sizeof( NOTIFYICONDATA );
                          NID.dwState = 0;
                          NID.dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
      
                          return;
                     }
      
                     DestroyIcon( NID.hBalloonIcon );
                }
      
                DestroyIcon( NID.hIcon );
           }
      
           //delete NID;
           //NID = NULL;
      //}
      

      }

      static BOOL Min2SysTray( HWND hDlg )
      {

      T 1 Reply Last reply
      0
      • F Frankie C

        From code you posted it seems very improbable to me that it can work with memory dynamically allocated (new) for NOTIFYICONDAT. This memory is released when sub exits, while it is not reused may happen that it works, as soon it is reused and filled with data making nosense for IconNotify it will not work anymore. The problem you mentioned is related only to services and program that starts before desktop (iexplorer) is started (that is the case of utilities wrote by the author of article you mentioned). In that case the solution is to wait for initialization to complete. You will find all info, if you need, here[^]. Making it static and changing the access to its members it works for me. This is the amended code:

        #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

        static BOOL Opning = TRUE;

        static NOTIFYICONDATA NID;

        static void Init_NID( HWND hDlg )
        {
        //if ( NID = new NOTIFYICONDATA )
        //{
        memset( &NID, 0, sizeof( NOTIFYICONDATA ) );

             if ( LoadIconMetric( AppInst,
                                  (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                  LIM\_SMALL, &NID.hIcon ) == S\_OK )
             {
                  if ( LoadIconMetric( AppInst,
                                       (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                       LIM\_SMALL, &NID.hBalloonIcon ) == S\_OK )
                  {
                       strcpy( NID.szTip, "My App Name" );
                       strcpy( NID.szInfoTitle, "Hi There" );
                       strcpy( NID.szInfo, "My notification message.." );
        
                       if ( Opning )
                       {
                            NID.uTimeout = 5000;
                            NID.uID = TRAY\_ICON\_ID;
                            NID.dwInfoFlags = NIIF\_USER;
                            NID.uCallbackMessage = MSG\_FROM\_TRAY;
                            NID.cbSize = sizeof( NOTIFYICONDATA );
                            NID.dwState = 0;
                            NID.dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
        
                            return;
                       }
        
                       DestroyIcon( NID.hBalloonIcon );
                  }
        
                  DestroyIcon( NID.hIcon );
             }
        
             //delete NID;
             //NID = NULL;
        //}
        

        }

        static BOOL Min2SysTray( HWND hDlg )
        {

        T Offline
        T Offline
        Tacitonitus
        wrote on last edited by
        #3

        Apologies. I made a mistake in transcribing the original code. Which actually has nothing to do with why this code still doesn't work - just to be clear. In the original code, the NID->szTip, NID->szInfoTitle, and NID->szInfo structure members are not initialized by strcpy(). I changed it to a bunch of strcpy() calls to "simplify" the code (to make it easier to read).. They are initialized in the original code by a function call whose return value sets an auto bool called, "Opning". When I substituted out that function call for those strcpy() calls (for simplicity), I also (erroneously) took out the "bool Opning =" part. My bad. To make a long story short, the following is a far more correct "transcription" of the existing code:

        #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
        #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

        #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

        static NOTIFYICONDATA *NID;

        static void Init_NID( HWND hDlg )
        {
        if ( NID = new NOTIFYICONDATA )
        {
        memset( NID, 0, sizeof( NOTIFYICONDATA ) );

             if ( LoadIconMetric( AppInst,
                                  (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                  LIM\_SMALL, &NID->hIcon ) == S\_OK )
             {
                  if ( LoadIconMetric( AppInst,
                                       (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                       LIM\_SMALL, &NID->hBalloonIcon ) == S\_OK )
                  {
                       bool Opning;
        
                       if ( Opning = LoadStrings( NID->szTip,
                                                  NID->szInfo,
                                                  NID->szInfoTitle ) )
                       {
                            NID->uTimeout = 5000;
                            NID->uID = TRAY\_ICON\_ID;
                            NID->dwInfoFlags = NIIF\_USER;
                            NID->uCallbackMessage = MSG\_FROM\_TRAY;
                            NID->cbSize = sizeof( NOTIFYICONDATA );
                            NID->dwState = 0;
                            NID->dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
        
                            return;   // <== i.e. RETURN to caller w/ NID != NULL..
                       }
        
                       DestroyIcon( NID->hBalloonIcon );
                  }
        
                  DestroyIcon( NID->hIcon );
             }
        
             delete NID;
             NID = NULL;
        }
        

        }

        Again, sorry for

        F 2 Replies Last reply
        0
        • T Tacitonitus

          Apologies. I made a mistake in transcribing the original code. Which actually has nothing to do with why this code still doesn't work - just to be clear. In the original code, the NID->szTip, NID->szInfoTitle, and NID->szInfo structure members are not initialized by strcpy(). I changed it to a bunch of strcpy() calls to "simplify" the code (to make it easier to read).. They are initialized in the original code by a function call whose return value sets an auto bool called, "Opning". When I substituted out that function call for those strcpy() calls (for simplicity), I also (erroneously) took out the "bool Opning =" part. My bad. To make a long story short, the following is a far more correct "transcription" of the existing code:

          #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
          #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

          #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

          static NOTIFYICONDATA *NID;

          static void Init_NID( HWND hDlg )
          {
          if ( NID = new NOTIFYICONDATA )
          {
          memset( NID, 0, sizeof( NOTIFYICONDATA ) );

               if ( LoadIconMetric( AppInst,
                                    (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                    LIM\_SMALL, &NID->hIcon ) == S\_OK )
               {
                    if ( LoadIconMetric( AppInst,
                                         (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                         LIM\_SMALL, &NID->hBalloonIcon ) == S\_OK )
                    {
                         bool Opning;
          
                         if ( Opning = LoadStrings( NID->szTip,
                                                    NID->szInfo,
                                                    NID->szInfoTitle ) )
                         {
                              NID->uTimeout = 5000;
                              NID->uID = TRAY\_ICON\_ID;
                              NID->dwInfoFlags = NIIF\_USER;
                              NID->uCallbackMessage = MSG\_FROM\_TRAY;
                              NID->cbSize = sizeof( NOTIFYICONDATA );
                              NID->dwState = 0;
                              NID->dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
          
                              return;   // <== i.e. RETURN to caller w/ NID != NULL..
                         }
          
                         DestroyIcon( NID->hBalloonIcon );
                    }
          
                    DestroyIcon( NID->hIcon );
               }
          
               delete NID;
               NID = NULL;
          }
          

          }

          Again, sorry for

          F Offline
          F Offline
          Frankie C
          wrote on last edited by
          #4

          I see, I have misinterpreted the usage of new in your code. What I mean is that I compiled a sample with a C (not C++) compiler and it works for me. The only problem I found compiling the code in 64bits is that a manifest resource is required. This is my full sample:

          #define WIN32_LEAN_AND_MEAN
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include "main.h"

          #define NELEMS(a) (sizeof(a) / sizeof((a)[0]))

          static INT_PTR CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);

          #define AppInst ghInstance
          static HANDLE ghInstance;

          #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
          #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

          #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

          static BOOL Opning = TRUE;

          static NOTIFYICONDATA NID;

          static void Init_NID( HWND hDlg )
          {
          //if ( NID = new NOTIFYICONDATA )
          //{
          memset( &NID, 0, sizeof( NOTIFYICONDATA ) );

               if ( LoadIconMetric( AppInst,
                                    (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                    LIM\_SMALL, &NID.hIcon ) == S\_OK )
               {
                    if ( LoadIconMetric( AppInst,
                                         (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                         LIM\_SMALL, &NID.hBalloonIcon ) == S\_OK )
                    {
                         strcpy( NID.szTip, "My App Name" );
                         strcpy( NID.szInfoTitle, "Hi There" );
                         strcpy( NID.szInfo, "My notification message.." );
          
                         if ( Opning )
                         {
                              NID.uTimeout = 5000;
                              NID.uID = TRAY\_ICON\_ID;
                              NID.dwInfoFlags = NIIF\_USER;
                              NID.uCallbackMessage = MSG\_FROM\_TRAY;
                              NID.cbSize = sizeof( NOTIFYICONDATA );
                              NID.dwState = 0;
                              NID.dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
          
                              return;
                         }
          
                         DestroyIcon( NID.hBalloonIcon );
                    }
          
                    DestroyIcon( NID.hIcon );
               }
          
               //delete NID;
               //NID = NULL;
          //}
          

          }

          static BOOL Min2SysTray( HWND hDlg )
          {
          BOOL Success = FALSE;

          //if ( NID )
          //{
               NOTIFYICONDATA Ver;
               memset( &Ver, 0, sizeof( NOTIFYICONDATA )
          
          T 1 Reply Last reply
          0
          • F Frankie C

            I see, I have misinterpreted the usage of new in your code. What I mean is that I compiled a sample with a C (not C++) compiler and it works for me. The only problem I found compiling the code in 64bits is that a manifest resource is required. This is my full sample:

            #define WIN32_LEAN_AND_MEAN
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include "main.h"

            #define NELEMS(a) (sizeof(a) / sizeof((a)[0]))

            static INT_PTR CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);

            #define AppInst ghInstance
            static HANDLE ghInstance;

            #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
            #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

            #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

            static BOOL Opning = TRUE;

            static NOTIFYICONDATA NID;

            static void Init_NID( HWND hDlg )
            {
            //if ( NID = new NOTIFYICONDATA )
            //{
            memset( &NID, 0, sizeof( NOTIFYICONDATA ) );

                 if ( LoadIconMetric( AppInst,
                                      (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                      LIM\_SMALL, &NID.hIcon ) == S\_OK )
                 {
                      if ( LoadIconMetric( AppInst,
                                           (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                           LIM\_SMALL, &NID.hBalloonIcon ) == S\_OK )
                      {
                           strcpy( NID.szTip, "My App Name" );
                           strcpy( NID.szInfoTitle, "Hi There" );
                           strcpy( NID.szInfo, "My notification message.." );
            
                           if ( Opning )
                           {
                                NID.uTimeout = 5000;
                                NID.uID = TRAY\_ICON\_ID;
                                NID.dwInfoFlags = NIIF\_USER;
                                NID.uCallbackMessage = MSG\_FROM\_TRAY;
                                NID.cbSize = sizeof( NOTIFYICONDATA );
                                NID.dwState = 0;
                                NID.dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
            
                                return;
                           }
            
                           DestroyIcon( NID.hBalloonIcon );
                      }
            
                      DestroyIcon( NID.hIcon );
                 }
            
                 //delete NID;
                 //NID = NULL;
            //}
            

            }

            static BOOL Min2SysTray( HWND hDlg )
            {
            BOOL Success = FALSE;

            //if ( NID )
            //{
                 NOTIFYICONDATA Ver;
                 memset( &Ver, 0, sizeof( NOTIFYICONDATA )
            
            T Offline
            T Offline
            Tacitonitus
            wrote on last edited by
            #5

            Thanks very much Frankie-C, that information is (I hope) fairly indicative of what I've been suspecting (actually dreading) about this whole fiasco since shortly after it began.. And that is that I don't think the 64-bit Shell_NotifyIcon() works.. like, at all.. That's the only logical explanation that I can think of for what I'm seeing (and what you're saying).. So this is good; this is progress.. Fortunately, the manifest resource issue that you mentioned is easily rectified. Just add the following #pragma in your StdAfx.h:

            #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' "\
            "version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

            Then set the following option in your Project Property Page: Linker ==> Manifest File ==> Generate Manifest ==> Yes (/MANIFEST) and voila! No need to create a manifest resource.. Assuming, of course, that you're using some reasonably recent version of Microsoft Visual Studio.. Of course, as you may have already surmised, I'm telling you this in the hope that you'll try compiling your code in 64-bit, and apprise me of the results that you get.. If my suspicions are correct, your code, like mine, won't work in 64-bit.. If I'm wrong about that, then that would be almost as good (actually better in the long term). Then I'll just take your code verbatim, and start adding in bits of my other stuff until it fails. In my experience, bugs are rooted out far more easily when you're adding to code that works, as opposed to attempting to subtract from code that doesn't.. But I kinda need to know that the 64-bit Shell_NotifyIcon() works for someone, *anyone*, before I go down that (very long) road.. Because at this point, I don't think it will.. Anyway, thanks again for your help. I see that you're still insisting on a static NID as opposed to a static NID pointer.. Well, six of one, half dozen the other - you know. The reason I made it a pointer (and yes, in my own code, it's still a pointer) is because the whole System Tray thing is an End-User option, so why allocate memory that might never be used? And because making it a pointer allows it to double as a kind of boolean - if it's not NULL, it means that all steps of the initialization succeeded, and if it is NULL, then don't use it at all.. Kind of an all-or-nothing approach.. And last and least, I think we both know that that silly "Opning" variable doesn

            F 1 Reply Last reply
            0
            • T Tacitonitus

              Thanks very much Frankie-C, that information is (I hope) fairly indicative of what I've been suspecting (actually dreading) about this whole fiasco since shortly after it began.. And that is that I don't think the 64-bit Shell_NotifyIcon() works.. like, at all.. That's the only logical explanation that I can think of for what I'm seeing (and what you're saying).. So this is good; this is progress.. Fortunately, the manifest resource issue that you mentioned is easily rectified. Just add the following #pragma in your StdAfx.h:

              #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' "\
              "version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

              Then set the following option in your Project Property Page: Linker ==> Manifest File ==> Generate Manifest ==> Yes (/MANIFEST) and voila! No need to create a manifest resource.. Assuming, of course, that you're using some reasonably recent version of Microsoft Visual Studio.. Of course, as you may have already surmised, I'm telling you this in the hope that you'll try compiling your code in 64-bit, and apprise me of the results that you get.. If my suspicions are correct, your code, like mine, won't work in 64-bit.. If I'm wrong about that, then that would be almost as good (actually better in the long term). Then I'll just take your code verbatim, and start adding in bits of my other stuff until it fails. In my experience, bugs are rooted out far more easily when you're adding to code that works, as opposed to attempting to subtract from code that doesn't.. But I kinda need to know that the 64-bit Shell_NotifyIcon() works for someone, *anyone*, before I go down that (very long) road.. Because at this point, I don't think it will.. Anyway, thanks again for your help. I see that you're still insisting on a static NID as opposed to a static NID pointer.. Well, six of one, half dozen the other - you know. The reason I made it a pointer (and yes, in my own code, it's still a pointer) is because the whole System Tray thing is an End-User option, so why allocate memory that might never be used? And because making it a pointer allows it to double as a kind of boolean - if it's not NULL, it means that all steps of the initialization succeeded, and if it is NULL, then don't use it at all.. Kind of an all-or-nothing approach.. And last and least, I think we both know that that silly "Opning" variable doesn

              F Offline
              F Offline
              Frankie C
              wrote on last edited by
              #6

              Thanks Tacitonitus, BTW my code is 64 bits, and I assure you that it works. I didn't use VC, but PellesC compiler. You can get the working project (with even the executable) here[^] if you need. Just to give more detail, my manifest contains:

              Verbal description of MyApp.

              This is important because if I compile without it the loader complains about a missing ordinal in commctl32:

              The ordinal 380 could not be located in the dynamic link library COMCTL32.dll.

              T 1 Reply Last reply
              0
              • T Tacitonitus

                Apologies. I made a mistake in transcribing the original code. Which actually has nothing to do with why this code still doesn't work - just to be clear. In the original code, the NID->szTip, NID->szInfoTitle, and NID->szInfo structure members are not initialized by strcpy(). I changed it to a bunch of strcpy() calls to "simplify" the code (to make it easier to read).. They are initialized in the original code by a function call whose return value sets an auto bool called, "Opning". When I substituted out that function call for those strcpy() calls (for simplicity), I also (erroneously) took out the "bool Opning =" part. My bad. To make a long story short, the following is a far more correct "transcription" of the existing code:

                #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
                #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

                #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

                static NOTIFYICONDATA *NID;

                static void Init_NID( HWND hDlg )
                {
                if ( NID = new NOTIFYICONDATA )
                {
                memset( NID, 0, sizeof( NOTIFYICONDATA ) );

                     if ( LoadIconMetric( AppInst,
                                          (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                          LIM\_SMALL, &NID->hIcon ) == S\_OK )
                     {
                          if ( LoadIconMetric( AppInst,
                                               (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                               LIM\_SMALL, &NID->hBalloonIcon ) == S\_OK )
                          {
                               bool Opning;
                
                               if ( Opning = LoadStrings( NID->szTip,
                                                          NID->szInfo,
                                                          NID->szInfoTitle ) )
                               {
                                    NID->uTimeout = 5000;
                                    NID->uID = TRAY\_ICON\_ID;
                                    NID->dwInfoFlags = NIIF\_USER;
                                    NID->uCallbackMessage = MSG\_FROM\_TRAY;
                                    NID->cbSize = sizeof( NOTIFYICONDATA );
                                    NID->dwState = 0;
                                    NID->dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
                
                                    return;   // <== i.e. RETURN to caller w/ NID != NULL..
                               }
                
                               DestroyIcon( NID->hBalloonIcon );
                          }
                
                          DestroyIcon( NID->hIcon );
                     }
                
                     delete NID;
                     NID = NULL;
                }
                

                }

                Again, sorry for

                F Offline
                F Offline
                Frankie C
                wrote on last edited by
                #7

                Wait a moment, maybe both of us were sleeping while looking at the issue! :omg: Look better at your code:

                #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
                #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

                #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

                static NOTIFYICONDATA *NID;

                static void Init_NID( HWND hDlg )
                {
                if ( NID = new NOTIFYICONDATA )
                {
                memset( NID, 0, sizeof( NOTIFYICONDATA ) );

                     if ( LoadIconMetric( AppInst,
                                          (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon ),
                                          LIM\_SMALL, &NID->hIcon ) == S\_OK )
                     {
                          if ( LoadIconMetric( AppInst,
                                               (PCWSTR)MAKEINTRESOURCE( IDR\_BallIcon ),
                                               LIM\_SMALL, &NID->hBalloonIcon ) == S\_OK )
                          {
                               bool Opning;
                
                               if ( Opning = LoadStrings( NID->szTip,
                                                          NID->szInfo,
                                                          NID->szInfoTitle ) )
                               {
                                    NID->uTimeout = 5000;
                                    NID->uID = TRAY\_ICON\_ID;
                                    NID->dwInfoFlags = NIIF\_USER;
                                    NID->uCallbackMessage = MSG\_FROM\_TRAY;
                                    NID->cbSize = sizeof( NOTIFYICONDATA );
                                    NID->dwState = 0;
                                    NID->dwStateMask = NIS\_HIDDEN | NIS\_SHAREDICON;
                
                                    return;   // <== i.e. RETURN to caller w/ NID != NULL..
                               }
                
                               DestroyIcon( NID->hBalloonIcon );
                          }
                
                          DestroyIcon( NID->hIcon );
                     }
                
                     delete NID;   //If everything went good you are deleting the buffer!!!!!!!!!!!!!
                     NID = NULL;
                }
                

                }

                Have you realized that when everything is ok you deliberately destroy the buffer?!?! :confused: You simply missed a return:

                #define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
                #define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id

                #define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..

                static NOTIFYICONDATA *NID;

                static void Init_NID( HWND hDlg )
                {
                if ( NID = new NOTIFYICONDATA )
                {
                memset( NID, 0, sizeof( NOTIFYICONDATA ) );

                     if ( LoadIconMetric( AppInst,
                                          (PCWSTR)MAKEINTRESOURCE( IDR\_TrayIcon
                
                1 Reply Last reply
                0
                • F Frankie C

                  Thanks Tacitonitus, BTW my code is 64 bits, and I assure you that it works. I didn't use VC, but PellesC compiler. You can get the working project (with even the executable) here[^] if you need. Just to give more detail, my manifest contains:

                  Verbal description of MyApp.

                  This is important because if I compile without it the loader complains about a missing ordinal in commctl32:

                  The ordinal 380 could not be located in the dynamic link library COMCTL32.dll.

                  T Offline
                  T Offline
                  Tacitonitus
                  wrote on last edited by
                  #8

                  Yes, I got exactly that same error message when I tried to "disable Visual Styles", to see if it would make a difference.. So it looks like I've got to take that "very long" road I mentioned.. Well, like I said, in the long term, that's probably a good thing (I'm trying to stay positive).. So let me ask you: what size Icons are you passing in to the LoadIconMetric() function(s)? I'm passing in 32x32 pixel Icons, and trusting that the LoadIconMetric() function will either squash it down to the appropriate size, or return an error code if it can't. However, I can no longer trust even the most obvious of assumptions any more, which is why I'm asking.. Also, I can't download your project because you have to be a member of whatever to do so.. But that doesn't matter much - I'm.. uh.. somewhat familiar with the code.. :) This is maddening - according to you, the code works fine - it just doesn't work for me.. 'cause I'm.. special.. or cursed.. or something.. :wtf: Well, whatever. Ignore the previous paragraph. I guess I'll just have to keep slogging it out.. Cheers..

                  F 2 Replies Last reply
                  0
                  • T Tacitonitus

                    Yes, I got exactly that same error message when I tried to "disable Visual Styles", to see if it would make a difference.. So it looks like I've got to take that "very long" road I mentioned.. Well, like I said, in the long term, that's probably a good thing (I'm trying to stay positive).. So let me ask you: what size Icons are you passing in to the LoadIconMetric() function(s)? I'm passing in 32x32 pixel Icons, and trusting that the LoadIconMetric() function will either squash it down to the appropriate size, or return an error code if it can't. However, I can no longer trust even the most obvious of assumptions any more, which is why I'm asking.. Also, I can't download your project because you have to be a member of whatever to do so.. But that doesn't matter much - I'm.. uh.. somewhat familiar with the code.. :) This is maddening - according to you, the code works fine - it just doesn't work for me.. 'cause I'm.. special.. or cursed.. or something.. :wtf: Well, whatever. Ignore the previous paragraph. I guess I'll just have to keep slogging it out.. Cheers..

                    F Offline
                    F Offline
                    Frankie C
                    wrote on last edited by
                    #9

                    Icon is 32x32 256 colors. To download the sample you have just register is not a big issue.

                    1 Reply Last reply
                    0
                    • T Tacitonitus

                      Yes, I got exactly that same error message when I tried to "disable Visual Styles", to see if it would make a difference.. So it looks like I've got to take that "very long" road I mentioned.. Well, like I said, in the long term, that's probably a good thing (I'm trying to stay positive).. So let me ask you: what size Icons are you passing in to the LoadIconMetric() function(s)? I'm passing in 32x32 pixel Icons, and trusting that the LoadIconMetric() function will either squash it down to the appropriate size, or return an error code if it can't. However, I can no longer trust even the most obvious of assumptions any more, which is why I'm asking.. Also, I can't download your project because you have to be a member of whatever to do so.. But that doesn't matter much - I'm.. uh.. somewhat familiar with the code.. :) This is maddening - according to you, the code works fine - it just doesn't work for me.. 'cause I'm.. special.. or cursed.. or something.. :wtf: Well, whatever. Ignore the previous paragraph. I guess I'll just have to keep slogging it out.. Cheers..

                      F Offline
                      F Offline
                      Frankie C
                      wrote on last edited by
                      #10

                      Tacitonitus, I don't think that a code couldn't work because someone is marked by the obscure forces. First of all, it was was my wrong about the new operator because it seemed to me that you destroyed the buffer exiting the function. Of course to use a static or dynamic allocation makes no difference, what really counts is that the memory stay there when shell functions are called. The Shell_NotifyIcon, with a lot of bugs as usual for MS products, couldn't be not functional. There is a sea of 64 bits applications out there that works. My personal idea is that the problem is not in your code for Shell_NotifyIcon, but somewhere else. Probably you would take a tighten look to the whole code and try debugging to see if the buffer is consistent each time you use the Shell_NotifyIcon function. Cheers

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups