システムトレイアイコンの実装

8644 ワード

http://www.vckbase.com/document/viewdoc/?id=492
転載の効果はよくなくて、写真はすべてハを表示しないで、上の接続をつけましょう.
システムトレイプログラミング完全ガイド(一)コンパイル/northttibet
ここの例のソースコードをダウンロードします.    Windows 95の発売以来、システムトレイアプリケーションは魅力的なUIとして多くのユーザーに愛されています.システムトレイUIを使うWindowsアプリケーションは数え切れないほど多く、例えば「金山詞覇」「Winamp」「RealPlayer」などです.では、自分のトレーの使い方はどう書きますか?本論文は一連の文章の中の第一編であり、これらの文章はトレイアプリケーションのプログラミングを比較的体系的に記述する.自分のC++クラスを作成してシステムトレイの応用特性を向上させます.これらの文章を読んで、例を参照してください.読者は自分のプログラムにシステムトレイを自由に使えます.    MFCフレームワークは、システムトレイUIに既成のクラスが提供されていないことをご存知でしょうか?アプリケーションを表すアイコンをどのようにタスクバーに追加しますか?方法は簡単で、一つのAPI関数しか使えません.それはShell_です.NotifyIconこの関数自体もかなり分かりやすく使われています.その原型を見れば分かります.
BOOL Shell_NotifyIcon(
    DWORD dwMessage, 
    PNOTIFYICONDATA pnid
);      
最初のパラメータdwMessageタイプはDWORDであり、実行する動作を表しています.
      NIM_ADD:                 。
      NIM_MODIFY:              。
      NIM_DELETE:              。
      NIM_SETFOCUS:               。          ,           。  ,             
                             ,     "ESCAPE"     ,                      。 
      NIM_SETVERSION:                 。      
第二のパラメータpnidは、NOTIFYICONDA構造のアドレスであり、その内容はdwMessageの値によって決まる.この構造はSHELLLAPI.Hファイルで以下のように定義されています.
typedef struct _NOTIFYICONDATA {
  DWORD cbSize;           //     (sizeof struct),    
  HWND hWnd;             //            
  UINT uID;                //    ID (       WPARAM   )
  UINT uFlags;            
  UINT uCallbackMessage;    //            
  HICON hIcon;             //     
  CHAR szTip[64];          //     
} NOTIFYICONDATA;
uFlags  :
#define NIF_MESSAGE 0x1   //   uCallbackMessage   
#define NIF_ICON    0x2   //   hIcon   
#define NIF_TIP     0x4   //   szTip         
Shell_についてNotifyIcon関数の詳細な使用はMSDNを参照してください.    NOTIFYICONSDATA構造のhWndは「持つ」アイコンのウィンドウハンドルです.uIDは、任意の表示トレイアイコンのIDであってもよい(複数のアイコンがあれば)、一般的にリソースIDが使用される.HIconは、IDI_などの事前定義されたシステムアイコンを含む任意のアイコンのハンドルとすることができる.HAND、IDI_QUSTION、IDI_EXCLAMATION、またはWindowsのロゴIDI_WINLOGO.    アイコンの表示は難しくないです.鍵はイベントの処理です.ユーザーがマウスをアイコン上に移動したり、アイコン上でマウスをクリックしたりすると、通知メッセージを得るために、自分のメッセージIDをuCallbackMessageに割り当て、NIF_を設定することができます.MESSAGEマーク.ユーザーがアイコン上でマウスを移動したりクリックしたりすると、WindowsはhWndで指定されたウィンドウハンドルで設定したウィンドウプロセスを呼び出します.メッセージIDはucallbackMessageで指定されています.uIDの値はwParamで、lParamはマウスイベントです.例えばWM_LBTTODOWNなど.    Shell_にもかかわらずNotifyIcon関数は簡単で実用的です.しかし、Win 32 APIです.このためにC++クラスにカプセル化しました.このクラスはCTrayIconといいます.これによって、パレットプログラミングはもっと自由自在になります.NOTIFYICONSDATA、メッセージコード、マーク、およびMSDNを見なければならないので、細かい点を把握することができません.CTrayIconの定義と実装の詳細はソースコードの参照をダウンロードしてください.CTrayIconはプログラマーにより友好的なパレットプログラミングインターフェースを提供しています.NotifyIcon関数でパッケージ化されているほか、ミニフレームです.なぜかというと、Windowsシステムのアプリケーション・ソフトウェア・インターフェース・ガイドによって提唱された原則(このガイドはMSDNで見つけられます)に従って、このようなパレット・アイコンのユーザーインターフェースの挙動が強化されているからです.以下はCTrayIconの最終的なUI特性である.1、パレットのアイコンは情報提示があるべきで、つまりToolTipsである.2、右クリックはコンテキストメニューをポップアップするべきで、このメニューには属性ページを開くコマンドやアイコンに関する他のウィンドウを開くコマンドが含まれています.3、左クリックでさらに情報を表示したり、アイコンに代表されるオブジェクトを制御したり、例えば左クリックで音声アイコンをクリックしたときに音量制御を行います.これ以上の情報や制御がない場合は、何のアクションも行わないでください.    CTrayIconは上の特性を全面的にパッケージ化した.CTrayIconの動作原理を示すために、本明細書では例示的なプログラムTrayTest 1を提供します.図1は実行プログラムの後に表示されるダイアログです.図1はTrayTest 1が実行した後に表示されるダイアログです.アイコンをシステムトレイにインストールした後、トレイアイコンをダブルクリックすると、メッセージリストウィンドウが弾きます.マウスがパレットアイコン上で移動またはクリックしてください.(左右のキーのクリックまたはダブルクリック)発生したメッセージはいずれもこのウィンドウに表示されます.図2のように、図2のメッセージ表示ウィンドウがマウスカーソルをパレットアイコンに移動すると、アイコンの近くにヒント情報が表示されます.図3のように、TooltipはCTrayIconを正しく使うために、まずプログラムのどこかでCTrayIconを実装しなければなりません.例プログラムはメインフレームにCTrayIconを作成する例です.はい、そうです
Class MainFrame  public CFrameWnd {protected:  CTrayIcon m_trayIcon;                    // my tray icon
…….
};      
    次に、IDを提供しなければなりません.これはアイコンライフ期間内の唯一の表示です.今後表示するアイコンを変更しても、このIDはマウスイベントが発生した時に獲得するIDです.アイコンのリソースIDである必要はありません.例としてはこのIDはIDRuTRAYUICONです.フレームのコンストラクションCMainFrameはメンバー初期化リストを通じてmutrayconを初期化します.化:
CMainFrame::CMainFrame() : m_trayIcon(IDR_TRAYICON){
……
}      
アイコンを追加するためには、以下のSetIcon関数の一つを具体的な状況に応じて呼び出す必要があります.
      m_trayIcon.SetIcon(IDI_MYICON);         //   ID
      m_trayIcon.SetIcon("myicon");           //   
      m_trayIcon.SetIcon(hicon);              //HICON
      m_trayIcon.SetStandardIcon(IDI_WINLOGO);//          
    SetIcon(UNT uID)以外にも、これらの関数は、提示テキストを指定するためのLPCSTRタイプのオプションパラメータを有する.SetIcon(UICNT uID)は、IDとuIDの同じシリアルリソースを使用して、提示テキストとして使用する.例えば、TrayTest 1の行のコードは、このようなものである.
// ( mainframe.cpp   )
m_trayIcon.SetIcon(IDI_MYICON);      
この行のコードはまた、TrayTest 1がシリアルリソースを持っているので、IDもIDIuMYICONです.これはTRATEST.RCファイルで見られます.
STRINGTABLE PRELOAD DISCARDABLE 
BEGIN 
     IDI_MYICON "       TRAYTEST." 
END      
    アイコンを変更したいなら、別のIDやHICONでSetIcon関数の一つを呼び出してもいいです.CTrayTestはNIMuMODIFYではなく、NIMuADDでアイコンを変えます.同じ関数はアイコンを削除するためにも使えます.
m_trayIcon.SetIcon(0); //          
    CTrayIconはこのコードをNIMuDELETEと解釈しています.これらの表現行動の符号化は、すべて便利な関数によって代替されていることが分かりました.これはC++のおかげです.ここでは、通知メッセージと前述のUI特性をどのように処理するかを見てみます.通知メッセージの処理はアイコンを設定する前にしなければなりませんが、作成ウィンドウの後にCTrayIcを呼び出す必要があります.on:Set NotificationWnd、この仕事をする一番いい場所はOnCreate処理ルーチンにあります.TrayTestはここで処理します.
//             
#define WM_MY_TRAY_NOTIFICATION WM_USER+0
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
……
  //     
  m_trayIcon.SetNotificationWnd(this,
                        WM_MY_TRAY_NOTIFICATION);
                           m_trayIcon.SetIcon(IDI_MYICON);
  return 0;
}
メッセージが登録されると、次に通常のメッセージング方式でトレイ通知メッセージを処理することができる.
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,
             OnTrayNotification)
             // (or ON_REGISTERED_MESSAGE)
