wxTaskBarIcon with Balloon tooltips!

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
ctz
In need of some credit
In need of some credit
Posts: 4
Joined: Mon Sep 13, 2004 6:09 pm

wxTaskBarIcon with Balloon tooltips!

Post by ctz »

This class extends wxTaskBarIcon to offer balloon tooltips! It works very well in my application qDong:

Image

Code: Select all

class QDongTaskIcon : public wxTaskBarIcon
{
public:
	QDongTaskIcon();

	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;

	NOTIFYICONDATA notifyData;

	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);
	else
		return false;
}
Possible values for icon are:

NIIF_ERROR
An error icon.
NIIF_INFO
An information icon.
NIIF_NONE
No icon.
NIIF_WARNING
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.
eros
I live to help wx-kind
I live to help wx-kind
Posts: 162
Joined: Mon Sep 06, 2004 1:40 am
Location: Argentina

Post by eros »

Great stuff!
...
User avatar
tierra
Site Admin
Site Admin
Posts: 1355
Joined: Sun Aug 29, 2004 7:14 pm
Location: Salt Lake City, Utah, USA
Contact:

Post 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.
User avatar
Ryan Norton
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

NEAT!!

Definately stickied :).
[Mostly retired moderator, still check in to clean up some stuff]
Avi
Super wx Problem Solver
Super wx Problem Solver
Posts: 398
Joined: Mon Aug 30, 2004 9:27 pm
Location: Tel-Aviv, Israel

Post 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 SF.net (so it will be in one of the next wxWidgets versions if excepted!).
Scorcher24
Earned some good credits
Earned some good credits
Posts: 128
Joined: Sat Sep 25, 2004 9:11 pm
Location: Nuremberg, Germany
Contact:

Post 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 ??
rya.
Scorcher24
OS: Windows 7 Ultimate 64bit
IDE: VC++ 2008 Professional
WX: 2.9.2
My Projects
gunnar
In need of some credit
In need of some credit
Posts: 5
Joined: Wed Oct 13, 2004 11:27 am

My own version oif this snippet for 2.5.3

Post 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

#ifdef wxHAS_TASK_BAR_ICON
#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
{
public:
        wxTaskBarIconWindow(wxTaskBarIcon *icon)
                : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, 0),
                m_icon(icon)
        {
        }


private:
        wxTaskBarIcon *m_icon;
};

#endif


//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
#ifndef wxSUBRELEASE_NUMBER
#define wxTaskBarIconEvent wxEvent
#endif
#endif
class MusikTaskBarIcon: public wxTaskBarIcon
{
public:
        MusikTaskBarIcon(wxFrame * frame)
        {
#ifdef __WXMSW__
                m_dwShellDllVersion = GetDllVersion(wxT("shell32.dll"));
#endif
                m_pFrame = frame;
        };
        virtual bool SetIcon(const wxIcon& icon,
                const wxString& tooltip = wxEmptyString)
        {
                bool bRes = false;
#ifndef __WXMSW__
                bRes =  wxTaskBarIcon::SetIcon(icon,tooltip);
#else
                if(m_dwShellDllVersion < PACKVERSION(5,00))
                         bRes =  wxTaskBarIcon::SetIcon(icon,tooltip);
                else
                {
                        // we can use NOTIFYICONDATA V2,where the szTip has 128 chars instead of 64
                        bRes =  wxTaskBarIcon::SetIcon(icon,wxEmptyString); //just set the icon.
                        if(!tooltip.empty())
                        {// now set the tooltip text with the help of NOTIFYICONDATA V2 struct.
                                NOTIFYICONDATA nid;
                                memset(&nid,0,sizeof(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);
                        }
                }
#endif
                return bRes;
        }
#ifdef __WXMSW__
        virtual bool ShowBalloonInfo(const wxString &sTitle,const wxString  &sText)
        {
                bool bRes = true;
                if(m_dwShellDllVersion >= PACKVERSION(5,00))
                {
                        NOTIFYICONDATA nid;
                        memset(&nid,0,sizeof(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);
                }
                else
                        return false;

                return bRes;
        }
#endif
        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 );

DECLARE_EVENT_TABLE()

private:
        wxFrame *m_pFrame;
#ifdef __WXMSW__
        DWORD m_dwShellDllVersion;
#endif
};
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 ]


regards,
gunnar

EDIT: Updated the "tag" again to wxWidgtes syntax highlighting :)
Greetz,
upCASE
Get the music out of wxWidgets, use wxMusik ;-)
from http://musik.berlios.de
lowjoel
Part Of The Furniture
Part Of The Furniture
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post by lowjoel »

hmm will downloading the latest platform SDK do the trick? any help would be much appreciated.

thanks,
joel
wxDiilbert
Earned a small fee
Earned a small fee
Posts: 16
Joined: Tue Feb 08, 2005 3:52 am

Post by wxDiilbert »

Only works on MSW right ? :)
wxDiilbert
Earned a small fee
Earned a small fee
Posts: 16
Joined: Tue Feb 08, 2005 3:52 am

Post by wxDiilbert »

lowjoel wrote:hmm will downloading the latest platform SDK do the trick? any help would be much appreciated.

thanks,
joel
Yes... I have used tooltip stuff in MFC apps before and you need the common core component of the latest SDK installed.
[email protected]
In need of some credit
In need of some credit
Posts: 4
Joined: Fri Jul 08, 2005 5:31 pm

Post by [email protected] »

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.

Thanks.
lowjoel
Part Of The Furniture
Part Of The Furniture
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post 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:
lowjoel
Part Of The Furniture
Part Of The Furniture
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post 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 = 
+CFLAGS = -D_WIN32_IE=0x0600
 
 # Standard flags for C++ 
-CXXFLAGS = 
+CXXFLAGS = -D_WIN32_IE=0x0600
 
 # Standard preprocessor flags (common for CC and CXX) 
 CPPFLAGS = 


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"
 #endif
 
+#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);
 
 #if WXWIN_COMPATIBILITY_2_4
     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)
         RemoveIcon();
-
+	
     if (m_win)
         m_win->Destroy();
 }
@@ -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
[email protected]
In need of some credit
In need of some credit
Posts: 4
Joined: Fri Jul 08, 2005 5:31 pm

Post by [email protected] »

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?
lowjoel
Part Of The Furniture
Part Of The Furniture
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post 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
Post Reply