Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Shell_NotifyIcon WITHOUT adding an icon in the notification area

MSDN's documentation about Notifications and the Notification Area is pretty clear in the requirement for having an icon in the notification area in order to display a notification:

To display a notification, you must have an icon in the notification area. In certain cases, such as Microsoft Communicator or battery level, that icon will already be present. In many other cases, however, you will add an icon to the notification area only as long as is needed to show the notification.

Since I do not wish to add any icon to the notification area, I was thinking of perhaps "reusing" an existing one that is most likely to be there on a typical desktop. A good candidate may be the system clock.

My questions are:

  1. How do I find/enumerate the NOTIFYICONDATA structure for the system clock (AKA "Date and Time Properties" when restored)?
  2. Is there a better way of accomplishing this (without adding an icon)?
like image 589
WinWin Avatar asked Jun 07 '11 19:06

WinWin


People also ask

How do I remove icons from my notification area?

Step 1: Right-click on the Taskbar and select Properties. Step 2: Under the Notification Area, click the button Customize. Step 3: Look for the icons and select the Behaviors as Hide icon and notifications to hide icon as well as other related notifications.

How do I turn on the Show icon in the notification area?

Press the Windows key , type "taskbar settings", then press Enter . Or, right-click the taskbar, and choose Taskbar settings. In the window that appears, scroll down to the Notification area section. From here, you can choose Select which icons appear on the taskbar or Turn system icons on or off.


1 Answers

Shell_NotifyIcon uses IUserNotification under the hood. I played around with it and made a utility out of it. I heard of a visually impaired sysadmin who uses it to make his scripts screen reader compatible. It is command line, it does not have a message loop.

It is self aware, meaning that notifications sent to it will be queued (you have control over it). For that to work, I provided a IQueryContinue implementation. The project is in C++ and is open source, help yourself.

Here is the guts of it :

 HRESULT NotifyUser(const NOTIFU_PARAM& params, IQueryContinue *querycontinue, IUserNotificationCallback *notifcallback)
 {
    HRESULT result = E_FAIL;

    IUserNotification *un = 0;
    IUserNotification2 *deux = 0; //French pun : "un" above stands for UserNotification but it also means 1 in French. deux means 2.

    //First try with the Vista/Windows 7 interface
    //(unless /xp flag is specified
    if (!params.mForceXP)
       result = CoCreateInstance(CLSID_UserNotification, 0, CLSCTX_ALL, IID_IUserNotification2, (void**)&deux);

    //Fall back to Windows XP
    if (!SUCCEEDED(result))
    {
       TRACE(eWARN, L"Using Windows XP interface IUserNotification\n");
       result = CoCreateInstance(CLSID_UserNotification, 0, CLSCTX_ALL, IID_IUserNotification, (void**)&un);
    }
    else
    {
       TRACE(eINFO, L"Using Vista interface IUserNotification2\n");
       un = (IUserNotification*)deux; //Rather ugly cast saves some code...
    }

    if (SUCCEEDED(result))
    {
       const std::basic_string<TCHAR> crlf_text(L"\\n");
       const std::basic_string<TCHAR> crlf(L"\n");
       std::basic_string<TCHAR> text(params.mText);
       size_t look = 0;
       size_t found;

       //Replace \n with actual CRLF pair
       while ((found = text.find(crlf_text, look)) != std::string::npos)
       {
          text.replace(found, crlf_text.size(), crlf);
          look = found+1;
       }

       result = un->SetIconInfo(params.mIcon, params.mTitle.c_str());
       result = un->SetBalloonInfo(params.mTitle.c_str(), text.c_str(), params.mType);

       //Looks like it controls what happends when the X button is
       //clicked on
       result = un->SetBalloonRetry(0, 250, 0);

       if (deux)
          result = deux->Show(querycontinue, 250, notifcallback);
       else
          result = un->Show(querycontinue, 250);

       un->Release();
    }

    return result;
 }
like image 107
ixe013 Avatar answered Oct 12 '22 11:10

ixe013