MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
MFCの基礎 - 常駐ソフトウェアのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
MFCの基礎 - 常駐ソフトウェア
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == タスクトレイに常駐するソフトウェアを開発する手順を記載する。<br> <br> 常駐ソフトウェアを開発するには、ソフトウェアのメインウィンドウとして登録するウィンドウクラスに、以下の処理を記述する。<br> # タスクバーに非表示のウィンドウを作成する。 # ウィンドウを破棄する時、ウィンドウクラスのオブジェクトが自身のオブジェクトを削除する。 # タスクトレイに対して、アイコン、ツールチップ文字列、コールバックを登録・変更・削除する。 # タスクトレイのアイコンに対するイベントの応答。 # ウィンドウを作成する時、タスクトレイに対してアイコンを登録する処理を呼び出す。 # ウィンドウを破棄する時、タスクトレイに対してアイコンを削除する処理を呼び出す。 <br><br> == 常駐ソフトウェア == ==== タスクバーに非表示のウィンドウを作成する ==== <code>CDialog</code>クラスまたは<code>CWnd</code>クラスを継承したCTrayWndクラスに、ウインドウを作成するメソッドを記述する。<br> <br> タスクバーに非表示のウィンドウを作成するため、Createメソッドを使用して、拡張ウィンドウスタイルとして<code>WS_EX_TOOLWINDOW</code>を指定する。<br> ウィンドウを非表示にするため、ウィンドウの幅・高さを0にする。<br> <syntaxhighlight lang="c++"> BOOL CTrayWnd::Create() { return CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(0), _T("TrayWnd"), WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL); } </syntaxhighlight> <br> CTrayWndクラスに、Createメソッドの宣言を追加する。<br> <syntaxhighlight lang="c++"> #pragma once class CTrayWnd : public CWnd { public: BOOL Create(); DECLARE_DYNAMIC(CTrayWnd) // ...略 } </syntaxhighlight> <br> ==== ウィンドウを破棄する時にウィンドウクラスが自身のオブジェクトを削除する ==== CTrayWndクラスに、PostNcDestroyメソッドを追加して、自身のオブジェクトを削除する処理を記述する。<br> <syntaxhighlight lang="c++"> void CTrayWnd::PostNcDestroy() { // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。 CWnd::PostNcDestroy(); delete this; } </syntaxhighlight> <br> ==== タスクトレイにアイコン・ツールチップ・コールバックを登録・変更・削除する ==== 上記で作成したCTrayWndクラスに、タスクトレイにアイコンを登録・変更・削除するメソッドを記述する。<br> このメソッドは、最終的には、Win32APIの<code>Shell_NotifyIcon</code>関数が行う。<br> <br> <code>Shell_NotifyIcon</code>関数の第1引数で、アイコンの登録・編集・削除を指定する。<br> <code>Shell_NotifyIcon</code>関数の第2引数の<code>NOTIFYICONDATA</code>構造体において、アイコン、ツールチップ文字列、コールバックを指定する。<br> <syntaxhighlight lang="c++"> BOOL CTrayWnd::NotifyIcon( DWORD dwMessage, HICON hIcon, LPCTSTR pszTip /*= NULL*/ ) { ASSERT(NIM_ADD == dwMessage || NIM_DELETE == dwMessage || NIM_MODIFY == dwMessage); NOTIFYICONDATA nid = {0}; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = GetSafeHwnd(); nid.uID = ID_ICON; // アイコンを1つだけサポートする // タスクトレイのアイコンID // 1つのプロセスで複数のアイコンをタスクトレイに表示する場合は、それぞれ異なるIDを指定する // このIDはプロセスごとに独立しているので、他のプロセスが同じIDを指定していたとしても、それらが衝突することはない nid.uCallbackMessage = WM_USER_TRAYNOTIFYICON; nid.uFlags = NIF_MESSAGE; if(NULL != hIcon && m_hIcon_current != hIcon) { // アイコン変更 nid.uFlags |= NIF_ICON; nid.hIcon = hIcon; m_hIcon_current = hIcon; } if(NULL != pszTip) { // ツールチップ表示 nid.uFlags |= NIF_TIP; _tcsncpy_s(nid.szTip, sizeof(nid.szTip), pszTip, _TRUNCATE); } return Shell_NotifyIcon(dwMessage, &nid); } BOOL CTrayWnd::NotifyIcon( DWORD dwMessage, HICON hIcon, UINT nStringResource ) { // 表示メッセージを、ストリングリソースのリソースIDで指定する関数 CString msg = _T(""); VERIFY(msg.LoadString(nStringResource)); return NotifyIcon( dwMessage, hIcon, msg ); } </syntaxhighlight> <br> TrayWnd.cppファイルのヘッダ部に、ID_ICONおよびWM_USER_TRAYNOTIFYICONの定義を記述する。<br> CTrayWndクラスのコンストラクタに、メンバ変数m_hIcon_currentの初期化処理を記述する。<br> <syntaxhighlight lang="c++"> // TrayWnd.cpp #include "stdafx.h" #include "MyApplication.h" #include "TrayWnd.h" #define ID_ICON 100 #define WM_USER_TRAYNOTIFYICON WM_APP + 100 IMPLEMENT_DYNAMIC(CTrayWnd, CWnd) CTrayWnd::CTrayWnd() : m_hIcon_current(NULL) { } // ...略 </syntaxhighlight> <br> TrayWnd.hファイルに、メンバ変数m_hIcon_currentおよびNotifyIconメソッドの宣言を記述する。<br> <syntaxhighlight lang="c++"> #pragma once class CTrayWnd : public CWnd { private: HICON m_hIcon_current; public: BOOL Create(); BOOL NotifyIcon(DWORD dwMessage, HICON hIcon, LPCTSTR pszTip = NULL); BOOL NotifyIcon(DWORD dwMessage, HICON hIcon, UINT nStringResource); DECLARE_DYNAMIC(CTrayWnd) // ...略 } </syntaxhighlight> <br> ==== タスクトレイのアイコンにおけるイベント(常駐ソフトウェアの共通処理) ==== CTrayWndクラスに、タスクトレイのアイコンにおけるイベントの応答処理を記述する。<br> <br> イベントの応答処理は、早く処理を完了させる必要があるため、イベントに応じて、ウィンドウメッセージをポストする。<br> <syntaxhighlight lang="c++"> // TrayWnd.cpp LRESULT CTrayWnd::OnTrayNotify(UINT wParam, LONG lParam) { UINT uiIconID = (UINT)wParam; UINT uiMouseMsg = (UINT)lParam; if(ID_ICON != uiIconID) { return 0; } // ここで模造メッセージをポストする理由 : // この通知関数からは、できるだけ早く抜ける必要がある // 例えば、OnLButtonDownでOLEコントロールを作成する場合、エラーコード"RPC_E_CANTCALLOUT_ININPUTSYNCCALL"が送出される // このエラーは、WinError.hによると、"ソフトウェアが入力同期呼び出しをディスパッチしているため、発信呼び出しはできない" switch(uiMouseMsg) { case WM_LBUTTONDOWN: m_bFireDoubleClick = FALSE; SetTimer( ID_CLICKTIMER, GetDoubleClickTime(), NULL ); break; case WM_LBUTTONUP: if(m_bFireDoubleClick) { PostMessage(WM_LBUTTONDBLCLK); } break; case WM_LBUTTONDBLCLK: m_bFireDoubleClick = TRUE; KillTimer(ID_CLICKTIMER); break; case WM_RBUTTONUP: PostMessage(WM_RBUTTONUP); break; } return 0; } </syntaxhighlight> <br> TrayWnd.cppファイルに、ID_CLICKTIMERの定義を記述する。<br> CTrayWndクラスのコンストラクタに、メンバ変数m_bFireDoubleClickの初期化処理を記述する。<br> <br> また、CTrayWndクラスに、<code>WM_TIMER</code>、<code>WM_LBUTTONUP</code>、<code>WM_RBUTTONUP</code>、<code>WM_LBUTTONDBLCLK</code>メッセージに対応するイベントハンドラを記述する。<br> <syntaxhighlight lang="c++"> // TrayWnd.cpp #include "stdafx.h" #include "MyApplication.h" #include "TrayWnd.h" #define ID_ICON 100 #define WM_USER_TRAYNOTIFYICON WM_APP + 100 #define ID_CLICKTIMER 4 IMPLEMENT_DYNAMIC(CTrayWnd, CWnd) ON_MESSAGE(WM_USER_TRAYNOTIFYICON, OnTrayNotify) // ... 略 BEGIN_MESSAGE_MAP(CTrayWnd, CWnd) ON_MESSAGE(WM_USER_TRAYNOTIFYICON, OnTrayNotify) END_MESSAGE_MAP() // ...略 CTrayWnd::CTrayWnd() : m_hIcon_current(NULL), m_bFireDoubleClick(false) { } // ...略 void CTrayWnd::OnTimer(UINT_PTR nIDEvent) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 if(ID_CLICKTIMER == nIDEvent) { KillTimer(nIDEvent); ::PostMessage(WM_LBUTTONUP); } // CWnd::OnTimer(nIDEvent); } void CTrayWnd::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 LButtonClick(); // CWnd::OnLButtonUp(nFlags, point); } void CTrayWnd::OnRButtonUp(UINT nFlags, CPoint point) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 RButtonClick(); // CWnd::OnRButtonUp(nFlags, point); } void CTrayWnd::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 LButtonDoubleClick(); // CWnd::OnLButtonDblClk(nFlags, point); } void CTrayWnd::LButtonClick() { POINT pt; GetCursorPos( &pt ); CMenu menu; menu.LoadMenu(IDM_TRAY_L); CMenu *pPopup = menu.GetSubMenu(0); // SetForgroundWindowとPostMessageが必要な理由は、Knowledge Base (Q135788)参照のこと SetForegroundWindow(); pPopup->TrackPopupMenu( TPM_RIGHTBUTTON, pt.x, pt.y, this ); ::PostMessage(WM_NULL); } void CTrayWnd::RButtonClick() { POINT pt = {0}; GetCursorPos(&pt); CMenu menu; menu.LoadMenu(IDM_TRAY_R); CMenu *pPopup = menu.GetSubMenu(0); // SetForgroundWindowとPostMessageが必要な理由は、Knowledge Base (Q135788)参照のこと SetForegroundWindow(); pPopup->TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this); ::PostMessage(WM_NULL); } void CTrayWnd::LButtonDoubleClick() { ::SendMessage(WM_COMMAND, ID_APP_ABOUT); // または CAboutDlg dlg; dlg.DoModal(); } </syntaxhighlight> <br> TrayWnd.hファイルに、メンバ変数m_bFireDoubleClickおよびOnTrayNotifyメソッドの宣言を記述する。<br> <syntaxhighlight lang="c++"> // TrayWnd.h #pragma once class CTrayWnd : public CWnd { private: HICON m_hIcon_current; BOOL m_bFireDoubleClick; protected: virtual void LButtonClick(); virtual void RButtonClick(); virtual void LButtonDoubleClick(); public: BOOL Create(); BOOL NotifyIcon(DWORD dwMessage, HICON hIcon, LPCTSTR pszTip = NULL); BOOL NotifyIcon(DWORD dwMessage, HICON hIcon, UINT nStringResource); DECLARE_DYNAMIC(CTrayWnd) public: CTrayWnd(); virtual ~CTrayWnd(); protected: DECLARE_MESSAGE_MAP() virtual void PostNcDestroy(); afx_msg LRESULT OnTrayNotify(UINT wParam, LONG lParam); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); }; </syntaxhighlight> <br> ==== ウィンドウの作成および破棄におけるアイコンの登録・削除 ==== CTrayWndクラスのコンストラクタに、メンバ変数m_hIcon_mainの初期化処理を記述する。<br> CTrayWndクラスに、<code>WM_CREATE</code>、<code>WM_DESTROY</code>メッセージに対応するイベントハンドラを記述する。<br> <syntaxhighlight lang="c++"> // TrayWnd.cpp #include "stdafx.h" #include "MyApplication.h" #include "TrayWnd.h" #include "AboutDlg.h" IMPLEMENT_DYNAMIC(CMyApplicationTrayWnd, CTrayWnd) CTrayWnd::CTrayWnd() : m_hIcon_main(NULL) { // ...略 } // ...略 int CTrayWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CWnd::OnCreate(lpCreateStruct) == -1) { return -1; } // TODO: ここに特定な作成コードを追加してください。 m_hIcon_main = AfxGetApp()->LoadIcon(IDR_MAINFRAME); NotifyIcon(NIM_ADD, m_hIcon_main, _T("MyApplication")); return 0; } void CTrayWnd::OnDestroy() { CWnd::OnDestroy(); // TODO: ここにメッセージ ハンドラ コードを追加します。 NotifyIcon( NIM_DELETE, NULL ); } </syntaxhighlight> <br> TrayWnd.hファイルに、メンバ変数m_hIcon_mainの宣言を記述する。<br> <syntaxhighlight lang="c++"> // TrayWnd.h #pragma once class CTrayWnd : public CWnd { private: HICON m_hIcon_main; protected: void LButtonClick(); void RButtonClick(); void LButtonDoubleClick(); DECLARE_DYNAMIC(CTrayWnd) // ...略 } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:MFC]]
MFCの基礎 - 常駐ソフトウェア
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse