トレイプログラムのデモ-目覚まし時計Alert


From: http://www.vckbase.com/document/viewdoc/?id=996
ソースコードのダウンロード
キーワード:トレイTrayはシステムトレイ(Tray)のプログラムを見たことがあると思いますが、このようなトレイプログラムAlertを作成する方法について説明します.Alertはシステムトレイで動作する小さな目覚まし時計で、設定された時間後にトリガーされ、スクリーンセーバーを実行し、曲を再生します.このプログラムはずっと前に书いたので、私は今VC++をインストールしていません.だから、本文のスクリーンショットは友达のLeoyinが作ってくれて、私に伝えてくれました.ここでも彼に感谢します.トレイプログラムを作成する鍵は、Windows API-Shell_にあります.NotifyIcon()の使用.このAPIの宣言はShellAPI.Hファイルに含まれている.StdAfx.hで「#include」を使用してプロジェクトに導入してください.私のように馬鹿ではありません.エンジニアリングマネージャにこのファイルを導入したので、クラスビューで見たくないものがたくさん見られました.私は今でもVC++IDEで修正していません.そうしましょう.まず、関連する関数と構造をご紹介します:Shell_NotifyIcon()のプロトタイプと説明(最新版)は以下の通りです.
BOOL Shell_NotifyIcon(
	DWORD dwMessage,
	PNOTIFYICONDATA lpdata
	);

