wxTaskBarIcon with Balloon tooltips!
-
- wxWorld Domination!
- Posts: 1339
- Joined: Wed Aug 03, 2005 8:10 am
- Location: BANGALORE, INDIA
- Contact:
I don't know how you do in wxDevCpp 6.10, but I guess you can search the file shellapi.h on your system and look whether it has definition for NIIF_INFO or not, if not, then download the latest platform SDK from microsoft and update your adv project by adding a preprocessor _WIN32_IE=0x600 and then recompile the adv project. You can use the free Microsoft Visual Studio 2005 Express for that.
Code: Select all
/////////////////////////////////////////////////////////////////////////
// File: taskbar.cpp
// Purpose: Implements wxTaskBarIconEx class for manipulating icons on
// the Windows task bar.
// Author: Julian Smart
// Modified by:
// Created: 24/3/98
// RCS-ID: $Id: taskbarex.cpp 11913 2007-01-19 23:45:19Z rwalton $
// Copyright: (c)
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "taskbarex.h"
#endif
#include "stdwx.h"
#include "BOINCGUIApp.h"
#include "msw/taskbarex.h"
#include "BOINCTaskBar.h"
LRESULT APIENTRY wxTaskBarIconExWindowProc( HWND hWnd, unsigned msg, UINT wParam, LONG lParam );
wxChar* wxTaskBarExWindowClass = (wxChar*) wxT("wxTaskBarExWindowClass");
wxChar* wxTaskBarExWindow = (wxChar*) wxT("wxTaskBarExWindow");
const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(wxT("TaskbarCreated"));
const UINT WM_TASKBARSHUTDOWN = ::RegisterWindowMessage(wxT("TaskbarShutdown"));
bool wxTaskBarIconEx::sm_registeredClass = FALSE;
UINT wxTaskBarIconEx::sm_taskbarMsg = 0;
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_CREATED )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_CONTEXT_MENU )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_SELECT )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_KEY_SELECT )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_SHOW )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK )
DEFINE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN )
IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIconEx, wxEvtHandler)
BEGIN_EVENT_TABLE (wxTaskBarIconEx, wxEvtHandler)
EVT_CLOSE(wxTaskBarIconEx::OnClose)
EVT_TASKBAR_CREATED(wxTaskBarIconEx::OnTaskBarCreated)
END_EVENT_TABLE ()
wxTaskBarIconEx::wxTaskBarIconEx(void)
{
m_hWnd = 0;
m_iconAdded = FALSE;
if (RegisterWindowClass())
m_hWnd = CreateTaskBarWindow( wxTaskBarExWindow );
}
wxTaskBarIconEx::wxTaskBarIconEx( wxChar* szWindowTitle )
{
m_hWnd = 0;
m_iconAdded = FALSE;
if (RegisterWindowClass())
m_hWnd = CreateTaskBarWindow( szWindowTitle );
}
wxTaskBarIconEx::~wxTaskBarIconEx(void)
{
if (m_iconAdded)
{
RemoveIcon();
}
if (m_hWnd)
{
::DestroyWindow((HWND) m_hWnd);
m_hWnd = 0;
}
}
// Events
void wxTaskBarIconEx::OnClose(wxCloseEvent& WXUNUSED(event))
{
wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::OnClose - Function Begin"));
::DestroyWindow((HWND) m_hWnd);
m_hWnd = 0;
wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::OnClose - Function End"));
}
void wxTaskBarIconEx::OnTaskBarCreated(wxTaskBarIconExEvent& WXUNUSED(event))
{
m_iconAdded = (Shell_NotifyIcon(NIM_ADD, ¬ifyData) != 0);
Shell_NotifyIcon(NIM_SETVERSION, ¬ifyData);
}
// Operations
bool wxTaskBarIconEx::SetIcon(const wxIcon& icon, const wxString& tooltip)
{
if (!IsOK())
return FALSE;
memset(¬ifyData, 0, sizeof(notifyData));
notifyData.cbSize = sizeof(notifyData);
notifyData.hWnd = (HWND) m_hWnd;
notifyData.uID = 99;
notifyData.uCallbackMessage = sm_taskbarMsg;
notifyData.uFlags = NIF_MESSAGE;
notifyData.uVersion = NOTIFYICON_VERSION;
if (icon.Ok())
{
notifyData.uFlags |= NIF_ICON;
notifyData.hIcon = (HICON) icon.GetHICON();
}
if (((const wxChar*) tooltip != NULL) && (tooltip != wxT("")))
{
notifyData.uFlags |= NIF_TIP ;
lstrcpyn(notifyData.szTip, WXSTRINGCAST tooltip, sizeof(notifyData.szTip));
}
if (m_iconAdded)
return (Shell_NotifyIcon(NIM_MODIFY, ¬ifyData) != 0);
else
{
m_iconAdded = (Shell_NotifyIcon(NIM_ADD, ¬ifyData) != 0);
if (IsBalloonsSupported())
Shell_NotifyIcon(NIM_SETVERSION, ¬ifyData);
return m_iconAdded;
}
}
bool wxTaskBarIconEx::SetBalloon(const wxIcon& icon, const wxString title, const wxString message, unsigned int timeout, unsigned int iconballoon)
{
if (!IsOK())
return false;
wxString strTip = wxEmptyString;
if (!IsBalloonsSupported())
strTip = title + wxT(" - ") + message;
memset(¬ifyData, 0, sizeof(notifyData));
notifyData.cbSize = sizeof(notifyData);
notifyData.hWnd = (HWND) m_hWnd;
notifyData.uID = 99;
notifyData.uCallbackMessage = sm_taskbarMsg;
notifyData.uFlags = NIF_MESSAGE;
notifyData.dwInfoFlags = iconballoon | NIIF_NOSOUND;
notifyData.uTimeout = timeout;
notifyData.uVersion = NOTIFYICON_VERSION;
if (icon.Ok())
{
notifyData.uFlags |= NIF_ICON;
notifyData.hIcon = (HICON) icon.GetHICON();
}
if (IsBalloonsSupported())
{
notifyData.uFlags |= NIF_INFO | NIF_TIP;
lstrcpyn(notifyData.szInfo, WXSTRINGCAST message, sizeof(notifyData.szInfo));
lstrcpyn(notifyData.szInfoTitle, WXSTRINGCAST title, sizeof(notifyData.szInfoTitle));
lstrcpyn(notifyData.szTip, WXSTRINGCAST wxEmptyString, sizeof(notifyData.szTip));
}
else
{
notifyData.uFlags |= NIF_TIP;
lstrcpyn(notifyData.szTip, WXSTRINGCAST strTip, sizeof(notifyData.szTip));
}
if (m_iconAdded)
return (Shell_NotifyIcon(NIM_MODIFY, & notifyData) != 0);
else
{
m_iconAdded = (Shell_NotifyIcon(NIM_ADD, & notifyData) != 0);
if (IsBalloonsSupported())
Shell_NotifyIcon(NIM_SETVERSION, ¬ifyData);
return m_iconAdded;
}
}
bool wxTaskBarIconEx::RemoveIcon(void)
{
if (!m_iconAdded)
return FALSE;
memset(¬ifyData, 0, sizeof(notifyData));
notifyData.cbSize = sizeof(notifyData);
notifyData.hWnd = (HWND) m_hWnd;
notifyData.uCallbackMessage = sm_taskbarMsg;
notifyData.uFlags = NIF_MESSAGE;
notifyData.hIcon = 0 ; // hIcon;
notifyData.uID = 99;
m_iconAdded = FALSE;
return (Shell_NotifyIcon(NIM_DELETE, & notifyData) != 0);
}
bool wxTaskBarIconEx::PopupMenu(wxMenu *menu) //, int x, int y);
{
// OK, so I know this isn't thread-friendly, but
// what to do? We need this check.
static bool s_inPopup = FALSE;
if (s_inPopup)
return FALSE;
s_inPopup = TRUE;
bool rval = FALSE;
wxWindow* win;
int x, y;
wxGetMousePosition(&x, &y);
// is wxFrame the best window type to use???
win = new wxFrame(NULL, -1, wxEmptyString, wxPoint(x,y), wxSize(-1,-1), 0);
win->PushEventHandler(this);
// Remove from record of top-level windows, or will confuse wxWindows
// if we try to exit right now.
wxTopLevelWindows.DeleteObject(win);
menu->UpdateUI();
// Work around a WIN32 bug
::SetForegroundWindow ((HWND) win->GetHWND ());
rval = win->PopupMenu(menu, 0, 0);
// Work around a WIN32 bug
::PostMessage ((HWND) win->GetHWND(),WM_NULL,0,0L);
win->PopEventHandler(FALSE);
win->Destroy();
delete win;
s_inPopup = FALSE;
return rval;
}
bool wxTaskBarIconEx::RegisterWindowClass()
{
if (sm_registeredClass)
return TRUE;
// Also register the taskbar message here
sm_taskbarMsg = ::RegisterWindowMessage(wxT("wxTaskBarIconExMessage"));
WNDCLASS wc;
bool rc;
HINSTANCE hInstance = GetModuleHandle(NULL);
/*
* set up and register window class
*/
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) wxTaskBarIconExWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = wxTaskBarExWindowClass ;
rc = (::RegisterClass( &wc ) != 0);
sm_registeredClass = (rc != 0);
return( (rc != 0) );
}
WXHWND wxTaskBarIconEx::CreateTaskBarWindow( wxChar* szWindowTitle )
{
HINSTANCE hInstance = GetModuleHandle(NULL);
HWND hWnd = CreateWindowEx (0, wxTaskBarExWindowClass,
szWindowTitle,
WS_OVERLAPPED,
0,
0,
10,
10,
NULL,
(HMENU) 0,
hInstance,
NULL);
return (WXHWND) hWnd;
}
bool wxTaskBarIconEx::IsBalloonsSupported()
{
#ifdef __WXMSW__
wxInt32 iMajor = 0, iMinor = 0;
if ( wxWINDOWS_NT == wxGetOsVersion( &iMajor, &iMinor ) )
{
if ( (5 >= iMajor) && (0 <= iMinor) )
return true;
}
#endif
return false;
}
long wxTaskBarIconEx::WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam )
{
wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::WindowProc - Function Begin"));
wxEventType eventType = 0;
long lReturnValue = 0;
if ( WM_CLOSE == msg )
{
wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_CLOSE Detected"));
wxCloseEvent eventClose(wxEVT_CLOSE_WINDOW);
ProcessEvent(eventClose);
if ( !eventClose.GetSkipped() )
lReturnValue = DefWindowProc((HWND) hWnd, msg, wParam, lParam);
else
lReturnValue = 0;
}
else if ( WM_TASKBARCREATED == msg )
{
wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_TASKBARCREATED Detected"));
eventType = wxEVT_TASKBAR_CREATED;
}
else if ( WM_TASKBARSHUTDOWN == msg )
{
wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_TASKBARSHUTDOWN Detected"));
eventType = wxEVT_TASKBAR_SHUTDOWN;
}
if (msg != sm_taskbarMsg)
lReturnValue = DefWindowProc((HWND) hWnd, msg, wParam, lParam);
if ( 0 == eventType )
{
switch (lParam)
{
case WM_LBUTTONDOWN:
eventType = wxEVT_TASKBAR_LEFT_DOWN;
break;
case WM_LBUTTONUP:
eventType = wxEVT_TASKBAR_LEFT_UP;
break;
case WM_RBUTTONDOWN:
eventType = wxEVT_TASKBAR_RIGHT_DOWN;
break;
case WM_RBUTTONUP:
eventType = wxEVT_TASKBAR_RIGHT_UP;
break;
case WM_LBUTTONDBLCLK:
eventType = wxEVT_TASKBAR_LEFT_DCLICK;
break;
case WM_RBUTTONDBLCLK:
eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
break;
case WM_MOUSEMOVE:
eventType = wxEVT_TASKBAR_MOVE;
break;
case WM_CONTEXTMENU:
eventType = wxEVT_TASKBAR_CONTEXT_MENU;
break;
case NIN_SELECT:
eventType = wxEVT_TASKBAR_SELECT;
break;
case NIN_KEYSELECT:
eventType = wxEVT_TASKBAR_KEY_SELECT;
break;
case NIN_BALLOONSHOW:
eventType = wxEVT_TASKBAR_BALLOON_SHOW;
break;
case NIN_BALLOONHIDE:
eventType = wxEVT_TASKBAR_BALLOON_HIDE;
break;
case NIN_BALLOONTIMEOUT:
eventType = wxEVT_TASKBAR_BALLOON_TIMEOUT;
break;
case NIN_BALLOONUSERCLICK:
eventType = wxEVT_TASKBAR_BALLOON_USERCLICK;
break;
}
}
if (eventType)
{
wxTaskBarIconExEvent event(eventType, this);
ProcessEvent(event);
lReturnValue = 0;
}
wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::WindowProc - Function End"));
return lReturnValue;
}
LRESULT APIENTRY wxTaskBarIconExWindowProc( HWND hWnd, unsigned msg, UINT wParam, LONG lParam )
{
return wxGetApp().GetTaskBarIcon()->WindowProc((WXHWND) hWnd, msg, wParam, lParam);
}
const char *BOINC_RCSID_46d006c50e = "$Id: taskbarex.cpp 11913 2007-01-19 23:45:19Z rwalton $";
Code: Select all
/////////////////////////////////////////////////////////////////////////
// File: wx/msw/taskbar.h
// Purpose: Defines wxTaskBarIcon class for manipulating icons on the
// Windows task bar.
// Author: Julian Smart
// Modified by:
// Created: 24/3/98
// RCS-ID: $Id: taskbarex.h 12240 2007-03-17 19:37:56Z rwalton $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////
#ifndef _TASKBAREX_H_
#define _TASKBAREX_H_
#if defined(__GNUG__) && !defined(__APPLE__)
#pragma interface "taskbarex.cpp"
#endif
// ----------------------------------------------------------------------------
// wxTaskBarIconEx
// ----------------------------------------------------------------------------
class wxTaskBarIconExEvent;
class wxTaskBarIconEx: public wxEvtHandler {
DECLARE_DYNAMIC_CLASS(wxTaskBarIconEx)
public:
wxTaskBarIconEx(void);
wxTaskBarIconEx( wxChar* szWindowTitle );
virtual ~wxTaskBarIconEx(void);
// Events
virtual void OnClose( wxCloseEvent& event );
virtual void OnTaskBarCreated( wxTaskBarIconExEvent& event );
// Accessors
inline WXHWND GetHWND() const { return m_hWnd; }
inline bool IsOK() const { return (m_hWnd != 0) ; }
inline bool IsIconInstalled() const { return m_iconAdded; }
// Operations
bool SetIcon(
const wxIcon& icon,
const wxString& tooltip = wxEmptyString
);
bool SetBalloon(
const wxIcon& icon,
const wxString title = wxEmptyString,
const wxString message = wxEmptyString,
unsigned int timeout = 5000,
unsigned int iconballoon = NIIF_INFO
);
bool RemoveIcon();
bool PopupMenu(wxMenu *menu); //, int x, int y);
// Implementation
static bool RegisterWindowClass();
static WXHWND CreateTaskBarWindow( wxChar* szWindowTitle );
static bool IsBalloonsSupported();
long WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam );
// Data members
protected:
WXHWND m_hWnd;
bool m_iconAdded;
NOTIFYICONDATA notifyData;
static bool sm_registeredClass;
static unsigned int sm_taskbarMsg;
private:
DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
// wxTaskBarIconEx events
// ----------------------------------------------------------------------------
class wxTaskBarIconExEvent : public wxEvent
{
public:
wxTaskBarIconExEvent(wxEventType evtType, wxTaskBarIconEx *tbIcon)
: wxEvent(wxID_ANY, evtType)
{
SetEventObject(tbIcon);
}
virtual wxEvent *Clone() const { return new wxTaskBarIconExEvent(*this); }
};
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_CREATED, 1557 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_CONTEXT_MENU, 1558 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_SELECT, 1559 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_KEY_SELECT, 1560 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_SHOW, 1561 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE, 1562 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT, 1563 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK, 1564 )
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN, 1565 )
END_DECLARE_EVENT_TYPES()
typedef void (wxEvtHandler::*wxTaskBarIconExEventFunction)(wxTaskBarIconExEvent&);
#define wxTaskBarIconExEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxTaskBarIconExEventFunction, &func)
#define wx__DECLARE_TASKBAREXEVT(evt, fn) \
wx__DECLARE_EVT0(wxEVT_TASKBAR_ ## evt, wxTaskBarIconExEventHandler(fn))
#define EVT_TASKBAR_CREATED(fn) wx__DECLARE_TASKBAREXEVT(CREATED, fn)
#define EVT_TASKBAR_CONTEXT_MENU(fn) wx__DECLARE_TASKBAREXEVT(CONTEXT_MENU, fn)
#define EVT_TASKBAR_SELECT(fn) wx__DECLARE_TASKBAREXEVT(SELECT, fn)
#define EVT_TASKBAR_KEY_SELECT(fn) wx__DECLARE_TASKBAREXEVT(KEY_SELECT, fn)
#define EVT_TASKBAR_BALLOON_SHOW(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_SHOW, fn)
#define EVT_TASKBAR_BALLOON_HIDE(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_HIDE, fn)
#define EVT_TASKBAR_BALLOON_TIMEOUT(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_TIMEOUT, fn)
#define EVT_TASKBAR_CONTEXT_USERCLICK(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_USERCLICK, fn)
#define EVT_TASKBAR_SHUTDOWN(fn) wx__DECLARE_TASKBAREXEVT(SHUTDOWN, fn)
#endif
// _TASKBAR_H_
How does ShowBallon works? I use the following code in my OnInit. But no balloon is shown.lowjoel wrote:OK guys this is the latest patch. This version allows for event handling to be done (took me half a day to solve the mystery of the undefined symbol )EVT_TASKBAR_BALLOON_SHOW will be triggered when the ballon is shown (ballons take turns to be shown)Code: Select all
Index: include/wx/taskbar.h =================================================================== RCS file: /pack/cvsroots/wxwindows/wxWindows/include/wx/taskbar.h,v retrieving revision 1.26 diff -u -r1.26 taskbar.h --- include/wx/taskbar.h 2005/05/04 18:52:03 1.26 +++ include/wx/taskbar.h 2005/08/03 03:42:59 @@ -18,6 +18,13 @@ #include "wx/event.h" +//Balloon Tooltips messages sent by the shell for MSW +#ifndef NIN_BALLOONSHOW + #define NIN_BALLOONSHOW 1026 + #define NIN_BALLOONHIDE 1028 + #define NIN_BALLOONUSERCLICK 1029 +#endif + class WXDLLIMPEXP_ADV wxTaskBarIconEvent; // ---------------------------------------------------------------------------- @@ -93,6 +100,9 @@ DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_RIGHT_UP,1554) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_LEFT_DCLICK,1555) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_RIGHT_DCLICK,1556) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_BALLOON_SHOW,1557) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_BALLOON_HIDE,1558) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV,wxEVT_TASKBAR_BALLOON_CLICK,1559) END_DECLARE_EVENT_TYPES() #define wxTaskBarIconEventHandler(func) \ @@ -108,6 +118,11 @@ #define EVT_TASKBAR_RIGHT_UP(fn) wx__DECLARE_TASKBAREVT(RIGHT_UP, fn) #define EVT_TASKBAR_LEFT_DCLICK(fn) wx__DECLARE_TASKBAREVT(LEFT_DCLICK, fn) #define EVT_TASKBAR_RIGHT_DCLICK(fn) wx__DECLARE_TASKBAREVT(RIGHT_DCLICK, fn) + +//MSW only events +#define EVT_TASKBAR_BALLOON_SHOW(fn) wx__DECLARE_TASKBAREVT(BALLOON_SHOW, fn) +#define EVT_TASKBAR_BALLOON_HIDE(fn) wx__DECLARE_TASKBAREVT(BALLOON_HIDE, fn) +#define EVT_TASKBAR_BALLOON_CLICK(fn) wx__DECLARE_TASKBAREVT(BALLOON_CLICK, fn) #endif // wxHAS_TASK_BAR_ICON 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/03 04:56:17 @@ -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/common/taskbarcmn.cpp =================================================================== RCS file: /pack/cvsroots/wxwindows/wxWindows/src/common/taskbarcmn.cpp,v retrieving revision 1.10 diff -u -r1.10 taskbarcmn.cpp --- src/common/taskbarcmn.cpp 2004/09/23 18:20:54 1.10 +++ src/common/taskbarcmn.cpp 2005/08/03 03:57:13 @@ -35,6 +35,9 @@ DEFINE_EVENT_TYPE( wxEVT_TASKBAR_RIGHT_UP ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_LEFT_DCLICK ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_RIGHT_DCLICK ) +DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_CLICK ) +DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE ) +DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_SHOW ) BEGIN_EVENT_TABLE(wxTaskBarIconBase, wxEvtHandler) 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/03 04:56:05 @@ -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)); } @@ -315,9 +314,26 @@ case WM_MOUSEMOVE: eventType = wxEVT_TASKBAR_MOVE; break; - + + case NIN_BALLOONSHOW: + //NIN_BALLOONSHOW - Sent when the balloon is shown (balloons are queued). + eventType = wxEVT_TASKBAR_BALLOON_SHOW; + break; + + case NIN_BALLOONHIDE: + //NIN_BALLOONHIDE - Sent when the balloon disappears - for example, when the + //icon is deleted. This message is not sent if the balloon is dismissed + //because of a timeout or a mouse click. + eventType = wxEVT_TASKBAR_BALLOON_HIDE; + break; + + case NIN_BALLOONUSERCLICK: + //NIN_BALLOONUSERCLICK - Sent when the balloon is dismissed because of a mouse click. + eventType = wxEVT_TASKBAR_BALLOON_CLICK; + break; + default: - break; + break; } if (eventType) @@ -328,6 +344,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, ¬ifyData); + else + return false; } #endif // __WIN95__
EVT_TASKBAR_BALLOON_HIDE will be triggered when the balloon is deleted by the program. It isnt sent when the user dismisses the balloon
EVT_TASKBAR_BALLOON_CLICK will be triggered when the user clicks on the balloon
Code: Select all
taskbar.SetIcon(wxICON(amain),_T("This is a testing"));
taskbar.ShowBalloon(_T("This is a test"),_T("This is a testing message"),10000,NIIF_INFO);
hi..
I have some errors with NOTIFYICONDATA struct.
I've tried anything but the problem is still there.
I'm using wxDev-c++ 6.10.2 with minGW 3.4.5
when i'm trying to create a balloontip in the compilation it says me:
the i've tried to write this to the resource file
but its still don'w work.. and now i have some conflict in definition of _WIN32_IE cause i need to write in the source file this
cause if i don't it says me [Warning] implicit declaration of function `InitCommonControlsEx'
when i write just define _WIN32_IE 0x0501 and delete the _WIN32_IE 0x0300 the program compiles good without errors but the balloontip doesn't work anyway..
how to fix this ?
thanks..
I have some errors with NOTIFYICONDATA struct.
I've tried anything but the problem is still there.
I'm using wxDev-c++ 6.10.2 with minGW 3.4.5
when i'm trying to create a balloontip in the compilation it says me:
Code: Select all
In function `WindowProcedure':
structure has no member named `uTimeout'
structure has no member named `szInfoTitle'
structure has no member named `szInfo'
Code: Select all
define _WIN32_IE 0x0501
Code: Select all
#ifndef _WIN32_IE
#define _WIN32_IE 0x0300
#endif
when i write just define _WIN32_IE 0x0501 and delete the _WIN32_IE 0x0300 the program compiles good without errors but the balloontip doesn't work anyway..
how to fix this ?
thanks..
I used the information here to adopt my code to generate ballon tooltips by my application. This worked perfect until wxwidgets version 2.8.6!
Unfortunately, my code stoped working when going to wxwidgets 2.8.8. The behavior when entering the ballon routine is as follows: The system tray adds an 'empty' icon field and the ballon tooltip is NOT shown (formerly it was). After the timeout the empty field is removed.
Here is the code which stopped working after 2.8.6:
Could anyone please guide me why this is not working anymore? Were there changes regarding this in wxwidgets releases after 2.8.6?
My platform is Windows XP (SP3) and MinGW/gcc.
Edit (2008-07-29): I've modified the taskbar sample which comes with wxwidgets (./samples/taskbar) and included the above function. The code compiled with the corresponding makefile and wxwidgets 2.8.4 works, the balloon tooltip is shown. The same code compiled with 2.8.8 doesnt work.
Thanks,
Stefan.
Unfortunately, my code stoped working when going to wxwidgets 2.8.8. The behavior when entering the ballon routine is as follows: The system tray adds an 'empty' icon field and the ballon tooltip is NOT shown (formerly it was). After the timeout the empty field is removed.
Here is the code which stopped working after 2.8.6:
Code: Select all
bool TaskBarIcon::ShowBalloonTip(wxString title, wxString message, unsigned int timeout, int icon)
{
NOTIFYICONDATA notifyData;
wxIcon tool_icon(tool_xpm);
memset(¬ifyData, 0, sizeof(NOTIFYICONDATA));
notifyData.cbSize = sizeof(NOTIFYICONDATA);
notifyData.uFlags = NIF_INFO | NIF_MESSAGE;
notifyData.hWnd = (HWND) parent->GetHWND();
notifyData.uID = 99;
notifyData.uTimeout = timeout;
notifyData.hIcon = (HICON) tool_icon.GetHICON();
notifyData.dwInfoFlags = icon | NIIF_NOSOUND | NIIF_INFO;
wxStrncpy(notifyData.szInfo, message.c_str(), WXSIZEOF(notifyData.szInfo));
wxStrncpy(notifyData.szInfoTitle, title.c_str(), WXSIZEOF(notifyData.szInfoTitle));
Shell_NotifyIcon(NIM_ADD, ¬ifyData);
wxSleep((int) (timeout / 100.0));
return (Shell_NotifyIcon(NIM_DELETE, ¬ifyData) != 0);
}
My platform is Windows XP (SP3) and MinGW/gcc.
Edit (2008-07-29): I've modified the taskbar sample which comes with wxwidgets (./samples/taskbar) and included the above function. The code compiled with the corresponding makefile and wxwidgets 2.8.4 works, the balloon tooltip is shown. The same code compiled with 2.8.8 doesnt work.
Thanks,
Stefan.
Last edited by Rayman on Sat Aug 30, 2008 2:04 pm, edited 1 time in total.
Meanwhile I found out what's wrong. The misbehaviour only appears with MinGW 3.4.5 and thus is independent of the wxWidgets version.
The balloon tooltip behaviour depends on the definitions of the NOTIFYICONDATA struct in shellapi.h.
More information can be found here:
http://groups.google.de/group/comp.soft ... 555?hl=de#
Stefan.
The balloon tooltip behaviour depends on the definitions of the NOTIFYICONDATA struct in shellapi.h.
More information can be found here:
http://groups.google.de/group/comp.soft ... 555?hl=de#
Stefan.
I have created a replacement wxTaskBarIcon class (wxTaskBarIconEx) that has support for balloon tips and enhanced functionality found in newer versions of Windows (large icons for e.g.). Due to time, I have yet to attempt to merge any of wxWidgets as a complete replacement. The class works on 2k+.
Hopefully this can be useful to someone and/or can be built upon.
Hopefully this can be useful to someone and/or can be built upon.
Code: Select all
#ifndef __WX_MSW_TASKBAR_ICON_EX__
#define __WX_MSW_TASKBAR_ICON_EX__
#if defined(__GNUG__) && !defined(__APPLE__)
#pragma interface "wxMswTaskbarIconEx.cpp"
#endif // defined(__GNUG__) && !defined(__APPLE__)
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4251)
#endif // defined(_MSC_VER)
#include <wx/wx.h>
#include <wx/taskbar.h>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif // defined(_MSC_VER)
// forwards
class wxMswTaskBarIconExWindow;
///////////////////////////////////////////////////////////////////////////////
// wxMswTaskBarIconEx
///////////////////////////////////////////////////////////////////////////////
enum EWxMswTaskBarIconExFeatures {
//
// Feature sets supported. Keep these in order!
// Also note that this class doesn't attempt to work with < Win2k
//
wxMSW_TASKBAREX_FEATURES_2K_PLUS = 1,
wxMSW_TASKBAREX_FEATURES_XP_PLUS = 2,
wxMSW_TASKBAREX_FEATURES_XP_SP2_PLUS = 3,
wxMSW_TASKBAREX_FEATURES_VISTA_PLUS = 4,
wxMSW_TASKBAREX_FEATURES_WIN7_PLUS = 5,
};
//
// Our own flags to cover NIIF_* flags
//
enum EWxMswTaskBarIconExShowBalloonFlags {
wxMSW_TASKBAREX_SB_NONE = 0x00000000, // NIIF_NONE
// icon flags - mutually exclusive
wxMSW_TASKBAREX_SB_INFO = 0x00000001, // NIIF_INFO
wxMSW_TASKBAREX_SB_WARNING = 0x00000002, // NIIF_WARNING
wxMSW_TASKBAREX_SB_ERROR = 0x00000003, // NIIF_ERROR
wxMSW_TASKBAREX_SB_NOSOUND = 0x00000010, // NIIF_NOSOUND (XPSP2+)
wxMSW_TASKBAREX_SB_LARGE_ICON = 0x00000020, // NIIF_LARGE_ICON (Vista+); wxIcon must be a large icon
wxMSW_TASKBAREX_SB_RESPECT_QUIET_TIME = 0x00000080, // NIIF_RESPECT_QUIET_TIME (Win7+)
wxMSW_TASKBAREX_SB_DEFAULT =
(wxMSW_TASKBAREX_SB_NOSOUND | wxMSW_TASKBAREX_SB_RESPECT_QUIET_TIME)
};
//
// Our own flags to replace NIF_* flags
//
enum EWxmswTaskBarIconExShowBalloonExFlags {
wxMSW_TASKBAREX_SB_EX_NONE = 0x00000000,
wxMSW_TASKBAREX_SB_EX_REALTIME = 0x00000001,
};
class wxMswTaskBarIconEx
: public wxTaskBarIconBase
{
DECLARE_DYNAMIC_CLASS(wxMswTaskBarIconEx)
public:
static const unsigned int TIMEOUT_MIN = 10000; // 10s
static const unsigned int TIMEOUT_MAX = 30000; // 30s
wxMswTaskBarIconEx();
~wxMswTaskBarIconEx();
// wxTaskBarIconBase virtuals
virtual bool SetIcon(const wxIcon& icon,
const wxString& tooltip = wxEmptyString);
virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu* pMenu);
// things found in the standard MSW impl. of wxTaskBarIcon
WXHWND GetHWND() const;
inline bool IsOk() const { return (NULL != m_win); }
inline bool IsIconInstalled() const { return m_bIconAdded; }
// wxMswTaskBarIconEx only methods
inline EWxMswTaskBarIconExFeatures GetFeatureSet() const { return m_featureSet; }
///
/// @brief Shows a balloon notification from the tray icon
///
/// @param [in] title Notification title (max length = 127 characters)
/// @param [in] msg Notification message (max length = 256, but 200
/// recommended max)
/// @param [in] userIcon User defined wxIcon to display. Pass wxIcon()
/// if using stock icons (see EShowBalloonFlags)
/// @param [in] flags Bitmask of EWxMswTaskBarIconExShowBalloonFlags values
/// @param [in] extraFlags Bitmask of EWxmswTaskBarExShowBalloonExFlags
/// values
/// @param [in] timeout Timeout value for notification. Note that in Vista+
/// this value is ignored (timeouts are handled by the system)
///
bool ShowBalloonNotification(const wxString& title, const wxString& msg,
const wxIcon& userIcon, const wxUint32 flags = wxMSW_TASKBAREX_SB_DEFAULT,
const wxUint32 extraFlags = wxMSW_TASKBAREX_SB_EX_NONE,
const unsigned int timeout = TIMEOUT_MAX);
protected:
friend class wxMswTaskBarIconExWindow;
long WindowProc(unsigned int msg, unsigned int wParam, long lParam);
void InitFeatureSet();
void RegisterWindowMessages();
EWxMswTaskBarIconExFeatures m_featureSet;
wxMswTaskBarIconExWindow* m_win;
bool m_bIconAdded;
wxIcon m_icon;
wxString m_tooltip;
};
////////////////////////////////////////////////////////////////////////////////
// wxMswTaskBarIconExEvent
////////////////////////////////////////////////////////////////////////////////
class wxMswTaskBarIconExEvent
: public wxEvent
{
public:
wxMswTaskBarIconExEvent(wxEventType evtType,
wxMswTaskBarIconEx* pTaskBarIcon)
: wxEvent(wxID_ANY, evtType)
{
SetEventObject(pTaskBarIcon);
}
virtual wxEvent* Clone() const { return new wxMswTaskBarIconExEvent(*this); }
private:
DECLARE_NO_ASSIGN_CLASS(wxMswTaskBarIconExEvent)
};
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_CREATED, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_CONTEXT_MENU, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_SELECT, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_KEY_SELECT, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_SHOW, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_HIDE, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_TIMEOUT, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_USERCLICK, wxID_ANY)
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_SHUTDOWN, wxID_ANY)
END_DECLARE_EVENT_TYPES()
typedef void (wxEvtHandler::*wxMswTaskBarIconExEventFunction)(wxMswTaskBarIconExEvent&);
#define wxMswTaskBarIconExEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMswTaskBarIconExEventFunction, &func)
#define wx__DECLARE_MSW_TASKBAR_EX_EVT(evt, fn) \
wx__DECLARE_EVT0(wxEVT_TASKBAR_ ## evt, wxMswTaskBarIconExEventHandler(fn))
#define EVT_TASKBAR_CREATED(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(CREATED, fn)
#define EVT_TASKBAR_CONTEXT_MENU(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(CONTEXT_MENU, fn)
#define EVT_TASKBAR_SELECT(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(SELECT, fn)
#define EVT_TASKBAR_KEY_SELECT(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(KEY_SELECT, fn)
#define EVT_TASKBAR_BALLOON_SHOW(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(BALLOON_SHOW, fn)
#define EVT_TASKBAR_BALLOON_HIDE(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(BALLOON_HIDE, fn)
#define EVT_TASKBAR_BALLOON_TIMEOUT(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(BALLOON_TIMEOUT, fn)
#define EVT_TASKBAR_CONTEXT_USERCLICK(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(BALLOON_USERCLICK, fn)
#define EVT_TASKBAR_SHUTDOWN(fn) wx__DECLARE_MSW_TASKBAR_EX_EVT(SHUTDOWN, fn)
#endif // !__WX_MSW_TASKBAR_ICON_EX__
Code: Select all
#if defined(_MSC_VER)
// disable stupid STL warnings
#pragma warning(push)
#pragma warning(disable:4251)
#endif // defined(__WXMSW__)
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif // defined(__BORLANDC__)
#if !defined(WX_PRECOMP)
#include "wx/window.h"
#include "wx/frame.h"
#include "wx/utils.h"
#include "wx/menu.h"
#endif // !defined(WX_PRECOMP)
#include "wx/msw/private.h"
#include "wx/msw/winundef.h"
#include "wx/msw/ole/uuid.h"
#include "wx/dynlib.h"
#include "wxMswTaskBarIconEx.h"
#if !defined(__WXWINCE__)
#include <winreg.h>
#include <shellapi.h>
#include <shlwapi.h>
#endif // !defined(__WXWINCE__)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_CREATED)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_CONTEXT_MENU)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_SELECT)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_KEY_SELECT)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_SHOW)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_HIDE)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_TIMEOUT)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_BALLOON_USERCLICK)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_TASKBAR_SHUTDOWN)
// :TODO: add support for dwState (2k+) and hidden, e.g. HideIcon(const bool bHide)
// globals
UINT gs_msgWxMswTaskBar = 0;
UINT gs_msgRestartWxMswTaskBar = 0;
static const GUID gs_wxMswTaskBarIconExGuid = {
0x575a3b13, 0xe5f3, 0x475d, {0xbd, 0xf0, 0x7c, 0xad, 0xcc, 0xd0, 0x9a, 0xe9}
};
////////////////////////////////////////////////////////////////////////////////
// wxMswTaskBarIconExWindow
//
// Notes taken from wxTaskBarIconWindow:
//
// "NB: this class serves two purposes:
// 1. win32 needs a HWND associated with taskbar icon, this provides it
// 2. we need wxTopLevelWindow so that the app doesn't exit when
// last frame is closed but there still is a taskbar icon"
//
////////////////////////////////////////////////////////////////////////////////
class wxMswTaskBarIconExWindow
: public wxFrame
{
public:
wxMswTaskBarIconExWindow(wxMswTaskBarIconEx* pTaskBarIcon)
: wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, 0)
, m_pTaskBarIcon(pTaskBarIcon)
{
}
WXLRESULT MSWWindowProc(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
{
if(msg == gs_msgRestartWxMswTaskBar || msg == gs_msgWxMswTaskBar) {
return m_pTaskBarIcon->WindowProc(msg, wParam, lParam);
} else {
return wxFrame::MSWWindowProc(msg, wParam, lParam);
}
}
private:
wxMswTaskBarIconEx* m_pTaskBarIcon;
};
////////////////////////////////////////////////////////////////////////////////
// MswNotifyIconData - wrapper around NOTIFYICONDATA
////////////////////////////////////////////////////////////////////////////////
struct MswNotifyIconData
: public NOTIFYICONDATA
{
MswNotifyIconData(WXHWND hwnd, EWxMswTaskBarIconExFeatures featureSet)
{
memset(this, 0, sizeof(NOTIFYICONDATA));
//
// See MSDN remarks about NOTIFYICONDATA & cbSize here:
// http://msdn.microsoft.com/en-us/library/bb773352%28VS.85%29.aspx
//
if(featureSet >= wxMSW_TASKBAREX_FEATURES_VISTA_PLUS) {
this->cbSize = sizeof(NOTIFYICONDATA);
} else if(featureSet >= wxMSW_TASKBAREX_FEATURES_XP_PLUS) {
this->cbSize = NOTIFYICONDATA_V3_SIZE;
} else {
this->cbSize = NOTIFYICONDATA_V2_SIZE;
}
this->hWnd = (HWND)hwnd;
this->uCallbackMessage = gs_msgWxMswTaskBar;
this->uFlags = NIF_MESSAGE;
//
// special setup depending on platform
//
// Use guidItem for Win7+ otherwise uID
//
// :TODO: look into this further - the icon must be "registered", which means this may not work as our icon can be in a resource
/*if(featureSet >= wxMSW_TASKBAREX_FEATURES_WIN7_PLUS) {
this->uFlags |= NIF_GUID;
this->guidItem = gs_wxMswTaskBarIconExGuid;
} else {*/
this->uID = 99;
//}
//
// set the version for platforms that support it (2k+)
//
if(featureSet >= wxMSW_TASKBAREX_FEATURES_VISTA_PLUS) {
this->uVersion = NOTIFYICON_VERSION_4;
} else {
this->uVersion = NOTIFYICON_VERSION;
}
}
};
////////////////////////////////////////////////////////////////////////////////
// wxMswTaskBarIconEx
////////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC_CLASS(wxMswTaskBarIconEx, wxEvtHandler);
wxMswTaskBarIconEx::wxMswTaskBarIconEx()
: m_win(NULL)
, m_bIconAdded(false)
, m_featureSet(wxMSW_TASKBAREX_FEATURES_2K_PLUS)
{
InitFeatureSet();
RegisterWindowMessages();
}
wxMswTaskBarIconEx::~wxMswTaskBarIconEx()
{
if(m_bIconAdded) {
RemoveIcon();
}
if(m_win) {
m_win->Destroy();
}
}
/*virtual*/
bool wxMswTaskBarIconEx::SetIcon(const wxIcon& icon,
const wxString& tooltip /*= wxEmptyString*/)
{
if(!m_win) {
m_win = new wxMswTaskBarIconExWindow(this);
}
m_icon = icon;
m_tooltip = tooltip;
MswNotifyIconData iconData(GetHwndOf(m_win), m_featureSet);
if(icon.Ok()) {
iconData.uFlags |= NIF_ICON;
iconData.hIcon = GetHiconOf(icon);
}
//
// set the tip even if empty so it can be removed
//
iconData.uFlags |= NIF_TIP;
if(!tooltip.IsEmpty()) {
wxStrncpy(iconData.szTip, tooltip.c_str(), WXSIZEOF(iconData.szTip));
}
bool success = (TRUE == Shell_NotifyIcon(
m_bIconAdded ? NIM_MODIFY : NIM_ADD,
&iconData));
if(!success) {
wxLogMessage(wxSysErrorMsg());
}
if(!m_bIconAdded && success) {
m_bIconAdded = true;
//
// Instruct Windows to respect the uVersion member
//
if(TRUE != Shell_NotifyIcon(NIM_SETVERSION, &iconData)) {
wxLogMessage(wxSysErrorMsg());
}
}
return success;
}
/*virtual*/
bool wxMswTaskBarIconEx::RemoveIcon()
{
if(!m_bIconAdded) {
return false;
}
m_bIconAdded = false;
MswNotifyIconData iconData(GetHwndOf(m_win), m_featureSet);
return (TRUE == Shell_NotifyIcon(NIM_DELETE, &iconData));
}
/*virtual*/
bool wxMswTaskBarIconEx::PopupMenu(wxMenu* pMenu)
{
wxASSERT_MSG(NULL != m_win, wxT("taskbar icon not initialized"));
static bool s_bInPopup = false;
if(s_bInPopup) {
return false;
}
s_bInPopup = true;
int x;
int y;
::wxGetMousePosition(&x, &y);
m_win->Move(x, y);
m_win->PushEventHandler(this);
pMenu->UpdateUI();
//
// From origial wxTaskBarIcon::PopupMenu():
// "the SetForegroundWindow() and PostMessage() calls are needed to work
// around Win32 bug with the popup menus shown for the notifications as
// documented at http://support.microsoft.com/kb/q135788/"
//
::SetForegroundWindow(GetHwndOf(m_win));
bool retVal = m_win->PopupMenu(pMenu, 0, 0);
::PostMessage(GetHwndOf(m_win), WM_NULL, 0, 0L);
m_win->PopEventHandler(false);
s_bInPopup = false;
return retVal;
}
WXHWND wxMswTaskBarIconEx::GetHWND() const
{
return (NULL == m_win ? (WXHWND)NULL : GetHwndOf(m_win));
}
bool
wxMswTaskBarIconEx::ShowBalloonNotification(const wxString& title,
const wxString& msg,
const wxIcon& userIcon,
const wxUint32 flags /*= SHOW_BALLOON_DEFAULT*/,
const wxUint32 extraFlags /*= SHOW_BALLOON_EX_NONE*/,
const unsigned int timeout /*= TIMEOUT_MAX*/)
{
if(!IsOk() && !SetIcon(m_icon, m_tooltip)) {
return false;
}
MswNotifyIconData iconData(GetHwndOf(m_win), m_featureSet);
//
// Standard flags for balloon hints
//
iconData.uFlags |= NIF_INFO;
//
// XP SP2+ allows for the use of NIIF_USER (our userIcon)
//
if(userIcon.Ok() && m_featureSet >= wxMSW_TASKBAREX_FEATURES_XP_PLUS) {
//
// if in Vista+ use the hBalloonIcon else hIcon
//
if(m_featureSet >= wxMSW_TASKBAREX_FEATURES_VISTA_PLUS) {
iconData.hBalloonIcon = GetHiconOf(userIcon);
} else {
iconData.uFlags |= NIF_ICON;
iconData.hIcon = GetHiconOf(userIcon);
}
iconData.dwInfoFlags |= NIIF_USER;
} else {
if(flags & wxMSW_TASKBAREX_SB_INFO) {
iconData.dwInfoFlags |= NIIF_INFO;
} else if(flags & wxMSW_TASKBAREX_SB_WARNING) {
iconData.dwInfoFlags |= NIIF_WARNING;
} else if(flags & wxMSW_TASKBAREX_SB_ERROR) {
iconData.dwInfoFlags |= NIIF_ERROR;
} else {
// provide a default
iconData.dwInfoFlags |= NIIF_INFO;
}
}
//
// Vista+ also allows for large icons in balloon tips
//
if(m_featureSet >= wxMSW_TASKBAREX_FEATURES_VISTA_PLUS &&
(flags & wxMSW_TASKBAREX_SB_LARGE_ICON))
{
//
// From MSDN:
// "0x00000010. Windows Vista and later. The large version
// of the icon should be used as the notification icon.
// This corresponds to the icon with dimensions
// SM_CXICON x SM_CYICON. If this flag is not set, the icon
// with dimensions XM_CXSMICON x SM_CYSMICON is used.
//
// * This flag can be used with all stock icons.
//
// * Applications that use older customized icons
// (NIIF_USER with hIcon) must provide a new
// SM_CXICON x SM_CYICON version in the tray icon (hIcon).
// These icons are scaled down when they are displayed in
// the System Tray or System Control Area (SCA).
//
// * New customized icons (NIIF_USER with hBalloonIcon)
// must supply an SM_CXICON x SM_CYICON version in the
// supplied icon (hBalloonIcon)."
//
// If we're using userIcon instead of stock icons, validate it's OK
// otherwise fall back to default stock
//
if(userIcon.Ok()) {
int largeIconX = ::wxSystemSettings::GetMetric(wxSYS_ICON_X);
int largeIconY = ::wxSystemSettings::GetMetric(wxSYS_ICON_Y);
if(userIcon.GetWidth() >= largeIconX ||
userIcon.GetHeight() >= largeIconY)
{
iconData.dwInfoFlags |= NIIF_LARGE_ICON;
} else {
iconData.hIcon = 0;
iconData.hBalloonIcon = 0;
iconData.dwInfoFlags =~ NIIF_USER;
iconData.dwInfoFlags |= NIIF_INFO;
}
} else {
iconData.dwInfoFlags |= NIIF_LARGE_ICON;
}
}
if(m_featureSet <= wxMSW_TASKBAREX_FEATURES_XP_PLUS) {
iconData.uTimeout = timeout;
}
//
// Mix in the rest of the flags
//
// :TODO: clean this up, this is a dumb way of doing it me thinks
if(flags & wxMSW_TASKBAREX_SB_NOSOUND) {
iconData.dwInfoFlags |= wxMSW_TASKBAREX_SB_NOSOUND;
}
if(flags & wxMSW_TASKBAREX_SB_RESPECT_QUIET_TIME) {
iconData.dwInfoFlags |= wxMSW_TASKBAREX_SB_RESPECT_QUIET_TIME;
}
if(extraFlags & wxMSW_TASKBAREX_SB_EX_REALTIME) {
iconData.uFlags |= wxMSW_TASKBAREX_SB_EX_REALTIME;
}
//
// Populate the actual tooltip message data
//
wxStrncpy(iconData.szInfo, msg.c_str(), WXSIZEOF(iconData.szInfo));
wxStrncpy(iconData.szInfoTitle, title.c_str(),
WXSIZEOF(iconData.szInfoTitle));
return Shell_NotifyIcon(NIM_MODIFY, &iconData) ? true : false;
}
void wxMswTaskBarIconEx::InitFeatureSet()
{
int major;
int minor;
::wxGetOsVersion(&major, &minor);
if(major >= 6 && minor >= 1) {
m_featureSet = wxMSW_TASKBAREX_FEATURES_WIN7_PLUS;
} else if(major >= 6 && 0 == minor) {
m_featureSet = wxMSW_TASKBAREX_FEATURES_VISTA_PLUS;
} else if(major >= 5 && 1 == minor) {
m_featureSet = wxMSW_TASKBAREX_FEATURES_XP_PLUS;
//
// It's XP - see if it's SP2+
//
OSVERSIONINFOEX verInfo;
memset(&verInfo, 0, sizeof(OSVERSIONINFOEX));
verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if(::GetVersionEx((LPOSVERSIONINFO)&verInfo) && verInfo.wServicePackMajor >= 3) {
m_featureSet = wxMSW_TASKBAREX_FEATURES_XP_SP2_PLUS;
}
} else if(major >= 5 && 0 == minor) {
m_featureSet = wxMSW_TASKBAREX_FEATURES_2K_PLUS;
}
}
void wxMswTaskBarIconEx::RegisterWindowMessages()
{
static bool s_bReg = false;
if(!s_bReg) {
gs_msgRestartWxMswTaskBar =
::RegisterWindowMessage(wxT("TaskbarCreated"));
gs_msgWxMswTaskBar =
::RegisterWindowMessage(wxT("wxMswTaskBarIconExMessage"));
s_bReg = true;
}
}
long wxMswTaskBarIconEx::WindowProc(unsigned int msg, unsigned int wParam,
long lParam)
{
wxEventType eventType = 0;
//
// Handle re-draw
//
if(gs_msgRestartWxMswTaskBar == msg) {
m_bIconAdded = false;
SetIcon(m_icon, m_tooltip);
return 0;
}
wxASSERT(gs_msgWxMswTaskBar == msg); // the only other reason we should be called
//
// Using NOTIFYICON_VERSION_4, we must interpret lParam & wParam
// differently
//
long winMsg;
if(m_featureSet >= wxMSW_TASKBAREX_FEATURES_VISTA_PLUS) {
winMsg = LOWORD(lParam);
} else {
winMsg = lParam;
}
switch(winMsg) {
case WM_LBUTTONDOWN :
eventType = wxEVT_TASKBAR_LEFT_DOWN;
break;
case WM_LBUTTONUP :
eventType = wxEVT_TASKBAR_LEFT_UP;
break;
case WM_RBUTTONDOWN :
eventType = wxEVT_TASKBAR_RIGHT_DOWN;
break ;
case WM_RBUTTONUP:
eventType = wxEVT_TASKBAR_RIGHT_UP;
break ;
case WM_LBUTTONDBLCLK:
eventType = wxEVT_TASKBAR_LEFT_DCLICK;
break ;
case WM_RBUTTONDBLCLK :
eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
break;
case WM_MOUSEMOVE :
eventType = wxEVT_TASKBAR_MOVE;
break;
case WM_CONTEXTMENU :
eventType = wxEVT_TASKBAR_CONTEXT_MENU;
break;
case NIN_SELECT :
eventType = wxEVT_TASKBAR_SELECT;
break;
case NIN_KEYSELECT :
eventType = wxEVT_TASKBAR_KEY_SELECT;
break;
case NIN_BALLOONSHOW :
eventType = wxEVT_TASKBAR_BALLOON_SHOW;
break;
case NIN_BALLOONHIDE :
eventType = wxEVT_TASKBAR_BALLOON_HIDE;
break;
case NIN_BALLOONTIMEOUT :
eventType = wxEVT_TASKBAR_BALLOON_TIMEOUT;
break;
case NIN_BALLOONUSERCLICK :
eventType = wxEVT_TASKBAR_BALLOON_USERCLICK;
break;
}
if(eventType) {
wxMswTaskBarIconExEvent evt(eventType, this);
ProcessEvent(evt);
}
return 0;
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif // defined(__WXMSW__)