Page 1 of 3

wxTaskBarIcon with Balloon tooltips!

Posted: Mon Sep 13, 2004 6:22 pm
by ctz
This class extends wxTaskBarIcon to offer balloon tooltips! It works very well in my application qDong:


Code: Select all

class QDongTaskIcon : public wxTaskBarIcon

	bool ShowBalloon(wxString title, wxString message, unsigned int timeout = 10000, int icon = NIIF_INFO);

QDongTaskIcon::QDongTaskIcon() : wxTaskBarIcon()

bool QDongTaskIcon::ShowBalloon(wxString title, wxString message, unsigned int timeout, int icon)
	if (!IsOK())
		return FALSE;


	memset(&notifyData, 0, sizeof(notifyData));
	notifyData.cbSize = sizeof(notifyData);
	notifyData.hWnd = (HWND) m_hWnd;
	notifyData.uCallbackMessage = sm_taskbarMsg;
	notifyData.uFlags = NIF_MESSAGE;

	notifyData.uFlags |= NIF_INFO;
	lstrcpyn(notifyData.szInfo, WXSTRINGCAST message, sizeof(notifyData.szInfo));
	lstrcpyn(notifyData.szInfoTitle, WXSTRINGCAST title, sizeof(notifyData.szInfoTitle));
	notifyData.dwInfoFlags = icon | NIIF_NOSOUND;
	notifyData.uTimeout = timeout;

	notifyData.uID = 99;

	if (m_iconAdded)
		return (Shell_NotifyIcon(NIM_MODIFY, &notifyData) != 0);
		return false;
Possible values for icon are:

An error icon.
An information icon.
No icon.
A warning icon.

:arrow: however using this class is not compatible with windows ME and less. Only 2000, XP and 2003 support balloon tooltips AFAIK.

Posted: Tue Sep 14, 2004 3:38 am
by eros
Great stuff!

Posted: Tue Sep 14, 2004 6:42 am
by tierra
Awesome! Now I'm going to be looking for reasons to use this code just like I've been searching for reasons to use Jorgen's work... not to say Jorgen's work isn't good for anything, it's just a little more rare cases, and when they pop up, it definately comes in handy.

Posted: Tue Sep 14, 2004 6:45 am
by Ryan Norton

Definately stickied :).

Posted: Sun Sep 19, 2004 1:22 pm
by Avi
Very nice indeed! I would add an enum wxBalloonIcon which has nicer balloon icons codes ;) Anyway, please make this a patch (to extend the wxWidgets library) and post it at (so it will be in one of the next wxWidgets versions if excepted!).

Posted: Mon Oct 11, 2004 5:18 pm
by Scorcher24
Hi there !!
thx for your snippet. I tried it out, but I have some Problems.
It is about that Visual Stduio tells me, that some elements are no members of NOTIFYICONDATA. I have done the define like MSDN tells me (#define IE 0x0500 or so) but It doesn't help. I also included <shellapi.h>. Perhaps you can tell me whats wrong ??

My own version oif this snippet for 2.5.3

Posted: Wed Oct 13, 2004 11:44 am
by gunnar
I posted this on wx-dev list,but in case not everyone reads this list.

Well the forum version does actually not work with 2.5.3
No m_hWnd member anymore, but a wxTaskBarIconWindow * m_win,
where wxTaskBarIconWindow is deifined inside taskbar.cpp meaning its not
accessible from a user.

I made a quite hackish workaround and wrote the following code.

Code: Select all

#include "wx/taskbar.h"
#ifdef __WXMSW__
#include <ShellAPI.h>
// Here i define wxTaskBarIconWindow as it is only define privately in
taskbar,cpp of wxwidgets
// This is a hack, but which choice do i have else?
class wxTaskBarIconWindow : public wxFrame
        wxTaskBarIconWindow(wxTaskBarIcon *icon)
                : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, 0),

        wxTaskBarIcon *m_icon;


//quite hackish attempt to be able to compile with release 2.5.2 and cvs
HEAD before 2.5.3 release
#if wxVERSION_NUMBER < 2503
#define wxTaskBarIconEvent wxEvent
class MusikTaskBarIcon: public wxTaskBarIcon
        MusikTaskBarIcon(wxFrame * frame)
#ifdef __WXMSW__
                m_dwShellDllVersion = GetDllVersion(wxT("shell32.dll"));
                m_pFrame = frame;
        virtual bool SetIcon(const wxIcon& icon,
                const wxString& tooltip = wxEmptyString)
                bool bRes = false;