パラメータおよび戻り値の説明:
dwMessage
:[パラメータを入力]実行するアクションを説明します.アクションのオプション値は次のとおりです.
  • NIM_ADDは、トレイ領域
  • にアイコンを追加する.
  • NIM_DELETEトレイ領域からアイコン
  • を削除
  • NIM_MODIFY修正アイコン
  • NIM_SETFOCUSはフォーカス(Focus)をトレイ領域に戻します.このメッセージは、通常、トレイ領域アイコンがユーザインタフェースの操作を完了した後に発行されます.たとえば、トレイアイコンにショートカットメニューが表示され、ユーザーがESCキーを押して操作すると、NIM_が使用されます.SETFOCUSは、トレイ領域にフォーカスを保持し続けます.このアイテムは、システムハウジングと共通制御DLL(Shlwapi.dllとCoctl 32.dll)5.0以上のバージョンでのみ使用できます.
  • NIM_SETVERSIONは、特定のバージョンのシステムハウジングと共通制御DLLを使用することを指定します.デフォルト値は0で、Win 95方式が使用されていることを示します.このアイテムは、システムハウジングと共通制御DLL 5.0以上のバージョンでのみ使用できます.

  • lpdata:
    [入力パラメータ]NOTIFYICONDATA構造へのポインタ.
    戻り値:
    成功した場合、関数はTRUEを返します.そうでなければFALSEです.
    NOTIFYICONDATA
     構造の説明(最新版)は次のとおりです.
    typedef struct _NOTIFYICONDATA {
        DWORD cbSize;
        HWND hWnd;
        UINT uID;
        UINT uFlags;
        UINT uCallbackMessage;
        HICON hIcon;
        TCHAR szTip[64];
        DWORD dwState;
        DWORD dwStateMask;
        TCHAR szInfo[256];
        union {
            UINT uTimeout;
            UINT uVersion;
        };
        TCHAR szInfoTitle[64];
        DWORD dwInfoFlags;
        GUID guidItem;
    } NOTIFYICONDATA, *PNOTIFYICONDATA;

    cbSize
    異なるバージョンに適応するために、バイト単位の構造サイズ.
    hWnd
    Windowsメッセージを受信するウィンドウハンドル.
    uID
    トレイアイコンのID.
    uFlags
    構造内の有効なデータを含むメンバーを示します.オプション:NIF_ICON, NIF_MESSAGE,NIF_TIP,NIF_STATE,NIF_INFO,NIF_GUID.
    uCallbackMessage
    コールバックメッセージIDは、ユーザーによってカスタマイズされます.カスタムメッセージ処理関数に関連付けられます.
    hIcon
    トレイアイコンのハンドル.
    szTip
    トレイアイコンのプロンプト文字列.
    注:次のデータ・メンバーは
    システムハウジングと共通制御DLL 5.0以上のバージョンが有効です.
    dwState
    アイコンの状態:NIS_HIDDEN-非表示、またはNIS_SHAREDICON-ビジュアル.
    dwStateMask
    アイコンステータスマスク、dwStateの設定
    szInfo
    バルーン型ヒント(Balloon Tooltip)の文字列.
    uTimeout
    ミリ秒単位のプロンプト表示時間
    uVersion
    依存するバージョンを特定します.0-Win95,NOTIFYICON_VERSION-Win2000
    szInfoTitle
    バルーンヒントのタイトル
    dwInfoFlags
    バルーンプロンプトで使用するアイコンを設定します(MessageBoxで使用されているアイコンのように):
  • NIIF_ERRORエラー
  • NIIF_INFO情報
  • NIIF_NONEにはアイコンがない
  • NIIF_WARNING警告
  • NIIF_ICON_MASK 6.0バージョン保留
  • NIIF_NOSOUNDは6.0バージョン限定で、対応するサウンド
  • は再生されません
    guidItem
    バージョン6.0保存
    次に、このAlertを実現しましょう.AlertはダイアログベースのWin 32アプリケーションで、AppWizardで作成しましょう.次に、このダイアログボックスを図のように設計します.
     
    AlertDlg.Hに:
    #include < mmsystem.h >          //              ,  
    
    #define WM_NOTIFYICON	WM_USER+5  //      ID
    #define IDI_ICON		0x0005     //  ID
    #define IDT_APPLY		WM_USER+6  //        Timer      ID
    

    次にクラスCAlertDlgにデータメンバーm_を追加するIntervalとカスタムメンバー関数の宣言(どのように追加するかは私が教えなくてもいいでしょう).最後にCAlertDlgクラスを形成する声明(いくつかの注釈が削除されました)は以下の通りです.
    class CAlertDlg : public CDialog
    {
    public:
    	~CAlertDlg();
    	CAlertDlg(CWnd* pParent = NULL);
    
    
    	enum { IDD = IDD_ALERT_DIALOG };
    	int	m_Interval;		//    ,      
    
    
    protected:
    	virtual void DoDataExchange(CDataExchange* pDX);
    
    
    protected:
    	void ShowMessage(void);  //              
    	HICON m_hIcon;  //    
    
    
    	virtual BOOL OnInitDialog();
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    
    
    	afx_msg void OnClickApply();  //"  "           
    	virtual void OnCancel();  //"  "           
    	afx_msg void OnTimer(UINT nIDEvent);  //         
    	afx_msg void OnClickHide();  //"  "           
    
    	//   WM_NOTIFYICON       
    	afx_msg void OnNotifyIcon(WPARAM wParam, LPARAM lParam);  
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  //        
    	afx_msg BOOL OnQueryEndSession();  //Windows        
    
    
    	DECLARE_MESSAGE_MAP()
    };
    

    以下はAlertDlg.CPPにおける対応する関数の実装(ポイントアンカーを設定するか):
    BOOL CAlertDlg::OnInitDialog()
    {
    	SetIcon(m_hIcon, TRUE);
    	SetIcon(m_hIcon, FALSE);
    	
    	//        
    	CSpinButtonCtrl * pSpin;
    	pSpin = (CSpinButtonCtrl *) GetDlgItem(IDC_SPIN);
    	pSpin->SetRange(5,150);
    	m_Interval = 30;
    	CDialog::OnInitDialog();
    	
    	//      ,      
    	SetTimer(1, 1000, NULL);
    
    	//          
    	NOTIFYICONDATA nd;
    	nd.cbSize	= sizeof (NOTIFYICONDATA);
    	nd.hWnd	= m_hWnd;
    	nd.uID	= IDI_ICON;
    	nd.uFlags	= NIF_ICON|NIF_MESSAGE|NIF_TIP;
    	nd.uCallbackMessage= WM_NOTIFYICON;
    	nd.hIcon	= m_hIcon;
    
    	strcpy(nd.szTip, "    ");
    	
    	Shell_NotifyIcon(NIM_ADD, &nd);
    	
    	return TRUE;
    }
    
    void CAlertDlg::OnClickApply() 
    {
    	//       
    	UpdateData();
    	OnTimer(IDT_APPLY);
    }
    
    void CAlertDlg::OnCancel() 
    {
    	//      
    	KillTimer(1);
    
    	//            
    	NOTIFYICONDATA nd;
    	nd.cbSize	= sizeof (NOTIFYICONDATA);
    	nd.hWnd	= m_hWnd;
    	Shell_NotifyIcon(NIM_DELETE, &nd);
    	
    	CDialog::OnCancel();
    }
    
    void CAlertDlg::OnTimer(UINT nIDEvent) 
    {
    	static CString	strTemp;
    	static int		Count = 0;
    	COleDateTime	dtTime;
    
    	//        
    	//                 ,      ?
    	dtTime = COleDateTime::GetCurrentTime();  
    	strTemp.Format("     %02i:%02i:%02i ",
    			dtTime.GetHour(),
    			dtTime.GetMinute(),
    			dtTime.GetSecond());
    	GetDlgItem(IDC_CURTIME)->SetWindowText(strTemp);
    
    	//        
    	if (nIDEvent == IDT_APPLY) Count = 0;  //            ,       
    	Count++;
    	int RestTime;
    	RestTime = m_Interval - Count/60;
    	if (RestTime <= 0) 
    	{
    		Count = 0;
    		ShowMessage();
    	}
    	
    	strTemp.Format("        %i   ", RestTime);
    	GetDlgItem(IDC_RESTTIME)->SetWindowText(strTemp);	
    	CDialog::OnTimer(nIDEvent);
    }
    
    //  ShowMessasge()  ,          ,        
    void CAlertDlg::ShowMessage()
    {
    	//  C:\InfoCD\WinaMP\  WinaMP3  Music.m3u  
    	::WinExec("C:\\INFOCD\\WINAMP\\WINAMP.EXE music.m3u",SW_HIDE);
    	
    	MessageBox("        ......", 
    			"  ", 
    			MB_SYSTEMMODAL|MB_OK|MB_ICONEXCLAMATION|MB_ICONWARNING);
    
    	//  C:\Windows\System      
    	ShellExecute(m_hWnd,"open","C:\\WINDOWS\\SYSTEM\\  .scr", NULL,NULL,SW_SHOWNORMAL);
    }
    
    afx_msg void CAlertDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
    {
    	//            
    	//wParam         ID,lParam   Windows   
    	if ((wParam == IDI_ICON)&&(lParam == WM_LBUTTONDOWN))
    		ShowWindow(SW_SHOWNORMAL);
    }
    
    void CAlertDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	//      (MFC Bug?),            
    	if (nID == SC_MAXIMIZE)
    		return;
    	if (nID == SC_MINIMIZE)
    		ShowWindow(SW_HIDE);
    	else
    		CWnd::OnSysCommand(nID, lParam);
    }
    
    BOOL CAlertDlg::OnQueryEndSession()
    {
    	//      Windows         
    	CAlertDlg::OnCancel();
    	return TRUE;
    }
    
    void CAlertDlg::OnClickHide() 
    {
    	OnSysCommand(SC_MINIMIZE, 0x0000);
    	return;
    }

    では、上記のソースコードを読むことで、トレイプログラムの作成について認識していると思います.これも本稿の根本的な目的です.ただ、このプログラムにはBugがあります.プログラムが終了した後もアイコンがトレイに表示され、マウスをアイコンの上に通すと消えます.このバグは誰かが解決策を提案したのを覚えています.アイコンのハンドルを解放しようとしているようです.残念ながら覚えていません.このプログラムも修正されていません. 
    皆さんのご返事を心よりお待ちしております.ありがとうございます.
    参考記事:
    1、MSDNの関連リンク:The Taskbar
    , TrayNot Sample
    ,
    2、VCKBaseにも多くの優秀な文章(例えばNorthTibetがコンパイルした「システムトレイプログラミング完全ガイド」
    ”).
    ハードディスク(HDD)版のMSDNでは、対応する特集記事があるので、自分で探してみましょう.