MASATOの開発日記


前の開発日記 次の開発日記 一覧

2003/03/08

最近もAge of Mythologyというゲームにはまりまくりです。 いつになったら抜け出せることやら・・・

最小化したときタスクトレイに潜む方法

環境Visual C++.NET
言語C++

本日紹介するのは、MFCアプリケーションに「最小化時タスクトレイに格納する」機能を付けようと思ったとき、 どのようにすれば良いかというノウハウ的なものです。 「タスクトレイにアイコンを表示する方法は?」というようなポイント的なものではありません。 この機能を実装するためには、MFCアプリケーションのスケルトンコードのあちこちに 色々なコードを埋め込む必要がありますので、どこにどんなことをするコードを埋め込むのかというやり方の紹介です。

最小化時タスクトレイに格納するだけではあまり面白くないので、 アプリケーションには以下の3つのオプションがあるとします。

実際には、上のオプションのどれかは常に真ということもありえるでしょう。 そういうときは以下のコードは適時最適化して下さい。

いまさらですが、対象はMFCのSDIアプリケーションということにします。MDIでもたぶん同じでしょう。 処理を行うタイミングは、以下の3点です。

まずは起動時の処理です。CxxxApp::InitInstanceに以下のコードを埋め込みます。

if (MINIMIZE_START){
  m_nCmdShow = SW_HIDE;
}

// 以下はMFCが作成したコード
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
// 中略
m_pMainWnd->ShowWindow(MINIMIZE_START ? SW_MINIMIZE : SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;

つまりはpDocTemplateを定義している前にちょこちょこコードを埋め込み、 最後でShowWindowしているところをちょこちょこ変えよう、ということです。

お次は、ウィンドウサイズ変更時の処理と行きたいところですが、 実はオプション変更時とウィンドウサイズ変更時の処理は同じ物にできるので、 オプション変更時の処理から説明します。
まずはダミーのメニューリソースを作成し、ID_UPDATE_OPTIONというIDを持ったメニュー項目を追加します。 わざわざダミーのメニューリソースを作成する意味は、以下で説明します。
次に、オプション変更時に以下のコードを実行します。

AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(ID_UPDATE_OPTION, 0), NULL);

何時オプションが変更されるのかはアプリケーションによって異なります。 例えば、オプション変更ダイアログのメンバ関数DoModalを呼んだ結果、IDOKが返ってきたときです。

次に、CMainFrameに、ID_UPDATE_OPTIONのコマンドハンドラを記述します。 恐らくOnUpdateOptionという名前のメンバ関数になるでしょう。
上記したように、ダミーのメニューリソースを作ると、このID_UPDATE_OPTIONのコマンドハンドラが VisualStudioの機能を使って簡単に追加できるはずです。 リソースシンボルやON_COMMANDマクロを自分で編集しても同じことが出来ますが、 やっぱり統合開発環境の支援はありがたいものです。
また、CMainFrameの関数を直接呼ぶのではなく、こうしてSendMessageでコマンドを送信している理由は、 MainFrm.hをインクルードしたくなかった、つまりはCMainFrameと他のクラスの関連性を増やしたくなかったからです。

そして、OnUpdateOptionに以下のようなコードを追加します。

void CMainFrame::OnUpdateOption()
{
  BOOL usetrayicon = ALWAYS_TASK_TRAY
    || (IsIconic() && STORE_TASK_TRAY);
  if (usetrayicon && トレイアイコンが表示されていない){
    トレイアイコンを表示する
  }else if (!usetrayicon && トレイアイコンが表示されている){
    トレイアイコンを削除する
  }

  BOOL storetasktray = STORE_TASK_TRAY;
  if (IsIconic() && storetasktray){
    ShowWindow(SW_HIDE);
  }else if (!IsWindowVisible() && !storetasktray){
    ShowWindow(SW_MINIMIZE);
  }
}

トレイアイコンの表示方法は、検索サイトでShell_NotifyIconをキーワードに検索すれば ごそっと出てくるのでどれかを参考にして下さい。

最後に、ウィンドウサイズ変更時の処理です。CMainFrameにWM_SIZEのハンドラを追加します。 OnSizeという名前のメンバ関数になるはずです。そこに以下のコードを記述します。

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
  __super::OnSize(nType, cx, cy);

  if (nType == SIZE_MINIMIZED || nType == SIZE_RESTORED){
    OnUpdateOption();
  }
}

あとはおまけとしてWM_DESTROYのハンドラでタスクトレイのアイコンを削除しておきましょう。

void CMainFrame::OnDestroy()
{
  if (トレイアイコンが表示されている){
    トレイアイコンを削除する
  }

  __super::OnDestroy();
}

以上で完了です!後はトレイアイコンの表示及び削除の部分を実装すればOKです。

前の開発日記 次の開発日記 一覧