END_MESSAGE_MAP()

LRESULT 
CMainFrame::OnTrayNotification(WPARAM wp, LPARAM lp)
{                    
……
       //     
……
return m_trayIcon.OnTrayNotification(wp, lp);
}      
    メッセージプロセッサが制御されると、WPARAMの値はCTrayIconを構成する際に指定されたIDであり、LPARAMはマウスイベント(WMULBUTONDOWNなど)である.を選択します.通知メッセージが得られたら、何でもしたいことができます.例のプログラムTrayTestは通知情報を表示します.詳細はソースコードを参照してください.メッセージの処理が完了したら、CTrayIconを呼び出してください.OTrayNotificationはデフォルト処理を行います.この仮想関数は(書き換え可能です.)前述したデフォルトのUIを実現します.特にWMULBUTOnDBLCLKとWMURBUTTONUPを処理します.CTrayIconはアイコンIDと同じメニューを探しています.見つかったら、ユーザーがアイコンを右クリックすると、CTrayIconはこのメニューを表示し、ユーザー数がアイコンをダブルクリックすると、CTrayIconは最初のメニューコマンドを実行します.    一つ目のことは、メニューを表示する前に、CTrayIconは最初のメニュー項目をデフォルトとしてブラックで表示します.しかし、どのように黒体でメニュー項目を表示しますか?MSDEV/INCLUDE/*.Hで検索したら、Get/SetMenuDefaultItemを発見しました.この関数には関連するCMenuパッケージがありませんので、直接呼び出します.
//           (  ):
::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);       
    ここ0は最初のメニュー項目を表しています.TRUEはメニュー項目のIDを位置で表しています.なぜMFCはGet/SetMenuDefaultItem関数を包装していませんか?マイクロソフトのやつらはこれらの関数のためだと説明しています.最新のWindows版ではまだ実現されていません.最新のWindows版で実現すると、すぐにMFCに追加されます.    二つ目のイベントはコンテキストメニューの表示です.
      ::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu, ...);      
    TrackPoppMenuをパレットのコンテキストで正しく動作させるためには、まずSetForeground Windowを呼び出す必要があります.そうしないと、ESCAPEキーを押したり、メニューの外でマウスをクリックしたりすると、メニューが消えません.この問題を解決するために数時間を費やしました.最後にMSDNで解決方法を見つけました.詳細を知るために、MSDNのQ 35788を参照してください.泣いたり笑ったりするのは時間をかけてこの問題に関心を持っています.最後にマイクロソフトのやつらがMSDNであなたに問題の結論を出しました.「This behavior is by design...」本当に気が短い人です.    あなたが見ているように、CTrayIconはトレーアプリケーションのプログラミングを逆の手のように容易にします.TrayTest 1のやるべきことはCTrayIconを起動するだけです.:OTrayNotificationは、アイコンIDと同じメニューを提供する通知メッセージプロセッサを実現します.このように簡単です.
// (TRAYTEST.RC  )
IDR_TRAYICON MENU DISCARDABLE 
BEGIN
    POPUP "  (&T)"
    BEGIN
        MENUITEM "  (&O)",                    ID_APP_OPEN
        MENUITEM "   TrayTest(&A)...",        ID_APP_ABOUT
        MENUITEM SEPARATOR
        MENUITEM "  TrayTest   (&S)",       ID_APP_SUSPEND
    END
END      
    図4に示すように、ユーザがトレイアイコン上で右クリックすると、CTrayIconはこのメニューを表示します.アイコンをダブルクリックすると、CTrayIconは最初のメニューコマンドを実行します.「開く」すると、TrayTestがアクティブになります.TrayTest 1を終了するためには、「Suspend TRayTEST」メニュー項目を選択しなければなりません.「ファイル|」から退出します.終了またはTrayTest 1メインウィンドウを閉じます.TrayTest 1は本当に閉じられません.自分だけを隠します.この行為はTrayTest 1がCMainframeを書き換えました.OOCloseが実現しました.図4 TRATEST 1トレイアイコンメニューです.    最後に、心配されている問題を説明したいです.この小さいアイコンを見た後、できるだけ早く自分のプログラムにパレットのアイコンを入れたいです.プログラマとしては、これは全く理解できます.自分のプログラムにパレットのアイコンを追加することに成功したら、友達の間で自慢してもいいです.しかし、すべてのアプリケーションではないことを覚えてください.パレットのアイコンを使う必要があります.必要でなければ蛇足を加えないでください.そうでなければ、トレイのアイコンが多すぎると、必ず画面のゴミになります.下の図5を見てください.