#ifndef __WXMSW__
                bRes =  wxTaskBarIcon::SetIcon(icon,tooltip);
                if(m_dwShellDllVersion < PACKVERSION(5,00))
                         bRes =  wxTaskBarIcon::SetIcon(icon,tooltip);
                        // we can use NOTIFYICONDATA V2,where the szTip has 128 chars instead of 64
                        bRes =  wxTaskBarIcon::SetIcon(icon,wxEmptyString); //just set the icon.
                        {// now set the tooltip text with the help of NOTIFYICONDATA V2 struct.
                                NOTIFYICONDATA nid;
                                nid.cbSize = NOTIFYICONDATAW_V2_SIZE;
                                nid.hWnd = (HWND)m_win->GetHWND();
                                nid.uID = 99;
                                nid.uFlags = NIF_TIP;
                                wxStrncpy(nid.szTip, tooltip.c_str(), WXSIZEOF(nid.szTip));
                                Shell_NotifyIcon(NIM_MODIFY, &nid);
                return bRes;
#ifdef __WXMSW__
        virtual bool ShowBalloonInfo(const wxString &sTitle,const wxString  &sText)
                bool bRes = true;
                if(m_dwShellDllVersion >= PACKVERSION(5,00))
                        NOTIFYICONDATA nid;
                        nid.cbSize = NOTIFYICONDATAW_V2_SIZE;
                        nid.hWnd = (HWND)m_win->GetHWND();
                        nid.uID = 99;
                        nid.uFlags = NIF_INFO;
                        wxStrncpy(nid.szInfo, sText.c_str(), WXSIZEOF(nid.szInfo));
                        wxStrncpy(nid.szInfoTitle, sTitle.c_str(), WXSIZEOF(nid.szInfoTitle));
                        nid.dwInfoFlags = NIIF_NOSOUND|NIIF_INFO;
                        nid.uTimeout = 5000;

                        Shell_NotifyIcon(NIM_MODIFY, &nid);
                        return false;

                return bRes;
        void RestoreFrame();
    void OnRButtonUp(wxTaskBarIconEvent&);
    void OnLButtonDown(wxTaskBarIconEvent&);
    void OnMenuRestore(wxCommandEvent&);
    void OnMenuHide(wxCommandEvent&);
    void OnMenuPlayPause(wxCommandEvent&);
    void OnMenuPrev(wxCommandEvent&);
    void OnMenuNext(wxCommandEvent&);
    void OnMenuStop(wxCommandEvent&);
    void OnMenuExit(wxCommandEvent&);
    void OnMenuSetNewIcon(wxCommandEvent&);
        void OnUpdateUIRateSel ( wxUpdateUIEvent &event);
        void OnMenuRateSel( wxCommandEvent& event );


        wxFrame *m_pFrame;
#ifdef __WXMSW__
        DWORD m_dwShellDllVersion;
set _WIN32_IE=0x0600
in your projects preprocessor definitions.

the code of GetDllVersion(LPCTSTR dll)
can be found in the MSDN.

Maybe someone likes to incorporate this code into wxwidgets.
Instead of GetDllVersion(LPCTSTR dll) a more general version of
wxApp:GetComCtlVeersion() could be made.

EDIT: I added syntax highlighting, please use the [ syntax ] tag for code, or at least [ code ]


EDIT: Updated the "tag" again to wxWidgtes syntax highlighting :)

Posted: Sat Jul 02, 2005 12:23 pm
by lowjoel
hmm will downloading the latest platform SDK do the trick? any help would be much appreciated.


Posted: Sun Jul 03, 2005 12:00 pm
by wxDiilbert
Only works on MSW right ? :)

Posted: Sun Jul 03, 2005 12:01 pm
by wxDiilbert
lowjoel wrote:hmm will downloading the latest platform SDK do the trick? any help would be much appreciated.

Yes... I have used tooltip stuff in MFC apps before and you need the common core component of the latest SDK installed.

Posted: Mon Jul 11, 2005 11:52 pm
I don't understand Gunnar's example. And the original one isn't quite working for me either. I ran into Gunnar's problem with m_hWnd not being available to set the NOTIFYICONDATA.hWnd equal to.

I assume this is the handle of the window that the tooltip will show up in. Only problem is, I don't see how Gunnar's example of including the wxTaskBarIconWindow class definition helps me accomplish this goal.

In his code for setting hWnd, he shows:

Code: Select all

nid.hWnd = (HWND)m_win->GetHWND()
I can't figure out where the m_win is supposed to be coming from there. I'm assuming that it's a reference to the wxTaskBarIconWindow, but how do we get that? If we instantiate it separately (after the wxTaskBarIcon is created), and then pass it into the ShowBalloon method, things don't work (I've tried this). That's probably not surprising, in that I think what he's saying is a wxTaskBarIconWindow is created under the covers when a wxTaskBarIcon is created. So how the deuce do I get the address (or the hWnd) of that window after it's created in a hidden manner during the wxTaskBarIcon creation?

Basically, I don't understand what I'm supposed to do with the wxTaskBarIconWindow class, and how that helps me get this bleeding window handle that I need.

Have been struggling with this one for some time. I would certainly appreciate help.


Posted: Mon Aug 01, 2005 5:04 am
by lowjoel
I'm working on a patch to integrate this function into wxTaskBarIcon... and hopefully i will build a dll and static version (along with 2.6.2 CVS) and upload it to my server for download (along with a few other patches) just that building wx takes time.... :roll:

Posted: Mon Aug 01, 2005 12:46 pm
by lowjoel
I've done the patch:

Code: Select all

Index: build/msw/config.gcc
RCS file: /pack/cvsroots/wxwindows/wxWindows/build/msw/config.gcc,v
retrieving revision 1.18
diff -u -r1.18 config.gcc
--- build/msw/config.gcc	2005/07/28 12:42:09	1.18
+++ build/msw/config.gcc	2005/08/01 06:01:02

@@ -17,10 +17,10 @@
 CXX = g++
 # Standard flags for CC 
+CFLAGS = -D_WIN32_IE=0x0600
 # Standard flags for C++ 
+CXXFLAGS = -D_WIN32_IE=0x0600
 # Standard preprocessor flags (common for CC and CXX) 

Index: include/wx/msw/taskbar.h
RCS file: /pack/cvsroots/wxwindows/wxWindows/include/wx/msw/taskbar.h,v
retrieving revision 1.24
diff -u -r1.24 taskbar.h
--- include/wx/msw/taskbar.h	2004/09/07 06:00:52	1.24
+++ include/wx/msw/taskbar.h	2005/08/01 08:22:00
@@ -17,6 +17,7 @@
 #pragma interface "taskbar.h"
+#include <shellapi.h>
 #include "wx/icon.h"
 // private helper class:
@@ -37,6 +38,7 @@
     bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
     bool RemoveIcon(void);
     bool PopupMenu(wxMenu *menu); //, int x, int y);
+    bool ShowBalloon(wxString title, wxString message, unsigned int timeout = 10000, int icon = NIIF_INFO);
     wxDEPRECATED( bool IsOK() const );

Index: src/msw/taskbar.cpp
RCS file: /pack/cvsroots/wxwindows/wxWindows/src/msw/taskbar.cpp,v
retrieving revision 1.46
diff -u -r1.46 taskbar.cpp
--- src/msw/taskbar.cpp	2005/05/31 09:20:33	1.46
+++ src/msw/taskbar.cpp	2005/08/01 12:43:45
@@ -135,7 +135,7 @@
     if (m_iconAdded)
     if (m_win)
@@ -165,7 +165,6 @@
     if ( !tooltip.empty() )
         notifyData.uFlags |= NIF_TIP;
-//        lstrcpyn(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
         wxStrncpy(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
@@ -183,6 +182,9 @@
     if (!m_iconAdded)
         return false;
+    /*if (m_balloon)
+        Shell_NotifyIcon(NIM_DELETE, &m_notifyData) != 0;*/
     m_iconAdded = false;
     NotifyIconData notifyData((HWND)m_win->GetHWND());
@@ -328,6 +330,25 @@
     return 0;
+bool wxTaskBarIcon::ShowBalloon(wxString title, wxString message, unsigned int timeout, int icon)
+	if (!IsOk())
+	    return false;
+	NotifyIconData notifyData((HWND)m_win->GetHWND());
+    notifyData.uFlags = NIF_INFO;
+    wxStrncpy(notifyData.szInfo, message.c_str(), WXSIZEOF(notifyData.szInfo));
+    wxStrncpy(notifyData.szInfoTitle, title.c_str(), WXSIZEOF(notifyData.szInfoTitle));
+    notifyData.dwInfoFlags = icon;
+    notifyData.uTimeout = timeout;
+    if (m_iconAdded)
+	    return Shell_NotifyIcon(NIM_MODIFY, &notifyData);
+    else
+        return false;
 #endif // __WIN95__
The devpak will be available soon

Posted: Mon Aug 01, 2005 9:31 pm
lowjoel wrote:I've done the patch:
That's pretty cool. What's this 'devpack' about? What would I need to do to update my DLLs to include your patch?

Also, does this mean that we can expect that code in future versions of wxWidgets?

Posted: Mon Aug 01, 2005 11:53 pm
by lowjoel
devpaks are prebuilt libraries... for mingw

but if u want to include the patch in ur distro, feel free,

but it doesnt mean it will be included in later wx versions