A.第一種方法是通過MFC來實作的,從網上找的,red已經注明。
如果我們在程式最小化時采用在系統工作列中的小圖示,就象金山詞霸一樣,單擊左鍵可以
實作最大最小化,單擊右鍵有快捷菜單,那麼整個程式會顯的很簡潔。
采用SDK的Shell_NotifyIcon等API可以實作系統工作列的小圖示,但是程式員必須仔細了解
這些API的具體用法,Chris Maunder 開發的系統工作列類CSystemTray封裝了這些API的功能,
使MFC程式員可以友善的實作具有系統工作列小圖示的程式。
---- CsytemTray的功能很多,看一看它的成員函數就可以知道其大緻功能了。
BOOL Enabled() { return m_bEnabled; }
BOOL Visible() { return !m_bHidden; }
//Create the tray icon
Create(CWnd* pWnd, UINT uCallbackMessage,
LPCTSTR szTip, HICON icon, UINT uID);
//Change or retrieve the Tooltip text
BOOL SetTooltipText(LPCTSTR pszTooltipText);
BOOL SetTooltipText(UINT nID);
CString GetTooltipText() const;
//Change or retrieve the icon displayed
BOOL SetIcon(HICON hIcon);
BOOL SetIcon(LPCTSTR lpIconName);
BOOL SetIcon(UINT nIDResource);
BOOL SetStandardIcon(LPCTSTR lpIconName);
BOOL SetStandardIcon(UINT nIDResource);
HICON GetIcon() const;
void HideIcon();
void ShowIcon();
void RemoveIcon();
void MoveToRight();
//Change or retrieve the window to
send notification messages to
BOOL SetNotificationWnd(CWnd* pNotifyWnd);
CWnd* GetNotificationWnd() const;
下面是實作步驟:
(1)首先在Project中加入CsystemTray類的.cpp和.h檔案,這樣在Workspace的
ClassView中可以看到CsystemTray類。
(2)然後在CframeWnd的派生類的頭檔案中
a.加入WM_ICON_NOTIFY 的消息定義
#define WM_ICON_NOTIFY WM_USER+1
b.在CframeWnd的派生類中添加變量
CSystemTray m_TrayIcon;
c.在CframeWnd的派生類的CPP檔案中添加消息映射
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
... ...
ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
END_MESSAGE_MAP()
(3)在CframeWnd的派生類中添加成員函數
LRESULT CMainFrame::OnTrayNotification(WPARAM wParam, LPARAM lParam)
{
return m_TrayIcon.OnTrayNotification(wParam, lParam);
}
(4)定義快捷菜單
在MENU中添加新菜單IDR_POPUP_MENU,可以如一般的菜單一樣從ClassWizard中定義其響應。
(5)在CsystemTray中修改OnTrayNotification函數,
定義你希望實作的效果,如單擊左鍵可以實作最大最小化,單擊右鍵有快捷菜單等功能。
LRESULT CSystemTray::OnTrayNotification(UINT wParam, LONG lParam)
{
//Return quickly if its not for this tray icon
if (wParam != m_tnd.uID)
return 0L;
CMenu menu, *pSubMenu;
//定義單擊右鍵有快捷菜單
if (LOWORD(lParam) == WM_RBUTTONUP)
{
if (!menu.LoadMenu(m_tnd.uID))
return 0;
if (!(pSubMenu = menu.GetSubMenu(0)))
return 0;
// Make first menu item the default (bold font)
::SetMenuDefaultItem(pSubMenu- >m_hMenu, 0, TRUE);
//Display and track the popup menu
CPoint pos;
GetCursorPos(&pos);
::SetForegroundWindow(m_tnd.hWnd);
::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x,
pos.y, 0, m_tnd.hWnd, NULL);
// BUGFIX: See "PRB: Menus for Notification
Icons Don't Work Correctly"
::PostMessage(m_tnd.hWnd, WM_NULL, 0, 0);
menu.DestroyMenu();
}
//定義輕按兩下左鍵有産生單擊快捷菜單第一項功能的響應
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
{
if (!menu.LoadMenu(m_tnd.uID)) return 0;
if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
// double click received, the default action is to execute first menu item
::SetForegroundWindow(m_tnd.hWnd);
::SendMessage(m_tnd.hWnd, WM_COMMAND,
pSubMenu->GetMenuItemID(0), 0);
menu.DestroyMenu();
}
//定義單擊左鍵為最小化或恢複視窗
else if (LOWORD(lParam) == WM_LBUTTONUP)
{
if(AfxGetMainWnd()->IsIconic()!=0)
{
EnableWindow(m_tnd.hWnd,TRUE);
ShowWindow(m_tnd.hWnd,SW_SHOW);
ShowWindow(m_tnd.hWnd,SW_RESTORE);
}
else
{
ShowWindow(m_tnd.hWnd,SW_SHOWMINIMIZED);
EnableWindow(m_tnd.hWnd,FALSE);
ShowWindow(m_tnd.hWnd,SW_HIDE);
}
}
return 1;
}
(6)在CmainFrame的派生類中添加WM_SIZE的消息響應函數,這可以實作程式最小化時
隻在系統工作列中有一個小圖示,而不會在一般工作列中有顯示
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
if(nType==SIZE_MINIMIZED)
{
EnableWindow(FALSE);
ShowWindow(SW_HIDE);
}
}
看起來似乎這樣實作步驟也不少,但是當我們再開發新的功能時會很友善,程式會更容易
了解與開發。如我們可以很友善實作動态小圖示。
a.我們隻需在CmainFrame的派生類中添加一個定時器,
SetTimer(IDW_TIMER1,500,NULL);
icon_id=0;
b.對定時發出的WM_TIME消息進行處理,例如時間到了就換一個圖示,圖示的變化可以根據
自己的喜好及實際情況定義,此處有3個圖示輪流變化。
void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//change the icon
//icon_id from 0 to 2 every 0.5s
if(nIDEvent ==IDW_TIMER1)
{
if(icon_id==0)
{
hIcon=AfxGetApp()->LoadIcon(IDR_ICON0);
icon_id++;
}
else if(icon_id==1)
{
hIcon=AfxGetApp()->LoadIcon(IDR_ICON1);
icon_id++;
}
else if(icon_id=2)
{
hIcon=AfxGetApp()->LoadIcon(IDR_ICON2);
icon_id=0;
}
m_TrayIcon.SetIcon(hIcon);
}
CFrameWnd::OnTimer(nIDEvent);
}
B.第二種方法是通過消息去處理;
建立的基于對話框,看下面說明:
a.在WM_SIZE 消息裡面處理有檢測到最小化的動作時,作如下的操作:
主要是從代碼中摘取的,看主要的代碼就好了:
case WM_SIZE:
if(wParam == SIZE_MINIMIZED)//if wparam == minimized,then add the icon into the taskbar only;
{
if(!g_bAddIcon)
{
if(!AddIconToTaskbar(hDlg))
MessageBox(0,"Add Icon to task bar ,failed!",0,0);
}
ShowWindow(hDlg,SW_HIDE);//hide the window;
}
break;
b.在WM_COMMAND消息中要remove掉圖示;
switch (LOWORD(wParam))
{
case IDCANCEL:
if (!g_bColor)
{
KillTimer(hDlg, 1);
}
portio.ShutdownDriver(szDriverName);
CloseHandle(hLogFile);
g_bRemove = TRUE;
AddIconToTaskbar(hDlg);
DeleteObject(hBrush);
DeleteObject(hCurrentFont);
EndDialog(hDlg, FALSE);
return TRUE;
}
C.關鍵函數 AddIconTaskBar(HWND hwnd),主要處理如下:
BOOL AddIconToTaskbar(HWND hwnd)
{
NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
strcpy(nid.szTip, "XXX");
nid.hWnd = hwnd;
nid.uID = 100;
nid.uFlags = NIF_ICON | NIF_MESSAGE;
nid.hIcon = LoadIcon(gst_hInstance, MAKEINTRESOURCE(IDI_TEMP));
nid.uCallbackMessage = WM_TASKMOUSE;//here to catch the mouse move message
if (nid.hIcon == NULL)
{
MessageBox(0, "Can not add icon ,failed!", 0, 0);
return FALSE;
}
if (!g_bRemove)
{
if (Shell_NotifyIcon(NIM_ADD, &nid))//add the icon into the taskbar
{
g_bAddIcon = TRUE;
return TRUE;
}
else
return FALSE;
}
else
{
Shell_NotifyIcon(NIM_DELETE, &nid);//delete the icon from the taskbar
return TRUE;
}
}
here, 處理滑鼠的動作如下,比較粗糙:
case WM_TASKMOUSE:
if( lParam == WM_LBUTTONDBLCLK)
{
ShowWindow(hDlg,SW_SHOWNORMAL);//double left click to show the window
}
break;
轉載請注明,謝謝合作!
red 2010/02/10