在Windows 95任務條的右邊有一個地區被稱為通知區域,在其中可以顯示一些應用程式的表徵圖,用按一下滑鼠其中的表徵圖一般能彈出應用程式的菜單,雙擊則能顯示應用程式的完整視窗介面。時鐘和音量控制是任務條通知區最常見的表徵圖。任務條通知區編程可以通過Windows 95外殼編程介面函數Shell_NotifyIcon來實現,該函數在shellapi.h標頭檔中聲明,其原型如下:
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid);
dwMessage是對通知區表徵圖進行操作的訊息,主要有三中,如下表所示。
Shell_NotifyIcon使用的訊息
訊息說明
NIM_ADD
在任務條通知區插入一個表徵圖
NIM_ DELETE
在任務條通知區刪除一個表徵圖
NIM_ MODIFY
對任務條通知區的表徵圖進行修改
pnid傳入一個NOTIFYICONDATA結構的指標。NOTIFYICONDATA結構聲明及各域的意義表示如下:
typedef struct _NOTIFYICONDATA
{
// nid
DWORD cbSize; // NOTIFYICONDATA結構的位元組數
HWND hWnd; // 處理通知區表徵圖訊息的視窗控制代碼
UINT uID; // 通知區表徵圖的ID
UINT uFlags; // 表示下述三項是否有意義的標誌
UINT uCallbackMessage; // 滑鼠點擊表徵圖所發出訊息的ID
HICON hIcon; // 表徵圖控制代碼
char szTip[64]; // 當滑鼠移到表徵圖上時顯示的提示資訊
} NOTIFYICONDATA, *PNOTIFYICONDATA;
當用Shell_NotifyIcon在任務條通知區中放置一個表徵圖時,同時也定義了一條回調訊息,當使用者用按一下滑鼠或雙擊表徵圖時,NOTIFYICONDATA結構中指定的視窗控制代碼將接受到該訊息。該訊息的lParam參數將說明滑鼠操作的方式。當應用程式退出時,應刪除任務條中的表徵圖。
下面的樣本將說明如何使前述的橢圓視窗程序作為表徵圖顯示在任務條通知區中,當按一下滑鼠表徵圖時,將彈出一個菜單,當雙擊時,橢圓視窗將完整顯示。
1. 用資源編輯器在EllipseWnd項目的IDR_MENU_CONTEXT菜單中增加一個功能表項目“在任務條中插入表徵圖”(ID為IDM_INSERTICON)。
2. 用資源編輯器在EllipseWnd項目中增加一個菜單資源IDR_MENU_ICON ,在其中設定三個功能表項目:
“啟用橢圓視窗”(ID為IDM_ACTIVEWINDOW)
“關於...”(ID為IDM_ABOUTBOX)
“退出 Alt+F4”(ID為IDM_EXIT)
3. 在CEllipseWndDlg.h源檔案中定義一個訊息UM_ICONNOTIFY用以響應表徵圖操作,並在CEllipseWndDlg類定義中增加響應該訊息的處理函數OnIconNotify。用ClassWizard增加響應功能表命令IDM_INSERTICON和IDM_ACTIVEWINDOW的函數定義和模板。CEllipseWndDlg.h中的修改如下:
// 定義響應表徵圖操作的訊息
#define UM_ICONNOTIFY WM_USER+100
class CEllipseWndDlg : public CDialog
{
// Construction
public:
CEllipseWndDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CEllipseWndDlg)
enum { IDD = IDD_ELLIPSEWND_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEllipseWndDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
CRgn m_rgnWnd;
// 處理表徵圖的功能函數說明
BOOL AddIcon();
BOOL DeleteIcon();
// Generated message map functions
//{{AFX_MSG(CEllipseWndDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
afx_msg void OnAboutbox();
afx_msg void OnExit();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnInserticon();
afx_msg void OnActivewindow();
//}}AFX_MSG
// 表徵圖訊息的處理函數說明
afx_msg void OnIconNotify(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
4. 在CEllipseWndDlg.cpp中增加訊息影射條目如下:
BEGIN_MESSAGE_MAP(CEllipseWndDlg, CDialog)
//{{AFX_MSG_MAP(CEllipseWndDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_CONTEXTMENU()
ON_COMMAND(IDM_ABOUTBOX, OnAboutbox)
ON_COMMAND(IDM_EXIT, OnExit)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_COMMAND(IDM_INSERTICON, OnInserticon)
ON_COMMAND(IDM_ACTIVEWINDOW, OnActivewindow)
//}}AFX_MSG_MAP
ON_MESSAGE(UM_ICONNOTIFY, OnIconNotify)
END_MESSAGE_MAP()
5. 在CEllipseWndDlg.cpp中增加如下的函數或代碼:
void CEllipseWndDlg::OnDestroy()
{
CDialog::OnDestroy();
// remove main window tag
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
// 應用程式退出時,刪除任務條中表徵圖
DeleteIcon();
}
BOOL CEllipseWndDlg::AddIcon()
{
// 在任務條中增加表徵圖
NOTIFYICONDATA nid;
nid.cbSize = sizeof(nid);
nid.hWnd = m_hWnd;
nid.uID = IDR_MAINFRAME;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = UM_ICONNOTIFY;
nid.hIcon = m_hIcon;
CString str = "橢圓視窗";
lstrcpyn(nid.szTip, (LPCSTR)str,
sizeof(nid.szTip) / sizeof(nid.szTip[0]));
return Shell_NotifyIcon(NIM_ADD, &nid);
}
BOOL CEllipseWndDlg::DeleteIcon()
{
// 刪除任務條中的表徵圖
NOTIFYICONDATA nid;
nid.cbSize = sizeof(nid);
nid.hWnd = m_hWnd;
nid.uID = IDR_MAINFRAME;
return Shell_NotifyIcon(NIM_DELETE, &nid);
}
// 響應表徵圖訊息處理函數
void CEllipseWndDlg::OnIconNotify(WPARAM wParam, LPARAM lParam)
{
switch ((UINT)lParam)
{
// 按一下滑鼠操作
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
{
// 裝入表徵圖操作菜單
CMenu menu;
menu.LoadMenu(IDR_MENU_ICON);
// 按一下滑鼠位置
CPoint point;
GetCursorPos(&point);
// 將背景視窗啟用
SetForegroundWindow();
// 顯示表徵圖菜單
menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
point.x, point.y, this, NULL);
// 增加一個額外訊息,使菜單操作正確
PostMessage(WM_USER, 0, 0);
break;
}
// 滑鼠雙擊操作
case WM_LBUTTONDBLCLK:
// 啟用應用程式
OnActivewindow();
break;
}
}
// 插入表徵圖到任務條通知區
void CEllipseWndDlg::OnInserticon()
{
// 先隱藏主窗
ShowWindow(SW_HIDE);
// 插入表徵圖
AddIcon();
}
// 啟用主窗
void CEllipseWndDlg::OnActivewindow()
{
// 先刪除表徵圖
DeleteIcon();
// 顯示主窗
ShowWindow(SW_SHOW);
UpdateWindow();
}