update 2003.11.30 第5回

YS6 EXP Viewerの制作過程


第5回 タスクアイコン常駐アプリケーション
とりあえず詳細説明は無しです(汗
私自信が解説するほど有意義に使いこなせてませんので…。

あと、前も説明したように今回紹介してる手法はあまりオススメできません。
説明しやすい&とても容易に実装できるため用いてるだけであって、
完璧なものではないので注意してください。

今回の解説に使ったサンプルのソースコード一式のダウンロード

ダイアログベースでダイアログを非表示
とりあえずMFCダイアログベースアプリケーションで作成します。
メイン処理のC++ソースコード(xxxxDLG.CPP)を開き、C****Dlg::OnPaint()メンバ関数を探し、
この関数内のコードを全部コメントアウト(もしくは削除)した後、以下のコードを追加します。
	ShowWindow(SW_HIDE);
	return;
ShowWindow()関数にSW_HIDEを渡すことでウインドウ非表示にしています。
とりあえずこれでダイアログを表示しないダイアログベースプログラムになりました。

タスクアイコン常駐
メイン処理のC++ソースコード内から以下の個所を探します。
BOOL CxxxxDlg::OnInitDialog()
ダイアログイニシャライズのメンバ関数ですが、ここの下の方に
	// TODO: 特別な初期化を行う時はこの場所に追加してください。
こんなコメントがありますので、この下に以下のコードを追加します。
	NOTIFYICONDATA notif;
	char cToolTipMsg[] = "SAMPLE";

	notif.cbSize = sizeof(NOTIFYICONDATA);
	notif.hIcon = m_hIcon;
	notif.hWnd = m_hWnd;
	strcpy(notif.szTip, cToolTipMsg);
	notif.uCallbackMessage = WM_USER+1;
	notif.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	notif.uID = 0;
	Shell_NotifyIcon(NIM_ADD, &notif);
これで起動と同時にタスクアイコンが生成され、WM_USER+1でタスクアイコンのメッセージを
得ることが出来るようになります。

メッセージ処理
タスクアイコンを表示するだけではそれ以外に何もできないので、
その上でクリックもしくは右クリックを行うとメッセージが出るようにしてみます。
続いてClassWizardを開き、オブジェクトID[CxxxxDlg](ダイアログ処理)のメッセージ
DefWindowProcをメンバ関数に追加します。
これでプログラム中のメッセージを参照して処理を行うことが可能になりましたので、
この関数内に以下のコードを記述します。
	if(message==WM_USER+1){
		if(lParam==WM_LBUTTONDOWN || lParam==WM_RBUTTONDOWN){
			MessageBox("メッセージがでます。",NULL,MB_OK);
		}
	}
これで、タスクアイコンをクリックするたびにメッセージボックスが出ます。
YS6EXPVではここでIDC_MENU1として予め定義しておいたメニュー情報をロードして、
TrackPopupMenuで終了メニューが出るようにしています。

終了処理
以上でタスクアイコンを使ったイベント処理が可能になりましたが、
「ダイアログが消えてて終了できない」
「無理やり落とすとタスクアイコンが残ったまま」
といった問題が残ったままだったりします。

まず、このタスクアイコンに終了もしくはダイアログ再描画機能を持たせることで、
プログラムを終わらせるように流れを作ればOKです。
ま、終了を前提としてないこれまでのサンプルが出来が悪いだけですが…(--;;;

そしてタスクアイコンが残ったままなのは「ちゃんと消してないから」です。
Windows2000だとメモリ開放がそこそこ上手なので大丈夫ですが、9x系統だと
タスクアイコン残したまま終了しちゃったりするのはあまりよろしくない気がします。
というわけで、ClassWizardでDestroyWindow()メンバ関数を追加し、
以下のコードを追加します。
	NOTIFYICONDATA notif;
	notif.cbSize = sizeof(NOTIFYICONDATA);
	notif.hWnd = m_hWnd;
	notif.uFlags = 0;
	notif.uID = 0;
	Shell_NotifyIcon(NIM_DELETE, &notif);
	CWnd::PostNcDestroy();	
	return CDialog::DestroyWindow();
あとは、先ほどのタスクアイコンをクリックした際の処理を EndDialog(TRUE); に変えて、
プログラムが終了するようにすれば完了です。

以上で
非常にツッコミどころ満載のタスクアイコンを扱うプログラムの作成方法ですが、
このベースにプロセス検索→情報取得→タイトルバー書き換えの処理を追加すれば、
それはそのままYS6EXPVと同じような動作を行うことができます。
まあ、そのものとも言えるんですが…(汗

以上でYS6 EXP Viewerの制作過程の解説は終了です。
本当はソースコードそのものを公開して完全版を解説してもいいのですが、
あまりにもスパゲッティソースな上、ハンガリー記法もちゃんと守れてません。
とても恥ずかしすぎて人には見せれません…(T-T

いつか時間ができて、作り直せたら公開するかもしれませんが…