TrayIcon
一直以为右下角气泡提醒是自己做的一个对话框.....才知道是TRAYICON的东东.
找到一篇好文章
http://www.codeproject.com/Articles/3147/WTL-Tray-Icon-Template
在此基础上少加改动,把气泡添上了..呵呵.
1 #pragma once 2 3 template <typename T> 4 class ATL_NO_VTABLE CTrayIconImpl 5 { 6 UINT WM_TRAYICON; 7 NOTIFYICONDATA m_nid; 8 bool m_bInstalled; 9 public: 10 CTrayIconImpl() : m_bInstalled( false ) 11 { 12 memset( &m_nid, 0, sizeof( NOTIFYICONDATA ) ); 13 m_nid.cbSize = sizeof( NOTIFYICONDATA ); 14 15 WM_TRAYICON = ::RegisterWindowMessage( TEXT( "WM_TRAYICON" ) ); 16 } 17 18 ~CTrayIconImpl() 19 { 20 if ( m_bInstalled ) 21 { 22 m_nid.uFlags = 0; 23 Shell_NotifyIcon( NIM_DELETE, &m_nid ); 24 } 25 } 26 27 bool InstallTrayIcon( HICON hIcon, LPCTSTR lpszTip = NULL, UINT uID = -1 ) 28 { 29 T* pT = static_cast<T*>( this ); 30 31 if ( m_bInstalled ) 32 { 33 return false; 34 } 35 36 m_nid.hWnd = pT->m_hWnd; 37 m_nid.uID = uID; 38 m_nid.hIcon = hIcon; 39 m_nid.uCallbackMessage = WM_TRAYICON; 40 41 if ( lpszTip != NULL ) 42 { 43 m_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 44 lstrcpy( m_nid.szTip, lpszTip ); 45 } 46 else 47 { 48 m_nid.uFlags = NIF_MESSAGE | NIF_ICON; 49 } 50 51 m_bInstalled = Shell_NotifyIcon( NIM_ADD, &m_nid ) ? true : false; 52 53 return m_bInstalled; 54 } 55 56 57 bool RemoveTrayIcon() 58 { 59 if ( m_bInstalled ) 60 { 61 m_nid.uFlags = 0; 62 63 if ( Shell_NotifyIcon( NIM_DELETE, &m_nid ) ) 64 { 65 m_bInstalled = false; 66 return true; 67 } 68 } 69 70 return false; 71 } 72 73 bool SetTrayTip( LPCTSTR lpszTip ) 74 { 75 if ( lpszTip != NULL ) 76 { 77 m_nid.uFlags = NIF_TIP; 78 lstrcpy( m_nid.szTip, lpszTip ); 79 return Shell_NotifyIcon( NIM_MODIFY, &m_nid ) ? true : false; 80 } 81 82 return false; 83 } 84 85 bool SetTrayInfo( LPCTSTR lpszInfo, LPCTSTR lpszTitle, UINT uTimeout = 3000, DWORD dwInfoFlags = NIIF_INFO ) 86 { 87 if ( lpszInfo != NULL ) 88 { 89 m_nid.uFlags = NIF_INFO; 90 m_nid.uTimeout = uTimeout; 91 m_nid.dwInfoFlags = dwInfoFlags; 92 lstrcpy( m_nid.szInfo, lpszInfo ); 93 lstrcpy( m_nid.szInfoTitle, lpszTitle ? lpszTitle : TEXT( "" ) ); 94 return Shell_NotifyIcon( NIM_MODIFY, &m_nid ) ? true : false; 95 } 96 97 return false; 98 } 99 100 BEGIN_MSG_MAP( CTrayIconImpl<T> ) 101 MESSAGE_HANDLER( WM_TRAYICON, OnTrayIcon ) 102 MESSAGE_HANDLER( WM_SYSCOMMAND, OnSysCommand ) 103 END_MSG_MAP() 104 105 void PrepareTrayMenu( HMENU hMenu ) 106 { 107 ATLASSERT( FALSE ); 108 109 /* 110 CMenuHandle menu(hMenu); 111 menu.EnableMenuItem(ID_TEST_DISABLED, MF_GRAYED); 112 menu.CheckMenuItem(ID_TEST_CHECKED, MF_CHECKED); 113 */ 114 } 115 116 LRESULT OnTrayIcon( UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ) 117 { 118 POINT pt; 119 HMENU hMenu, hPopup; 120 121 T* pT = static_cast<T*>( this ); 122 123 if ( wParam != m_nid.uID ) 124 { 125 return 0; 126 } 127 128 switch ( LOWORD( lParam ) ) 129 { 130 case WM_RBUTTONUP: 131 ::GetCursorPos( &pt ); 132 133 hMenu = ::LoadMenu( ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE( m_nid.uID ) ); 134 135 if ( !hMenu )return 0; 136 137 hPopup = ::GetSubMenu( hMenu, 0 ); 138 pT->PrepareTrayMenu( hPopup ); 139 140 ::SetForegroundWindow( pT->m_hWnd ); 141 ::TrackPopupMenu( hPopup, TPM_RIGHTALIGN, pt.x, pt.y, 0, pT->m_hWnd, NULL ); 142 // BUGFIX: See "PRB: Menus for Notification Icons Do Not Work Correctly" 143 pT->PostMessage( WM_NULL ); 144 145 ::DestroyMenu( hMenu ); 146 break; 147 148 case WM_LBUTTONDBLCLK: 149 if ( pT->IsIconic() ) 150 { 151 pT->ShowWindow( SW_RESTORE ); 152 } 153 else 154 { 155 if ( !pT->IsWindowVisible() ) 156 { 157 pT->ShowWindow( SW_SHOW ); 158 ::BringWindowToTop( pT->m_hWnd ); 159 ::SetForegroundWindow( pT->m_hWnd ); 160 } 161 else 162 { 163 pT->ShowWindow( SW_HIDE ); 164 } 165 } 166 167 break; 168 169 case NIN_BALLOONUSERCLICK: 170 if ( pT->IsIconic() ) 171 { 172 pT->ShowWindow( SW_RESTORE ); 173 } 174 else 175 { 176 if ( !pT->IsWindowVisible() ) 177 { 178 pT->ShowWindow( SW_SHOW ); 179 ::BringWindowToTop( pT->m_hWnd ); 180 } 181 182 ::SetForegroundWindow( pT->m_hWnd ); 183 } 184 185 break; 186 } 187 188 return 0; 189 } 190 191 LRESULT OnSysCommand( UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled ) 192 { 193 T* pT = static_cast<T*>( this ); 194 195 if ( wParam == SC_MINIMIZE ) 196 { 197 pT->ShowWindow( SW_HIDE ); 198 bHandled = TRUE; 199 } 200 else 201 { 202 bHandled = FALSE; 203 } 204 205 return 0; 206 } 207 };