タスクトレイにアイコンを登録するには Shell_NotifyIcon() を使用する.
タスクトレイに表示されるアイコンは 16 x 16 の大きさなのであらかじめ作成しておく.
タスクトレイに登録
// メニューハンドラのメッセージとなる
#define MYWM_NOTIFYICON (WM_USER+10)
NOTIFYICONDATA m_tnid;
m_tnid.cbSize = sizeof( NOTIFYICONDATA );
m_tnid.hWnd = m_hWnd;
m_tnid.uID = 1;
m_tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_tnid.uCallbackMessage = MYWM_NOTIFYICON;
m_tnid.hIcon = m_hIcon;
lstrcpy(m_tnid.szTip, "My Application");
Shell_NotifyIcon(NIM_ADD, &m_tnid);
タスクトレイから削除
Shell_NotifyIcon( NIM_DELETE, &m_tnid );
タスクトレイにマウスを持っていかなければアイコンが削除されない(リフレッシュしない)場合,VC++ であれば CMainFrame のデストラクタで削除を行っている可能性が高い.CFrameWnd::OnDestroy() で削除すればタスクトレイはリフレッシュされるはずである.
タスクトレイメニュー作成
メニューリソースに擬似的なメニューを追加する.(新規で追加)
その最初の項目にポップアップメニューとしてサブメニューを追加する.
これがタスクトレイで表示されるメニューとなる.
class CMyDlg :
{
afx_msg LONG On_MYWM_NOTIFYICON(UINT wParam, LONG lParam);
};
BEGIN_MESSAGE_MAP(Cxxxx, Cxxxxxx)
ON_MESSAGE(MYWM_NOTIFYICON, On_MYWM_NOTIFYICON)
END_MESSAGE_MAP()
LONG CMyDlg::On_MYWM_NOTIFYICON(WPARAM wParam, LPARAM lParam)
{
UINT uID = (UINT)wParam;
UINT uMouseMsg = (UINT)lParam;
if(uMouseMsg == WM_LBUTTONDBLCLK) {
// 左ボタンダブルクリックでウィンドウ表示
ShowWindow(SW_SHOW);
SetForegroundWindow();
} else if(uMouseMsg == WM_RBUTTONDOWN) {
// 右ボタンクリックでメニュー表示
CRect rc;
GetDesktopWindow()->GetWindowRect(rc);
SetForegroundWindow();
CMenu menu;
VERIFY(menu.LoadMenu(IDR_MENU1));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, rc.right, rc.bottom, AfxGetMainWnd());
}
return 0;
}
メニューを表示しても,ESC キーで消えなかったり,タスクバーをクリックするとメニューが後ろに隠れたり,メニューを選択しなければ消えない状態になることがある.
これを回避するには以下のように TrackPopupMenu() の後に WM_NULL をポストするようにする.(TrackPopupMenu() の前に SetForegroundWindow() を行っていなければそれも行う)
なぜ回避できるかは不明である.
SetForegroundWindow();
TrackPopupMenu(...);
PostMessage(WM_NULL, 0, 0);
アイコンの変更
// 切り替えるアイコンをリソースからロードしておく
m_hMyIcon1 = (HICON)LoadImage(pApp->m_hInstance, MAKEINTRESOURCE(IDI_MYICON1), IMAGE_ICON, 16, 16, 0);
m_hMyIcon2 = (HICON)LoadImage(pApp->m_hInstance, MAKEINTRESOURCE(IDI_MYICON2), IMAGE_ICON, 16, 16, 0);
void CMyDlg::BlinkIcon()
{
// アイコンを交互に切り替える
if(m_tnid.hIcon == m_hMyIcon1)
m_tnid.hIcon = m_hMyIcon2;
else
m_tnid.hIcon = m_hMyIcon1;
Shell_NotifyIcon(NIM_MODIFY, &m_tnid);
}
参照