画面右下のタスクトレイ(通知領域)にアイコンを登録するアプリケーションは多い。ここでは簡単にアイコンを登録するためのクラスとその使用例を作成した。
ここでは簡単にするためにInternet Explorerのバージョン判断処理やアイコンのID設定処理は省いた。またタスクトレイのアイコンを管理するクラス「CDnpTaskTrayIcon」内には右クリックメッセージ表示用やバルーンメッセージ表示用の処理も備えているが、ここで示した使用例では利用していない。
ダウンロードできるプロジェクトをビルド、実行すると初期状態でタスクトレイにアイコンが表示される。そのアイコンをダブルクリックを繰り返すとダイアログが表示したり消えたりする。
ATL/WTLアプリケーションウイザードでダイアログベースのプロジェクトを作成し、自動生成されたソースコードを編集する。
#pragma once
//#include "dinoputy.h"
//#include "dinoputy.cpp"
//
// タスクトレイアイコン管理クラス
//
// uIDはゼロ固定のため、複数のアイコン登録は未対応
//
//
//■使用例
//
////stdafx.hでIEバージョン値を次のように定義すること
////#define _WIN32_IE 0x0501
//
//#include "DnpTaskTrayIcon.h"
//
//#define WM_TRAY_NOTIFY_ICON WM_APP + 10
//
//class CMainFrame : public CFrameWindowImpl<CMainFr(....省略....)
//{
//protected:
// //メンバ変数として1行追加
// CDnpTaskTrayIcon _cTrayIcon;
//public:
//
// (....省略....)
//
// //メッセージマップに2行追加\
// BEGIN_MSG_MAP(CMainFrame)
// (....省略....)
// MESSAGE_HANDLER(WM_TRAY_NOTIFY_ICON, OnTrayNotify)
// CHAIN_MSG_MAP_MEMBER(_cTrayIcon) //タスクトレイにメッセージを回す
// END_MSG_MAP()
//
// //トレイの登録とバルーンメッセージの表示
// //OnCreateに限らず好きな位置に行を追加
// LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// {
// (....省略....)
//
// //トレイアイコンの登録
// _cTrayIcon.CreateTrayIcon(_T("テスト"),IDR_MAINFRAME,m_hWnd,WM_TRAY_NOTIFY_ICON);
//
// //バルーンメッセージの表示
// _cTrayIcon.ShowBaloonHelp(_T("バルーン"),_T("メッセージです"),15000);
//
// (....省略....)
// }
//
//
// (....省略....)
//
//
// //アイコンのクリック処理用関数を追加
// LRESULT OnTrayNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
// {
// switch(lParam)
// {
// case WM_LBUTTONDBLCLK: //ダブルクリック処理
// break;
//
// case WM_RBUTTONDOWN: //右クリック処理
// break;
//
// case NIN_BALLOONSHOW: //バルーンが表示されたとき
// break;
//
// case NIN_BALLOONTIMEOUT: //バルーンがタイムアウトで消えたとき
// break;
//
// case NIN_BALLOONHIDE: //バルーンが×ボタンのクリックにより消えたとき
// break;
//
// case NIN_BALLOONUSERCLICK: //バルーンが通知領域のクリックで消えたとき
// break;
// }
//
// return 0;
// }
//};
//
class CDnpTaskTrayIcon
{
protected:
bool _bCreateIcon; //アイコンが登録されているかどうか
HWND _hWnd; //通知先HWND
bool _bIsIE5orLater; //IEが5.0以上かどうか
UINT _nWmTaskbarCreated; //タスクバー再描画を知らせる登録メッセージのID
NOTIFYICONDATA _sData; //アイコン登録時情報
public:
BEGIN_MSG_MAP(CDnpTaskTrayIcon)
MESSAGE_HANDLER(_nWmTaskbarCreated, OnTaskbarCreated)
MESSAGE_HANDLER(WM_DESTROY,OnClose)
MESSAGE_HANDLER(WM_CLOSE,OnClose)
END_MSG_MAP()
//
// コンストラクタ
//
CDnpTaskTrayIcon()
{
_hWnd = NULL;
_bIsIE5orLater = true;//IsIEVerion5orLater();
_nWmTaskbarCreated = ::RegisterWindowMessage(_T("TaskbarCreated"));
_bCreateIcon = false;
ZeroMemory(&_sData,sizeof(NOTIFYICONDATA));
}
//
// アイコンの登録
//
bool CreateTrayIcon(LPCTSTR pszTitle,UINT nIconResource,HWND hWnd,UINT nNotifyMessage)
{
BOOL ret;
_hWnd = hWnd;
ATLASSERT(_bCreateIcon == false); //既にアイコンが登録されている
ZeroMemory(&_sData,sizeof(NOTIFYICONDATA));
_sData.cbSize = sizeof(NOTIFYICONDATA);
_sData.hWnd = hWnd;
_sData.uID = 0; //IDはゼロで固定している!
_sData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
_sData.hIcon = ::LoadIcon(_Module.m_hInst,MAKEINTRESOURCE(IDR_MAINFRAME));
_sData.uCallbackMessage = nNotifyMessage;
//IEのバージョンによって最大TIPS長が異なる!
if(pszTitle)
{
if(_bIsIE5orLater)
_tcsncpy_s(_sData.szTip,128,pszTitle,64);
else
_tcsncpy_s(_sData.szTip,128,pszTitle,128);
}
ret = Shell_NotifyIcon(NIM_ADD,&_sData);
_bCreateIcon = (ret) ? true : false;
return (ret) ? true : false;
}
//
// アイコンの変更
//
bool ChangeTrayIcon(UINT nIconResource)
{
BOOL ret;
ATLASSERT(_bCreateIcon); //アイコンが登録されていない
if(_bCreateIcon == false)
return false;
ZeroMemory(&_sData,sizeof(NOTIFYICONDATA));
_sData.cbSize = sizeof(NOTIFYICONDATA);
_sData.hWnd = _hWnd;
_sData.uID = 0; //IDはゼロで固定している!
_sData.uFlags = NIF_ICON;
_sData.hIcon = ::LoadIcon(_Module.m_hInst,MAKEINTRESOURCE(nIconResource));
ret = Shell_NotifyIcon(NIM_MODIFY,&_sData);
return (ret) ? true : false;
}
//
// バルーンヘルプの表示
//
bool ShowBaloonHelp(LPCTSTR pszTitle,LPCTSTR pszMessage,UINT nTimeOut)
{
BOOL ret;
NOTIFYICONDATA sData;
//■■OSのバージョンチェックもするべき
// ATLASSERT(_bCreateIcon); //アイコンが登録されていない
// ATLASSERT(_bIsIE5orLater); //IE5以上ではない!
if(_bCreateIcon == false)
return false;
ZeroMemory(&sData, sizeof(NOTIFYICONDATA));
sData.cbSize = sizeof(NOTIFYICONDATA);
sData.uFlags = NIF_INFO;
sData.hWnd = _hWnd;
sData.dwInfoFlags = NIIF_INFO;
sData.uTimeout = nTimeOut;
if(_bIsIE5orLater)
{
_tcsncpy_s(sData.szInfoTitle,64,pszTitle,64);
_tcsncpy_s(sData.szInfo,256,pszMessage,256);
}
ret = Shell_NotifyIcon(NIM_MODIFY,&sData);
return (ret) ? true : false;
}
//
// トレイアイコンの削除
//
bool RemoveTrayIcon(void)
{
BOOL ret;
NOTIFYICONDATA sData;
ATLASSERT(_bCreateIcon); //アイコンが登録されていない
ZeroMemory(&sData,sizeof(NOTIFYICONDATA));
sData.cbSize = sizeof(NOTIFYICONDATA);
sData.hWnd = _hWnd;
sData.uID = 0;
ret = Shell_NotifyIcon(NIM_DELETE,&sData);
_bCreateIcon = false;
return (ret) ? true : false;
}
//
// ポップアップメニューの表示
//
BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags=TPM_LEFTALIGN | TPM_RIGHTBUTTON)
{
BOOL ret;
POINT pt;
if(hMenu == NULL)
{
ATLASSERT(0);
return FALSE;
}
//カーソル位置の取得
::GetCursorPos(&pt);
::SetForegroundWindow(_hWnd); //これがないとメニューが消えない
//メニューの表示
ret = ::TrackPopupMenu(hMenu,uFlags,pt.x,pt.y,0,_hWnd,NULL);
::PostMessage(_hWnd,WM_NULL,NULL,NULL); //これがないとメニューが消えない可能性がある
return ret;
}
//
// ポップアップメニューの表示
//
bool TrackPopupMenu(UINT nMenuResource,int nSubMenu)
{
bool ret;
HMENU hMenu;
HMENU hPopMenu;
hMenu = ::LoadMenu(_Module.m_hInst,MAKEINTRESOURCE(nMenuResource));
ATLASSERT(hMenu);
if(hMenu == NULL)
return false;
hPopMenu = ::GetSubMenu(hMenu,nSubMenu);
ret = TrackPopupMenu(hPopMenu) ? true : false;
::DestroyMenu(hMenu);
return ret;
}
protected:
//
// アプリケーション終了時処理
//
LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
if(_bCreateIcon)
RemoveTrayIcon(); //アイコンを削除する
return 0;
}
//
// アイコン再描画処理
//
//タスクマネージャでexplorer.exeを強制終了させた場合などに消えたアイコンを再描画する
//
LRESULT OnTaskbarCreated(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
if(_bCreateIcon)
Shell_NotifyIcon(NIM_ADD,&_sData); //前回の情報を用いてアイコンを登録
return 0;
}
};
■MainDlg.h内に定義を追加
#include "DnpTaskTrayIcon.h" #define WM_TRAY_NOTIFY_ICON WM_APP + 10■MainDlg.hのCMainDlgにメンバー変数を追加
CDnpTaskTrayIcon _cTrayIcon;■MainDlg.hのCMainDlgにメッセージマップを追加
BEGIN_MSG_MAP(CMainDlg) (。。。省略。。。) MESSAGE_HANDLER(WM_TRAY_NOTIFY_ICON, OnTrayNotify) CHAIN_MSG_MAP_MEMBER(_cTrayIcon) //タスクトレイにメッセージを回す END_MSG_MAP()■MainDlg.hのOnInitDialogでアイコン登録処理を追加
//トレイアイコンの登録
_cTrayIcon.CreateTrayIcon(_T("テスト"),IDR_MAINFRAME,m_hWnd,WM_TRAY_NOTIFY_ICON);
■MainDlg.hのCMainDlgにメンバー関数を追加
//アイコンのクリック処理用関数を追加
LRESULT OnTrayNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
switch(lParam)
{
case WM_LBUTTONDBLCLK: //ダブルクリック処理
if(IsWindowVisible())
ShowWindow(SW_HIDE);
else
ShowWindow(SW_SHOWDEFAULT);
break;
case WM_RBUTTONDOWN: //右クリック処理
break;
case NIN_BALLOONSHOW: //バルーンが表示されたとき
break;
case NIN_BALLOONTIMEOUT: //バルーンがタイムアウトで消えたとき
break;
case NIN_BALLOONHIDE: //バルーンが×ボタンのクリックにより消えたとき
break;
case NIN_BALLOONUSERCLICK: //バルーンが通知領域のクリックで消えたとき
break;
}
return 0;
}
